1 創建測試目錄和文件
[root@docker-a ~]# mkdir lee
[root@docker-a ~]# cd lee/
[root@docker-a lee]# touch docker-compose.yml # 容器編排工具Docker Compose 默認識別docker-compose.yml文件
2 編寫docker-compose.yml文件和haproxy.cfg文件
2.1 核心配置說明
2.1.1 服務結構
- 共定義 3 個服務:
web1
、web2
(Nginx 網頁服務)和?haproxy
(負載均衡服務) - 形成 "負載均衡器 + 兩個后端服務" 的經典架構,通過 Haproxy 分發請求到 web1 和 web2
2.1.2 網絡通信
mynet1
?是核心通信網絡,三個服務都加入此網絡,確保 Haproxy 能訪問后端 Nginx- 容器間可通過容器名(如
web1
、web2
)直接通信(Docker 內置 DNS 解析) mynet2
?為預留網絡,可用于后續擴展其他服務(如添加數據庫時使用)
2.1.3 數據持久化
- Nginx 的網頁內容通過
volumes
掛載到宿主機,實現:- 宿主機直接修改網頁內容(無需進入容器)
- 容器重建后數據不丟失(內容保存在宿主機)
2.1.4 端口策略
- Nginx 容器使用
expose: 80
:僅在內部網絡暴露端口,外部無法直接訪問(增強安全性) - Haproxy 使用
ports: 80:80
:將宿主機 80 端口開放,作為外部訪問的唯一入口
2.1.5 重啟策略
restart: always
?確保服務在意外退出或服務器重啟后自動恢復,提高可用性
2.2 工作流程
- 外部用戶訪問宿主機的 80 端口(如
http://192.168.36.101
) - 請求通過端口映射進入 Haproxy 容器的 80 端口
- Haproxy 根據
haproxy.cfg
中的配置(如輪詢策略),將請求轉發到web1:80
或web2:80
- Nginx 容器處理請求,返回
/usr/share/nginx/html
目錄下的index.html
內容(來自宿主機掛載的目錄)
2.3 編寫docker-compose.yml文件
[root@docker-a lee]# vim docker-compose.yml
services:# 第一個Nginx服務容器(web1)web1:# 使用的基礎鏡像:最新版Nginximage: nginx:latest# 容器的自定義名稱(便于識別和操作)container_name: web1# 重啟策略:總是重啟(容器退出時自動重啟,包括系統啟動時)restart: always# 加入的網絡(與Haproxy共享mynet1網絡實現通信)networks:- mynet1# 暴露容器內部端口(僅在容器所在網絡內可見,外部無法直接訪問)expose:- 80 # Nginx默認監聽的端口# 數據卷掛載(將宿主機目錄與容器內目錄關聯,實現文件共享和持久化)volumes:# 宿主機目錄:/docker/web/html1 映射到容器內Nginx的默認網頁目錄# 這樣修改宿主機的/html1目錄內容,容器內會實時同步- /docker/web/html1:/usr/share/nginx/html# 第二個Nginx服務容器(web2),與web1配置類似,用于提供不同內容實現負載均衡效果web2:image: nginx:latestcontainer_name: web2restart: alwaysnetworks:- mynet1 # 同樣加入mynet1網絡,確保Haproxy能訪問expose:- 80volumes:# 與web1使用不同的宿主機目錄,以便存放不同的網頁內容- /docker/web/html2:/usr/share/nginx/html# Haproxy負載均衡服務,用于分發請求到web1和web2haproxy:# 使用2.3版本的Haproxy鏡像(需與配置文件兼容)image: haproxy:2.3container_name: haproxyrestart: always# 加入兩個網絡:# - mynet1:用于與web1、web2通信,獲取后端服務# - mynet2:可用于連接其他服務(當前配置中未使用,預留擴展)networks:- mynet1- mynet2# 掛載Haproxy配置文件:宿主機的haproxy.cfg映射到容器內的默認配置路徑# 注意:不同版本Haproxy的默認配置路徑可能不同,2.3版本路徑為/usr/local/etc/haproxy/volumes:- /docker/conf/haproxy/haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg# 端口映射:將宿主機的80端口映射到容器內的80端口# 外部訪問宿主機80端口時,請求會轉發到Haproxy容器的80端口ports:- 80:80# 定義網絡配置
networks:# 第一個網絡:供web1、web2和haproxy內部通信mynet1:# 使用bridge驅動(Docker默認的網絡驅動,創建獨立的網絡命名空間)driver: bridge# 第二個網絡:預留網絡,可用于擴展其他服務(如數據庫、緩存等)mynet2:driver: bridge
2.3.1 啟動配置文件
[root@docker-a lee]# docker compose up -d
2.4 編寫haproxy.cfg文件
[root@docker-a lee]# vim /docker/conf/haproxy/haproxy.cfg
[root@docker-a lee]# cat /docker/conf/haproxy/haproxy.cfg
#---------------------------------------------------------------------
# Example configuration for a possible web application. See the
# full configuration options online.
#
# https://www.haproxy.org/download/1.8/doc/configuration.txt
#
#---------------------------------------------------------------------#---------------------------------------------------------------------
# Global settings
#---------------------------------------------------------------------
global# to have these messages end up in /var/log/haproxy.log you will# need to:## 1) configure syslog to accept network log events. This is done# by adding the '-r' option to the SYSLOGD_OPTIONS in# /etc/sysconfig/syslog## 2) configure local2 events to go to the /var/log/haproxy.log# file. A line like the following can be added to# /etc/sysconfig/syslog## local2.* /var/log/haproxy.log#log 127.0.0.1 local2chroot /var/lib/haproxypidfile /var/run/haproxy.pidmaxconn 4000user haproxygroup haproxydaemon# turn on stats unix socketstats socket /var/lib/haproxy/stats# utilize system-wide crypto-policiesssl-default-bind-ciphers PROFILE=SYSTEMssl-default-server-ciphers PROFILE=SYSTEM#---------------------------------------------------------------------
# common defaults that all the 'listen' and 'backend' sections will
# use if not designated in their block
#---------------------------------------------------------------------
defaultsmode httplog globaloption httplogoption dontlognulloption http-server-closeoption forwardfor except 127.0.0.0/8option redispatchretries 3timeout http-request 10stimeout queue 1mtimeout connect 10stimeout client 1mtimeout server 1mtimeout http-keep-alive 10stimeout check 10smaxconn 3000listen webcluster # 定義一個名為webcluster的監聽集群bind *:80 # 監聽所有網絡接口的80端口(接收外部HTTP請求)mode http # 工作模式為HTTP(專門處理HTTP協議)balance roundrobin # 負載均衡算法:輪詢(依次分發請求到后端服務器)# 定義后端服務器1:web1容器的80端口server server1 web1:80 check inter 2 rise 3# 定義后端服務器2:web2容器的80端口server server2 web2:80 check inter 2 rise 3
[root@docker-a lee]#
2.4.1 寫入測試內容
[root@docker-a lee]# echo web1 > /docker/web/html1/index.html
[root@docker-a lee]# echo web2 > /docker/web/html2/index.html
[root@docker-a lee]# cat /docker/web/html1/index.html
web1
[root@docker-a lee]# cat /docker/web/html2/index.html
web2
[root@docker-a lee]#
2.4.2?重啟所有容器
[root@docker-a lee]# docker compose down
[root@docker-a lee]# docker compose up -d
[root@docker-a lee]# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
e201c44d759b haproxy:2.3 "docker-entrypoint.s…" 10 seconds ago Up 9 seconds 0.0.0.0:80->80/tcp, [::]:80->80/tcp haproxy
c16240d3589d nginx:latest "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 80/tcp web2
7c474eee1643 nginx:latest "/docker-entrypoint.…" 10 seconds ago Up 9 seconds 80/tcp web1
3 測試效果
[root@docker-a lee]# curl 192.168.36.101
web1
[root@docker-a lee]# curl 192.168.36.101
web2
[root@docker-a lee]# curl 192.168.36.101
web1
[root@docker-a lee]# curl 192.168.36.101
web2
通過此配置,可以實現簡單的負載均衡和高可用架構,適合作為 Web 服務的基礎部署方案。