Docker+Nginx负载均衡

使用手工commit的方式创建了一个基于CentOS的Nginx容器,并且可以通过外部访问到。入手docker compose——Docker容器编排的工具,可以配置并启动多个容器,适合复杂业务场景。本篇是铺垫nginx负载均衡的步骤记录。

手工搭建CentOS+Nginx容器

docker pull centos
在centos镜像基础上创建一个临时容器tmp,执行命令 docker run -it --privileged --name tmp centos /usr/sbin/init后如下图。保持不动,新开窗口进行后续操作。

进入容器 docker exec -it tmp /bin/bash
升级包 rpm -Uvh http://nginx.org/packages/centos/7/noarch/RPMS/nginx-release-centos-7-0.el7.ngx.noarch.rpm
默认安装 yum install nginx -y
 安装完成之后,nginx配置文件默认路径为 /etc/nginx/nginx.conf ,是全局配置文件。
启动nginx systemctl start nginx
设置开机自启动 systemctl enable nginx 启动成功我们可以使用 curl http://localhost 验证,正常的话,我们会看到Welcome to nginx之类的HTML源码。
接下来我们要把容器作为镜像保存起来,使用commit命令。
利用dockerfile里面的格式去创建新镜像 docker commit -c 'CMD ["/usr/sbin/init"] ' -c "EXPOSE 80" tmp centos:nginx
基于这个镜像创建新容器,因为docker非持久化,把配置文件映射到本地主机。使用cp命令。
docker cp tmp:/etc/nginx/nginx.conf /home/xugz/nginx/conf/
此时可以停止并删除临时容器tmp。
启动Nginx镜像 指定端口9090,nginx.conf文件同步 docker run --name mynginx --privileged -p 9090:80 -v /home/xugz/nginx/conf/nginx.conf:/etc/nginx/nginx.conf -d centos:nginx。启动成功后,使用虚拟机IP:9090在本地浏览器可以访问。

cp命令参考地址
commit命令参考地址

模拟创建多个web网站

本地新建文件/home/xugz/nginx/web1/index.html和/home/xugz/nginx/web2/index.html。两个HTML页面内容不一致。
基于本地已有镜像centos:httpd启动两个容器

1
2
docker run --name web1 -d -p 8080:80 --privileged -v /home/xugz/nginx/web1/:/var/www/html/ centos:httpd
docker run --name web1 -d -p 8081:80 --privileged -v /home/xugz/nginx/web1/:/var/www/html/ centos:httpd

要停止删除也要执行两条语句 docker stop web1 && docker rm web1docker stop web2 && docker rm web2
很明显,这样很麻烦,我们可以用compose来进行统一管理。

compose

下载安装
根据官方文档引导,首先下载Docker Compose的当前稳定版本
sudo curl -L "https://github.com/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose
 如果根本下载不动,也可以更换下载地址,使用命令
sudo curl -L "https://get.daocloud.io/docker/compose/releases/download/1.24.1/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

完成后授予文件可执行权限 sudo chmod +x /usr/local/bin/docker-compose
使用 docker-compose --version 查看版本

启动
为项目创建一个目录,这里我们基于的是原来创建的镜像

1
2
mkdir composetest
cd composetest

创建docker-compose.yml 文件,拷贝如下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
services:  # 任务
web1: # 自定义
container_name: web1 # 容器名称
image: "centos:httpd" # 这个容器基于的镜像
ports:
- "8080:80"
privileged: true #给容器加特权
volumes:
- "/home/xugz/nginx/web1/:/var/www/html/" #映射文件
web2:
container_name: web2
image: "centos:httpd"
ports:
- "8081:80"
privileged: true
volumes:
- "/home/xugz/nginx/web2/:/var/www/html/"
version: "3"

保存退出,在文件所在目录执行docker-compose up -d启动。
停止容器使用命令 docker-compose stop web1 删除容器使用命令 docker-compose rm
当然我们也可以连带Nginx一起启动操作,只需要在docker-compose.yml文件中services增加如下内容

1
2
3
4
5
6
7
8
nginx: 
container_name: mynginx
image: "centos:nginx"
ports:
- "9090:80"
privileged: true
volumes:
- "/home/xugz/nginx/conf/nginx.conf:/etc/nginx/nginx.conf"

yaml在线检查工具
compose官方参考文档

network

网络列表 docker network ls
查看详细信息 docker network inspect <network name>
容器之前可以使用IP进行互通,实验如图

手动配置

现在我们新建网络 mynginx 然后让上文中涉及的三个容器都加入我们新建的网络里
停止原有三个容器 使用命令 docker-compose stop
创建网络 指定子网为192.168.0.0 docker network create -d bridge --subnet=192.168.0.0/16 mynginx
在docker-compose.yml文件中新增如下内容

1
2
3
4
5
6
7
8
9
10
version: "3"
services:
web:
……
networks:
- "mynginx-net" # 和networks中网络名称一致
networks:
mynginx-net: # 可自定义
external:
name: "mynginx"

启动三个容器 使用命令docker-compose start就可以了。也可以进入容器验证查看

子网掩码的计算地址
network官方参考文档
网络配置参考(version 3)

compose up 时自动创建网络

参考文档
修改docker-compose.yml文件,示例如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
version: "3"
services:
app:
image: centos:nginx
container_name: mynginx
networks:
mynginx-net:
ipv4_address: 192.158.0.2

networks:
mynginx-net:
driver: bridge
ipam:
config:
- subnet: 192.158.0.0/24

保存后使用命令docker-compose up -d 启动,会自动生成名称为 mycompose_mynginx-net 的网络。

env_file

如果设置比较复杂,那么我们可以通过env_file来完成变量的引用
在docker-compose.yml文件同目录内新建 .env 文件,里面输入变量,格式为 xugz=192.158.0.7。在docker-compose.yml文件中直接使用 ${xugz}引用即可。

env_file参数参考文档

简单的Nginx负载均衡设置

修改本地nginx配置文件,当然你要确保你本地的文件已经和docker容器中的实时同步。
注释掉 include /etc/nginx/conf.d/*.conf; 这行,删除原来关于server配置,增加如下内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
upstream mydocker {
server 192.158.0.7; # web1 的ip地址 可以通过 docker network inspect mycompose_mynginx-net 查看到
server 192.158.0.3; # web2 的ip地址
}
server {
listen 80; # 默认80端口
server_name mydocker;
location / { # 访问根目录 默认跳转到http://mydocker,就是我们配置的 upstream mydocker
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_buffering off;
proxy_pass http://mydocker;
}
}

保存退出后回到docker-compose.yml文件所在目录,使用 docker-compose restart nginx 重启Nginx。访问 http://192.168.2.156:9090/ 会轮流跳转到web1或web2。

容器健康检查机制

参数如下:
–health-cmd: 检查的命令
–health-interval:两次健康检查的间隔
–health-timeout:健康检查命令运行超时时间,超过代表失败
–health-retries:当连续失败指定次数后,则将容器状态视为 unhealthy
–health-start-period:容器启动的初始化时间,此时健康检查失效不会计入次数

运行web1容器同时进行检查80端口是否正常,每三秒检查一次,当连续失败3次后提示,健康检查命令超5秒也代表失败。示例命令如下

1
2
3
4
docker run  --name web1 -d -p 8080:80 --privileged -v /home/xugz/nginx/web1/:/var/www/html/ \
--health-cmd="curl --silent --fail http://localhost:80/ || exit 1" --health-interval=3s --health-retries=3 \
--health-timeout=5s \
centos:httpd
参数说明 :
 \ 换行使用
 --silent --fail 出现错误的时候不进行输出
 exit 1 非正常退出
 || 表示 左边执行为false才会执行右边 && 为左边执行为true才会执行右边

此时,可以使用 docker inspect web1 命令检查容器
只看Health部分使用命令 docker inspect --format='' web1

使用Compose进行健康检查
docker-compose.yml文件对应容器中添加如下示例配置即可

1
2
3
4
5
healthcheck:
test: ["CMD", "curl", "-f", "http://localhost:80"]
interval: 3s
timeout: 10s
retries: 3

healthcheck参考文档

本文标题:Docker+Nginx负载均衡

文章作者:xugz

发布时间:2019年11月25日 - 13:33

最后更新:2021年09月11日 - 16:19

原始链接:https://xlline.github.io/2019/11/25/Docker-Nginx%E8%B4%9F%E8%BD%BD%E5%9D%87%E8%A1%A1/

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。