基于云服务器的多 Docker 实例网关配置,助力个人主页部署

 

本文讲解如何在一台云服务器上,使用 Docker 与 Nginx 的配合,实现多个应用使用一个ip和域名访问的功能。更具体一点就是个人备案主页(webApp)的部署。

背景

作为技术人,经常需要在云服务器上部署自己开发的小demo让别人使用,而出于经济原因,基本上只能买一台云服务器。而一台云服务器下要运行多个应用,然后一个域名访问,那么最合适的技术选型就是 Docker + nginx .

那么下面就根据我的个人在腾讯云服务器(Debian)上面部署个人备案主页(webApp)的流程看是如何部署 Docker + Nginx , 实现 Nginx 网关指向多实例的。

部署流程

安装 Docker

Debian 上面安装 Docker 比较简单,按照下面的命令行一个一个执行就好。

# 更新 apt 包索引
sudo apt-get update
# 安装 ca-certificates 和 curl 包。ca-certificates:用于处理 SSL/TLS 证书,确保与 HTTPS 站点的通信是安全的。
sudo apt-get install ca-certificates curl -y
# 创建 /etc/apt/keyrings 目录,并设置权限为 0755(所有者可读、可写、可执行,其他用户可读、可执行)。这个目录用于存放 apt 软件源的密钥文件。
sudo install -m 0755 -d /etc/apt/keyrings
# 从腾讯云的 Docker 镜像源下载 GPG 密钥,并将其存储在 /etc/apt/keyrings/docker.asc 文件中。
sudo curl -fsSL https://mirrors.cloud.tencent.com/docker-ce/linux/debian/gpg -o /etc/apt/keyrings/docker.asc
# 为 /etc/apt/keyrings/docker.asc 文件添加“所有用户可读”权限。
sudo chmod a+r /etc/apt/keyrings/docker.asc
# 为 Docker 添加腾讯云镜像源。
echo   "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.cloud.tencent.com/docker-ce/linux/debian/ \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" |   sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# 再次更新 apt 包索引。这次会更新并包含刚添加的 Docker 镜像源,以便后续可以从该源安装 Docker。
sudo apt-get update
# 安装 Docker
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
# 运行 Docker
systemctl start docker
## 执行以下命令,检查安装结果
docker info

部署web应用与使用 Nginx 反向代理

首先我们先要理解整个网络的全景图

Docker多实例网络全景图

我们需要先了解 Docker 的网络模式

  • bridge 网络:可以将多个容器加入到同一个 bridge 网络中,然后使用反向代理将流量引导到对应的容器。

  • host 网络:如果需要让容器共享宿主机的 IP,可以使用 –network host 选项,这样容器会直接使用宿主机的网络栈。要注意的是,host 网络模式适合少量服务共享,不适合大规模容器化应用。

  • 自定义网络 + DNS 配置:可以创建一个自定义的 Docker 网络,并指定各个服务的别名。这样,通过自定义 DNS 或使用反向代理可以方便地将不同路径路由到不同服务上。

由于我们需要在 Nginx 实例里面使用容器名可以充当容器的“主机名”,简化了容器间的通信和网络管理。而不是每一次启动 Docker 应用实例,都需要重新修改 Nginx 配置文件,重新运行。因此我们需要先新建一个 Docker 自定义网络。

docker network create custom_network
# 查看 docker 已有网络
docker network ls

然后我们运行应用镜像并加入到自定义网络中

# 这里使用我的个人备案主页web应用来示范
## 需要先登录腾讯云镜像服务
docker login https://ccr.ccs.tencentyun.com
## 拉取镜像
sudo docker pull ccr.ccs.tencentyun.com/abben/beian-web-app:0.0.2
## 运行应用镜像并加入到自定义网络中
docker run -d --name beian-web-app --network custom_network -p 8001:80 ccr.ccs.tencentyun.com/abben/beian-web-app:0.0.2

最后我们需要创建一个 Nginx 配置文件 nginx.conf ,配置 Nginx 作为反向代理,根据请求路径或子域名将请求路由到不同的应用容器。

mkdir -p /etc/docker-nginx && touch /etc/docker-nginx/nginx.conf
events {
  worker_connections 1024;
}

http {
    upstream beian-web-app {
        server beian-web-app:80;
    }

    # 若有第二个应用,那就定义第二个应用
    # upstream app2_backend {
    #     server app2:80;
    # }

    server {
        listen 80;
        server_name  _;

        # 路由 / 到 beian-web-app 容器实例
        location / {
            proxy_pass http://beian-web-app;
            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_set_header X-Forwarded-Proto $scheme;
        }

        # 路由 /app2 到 app2 容器实例
        #location /app2/ {
        #    proxy_pass http://app2_backend;
        #    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_set_header X-Forwarded-Proto $scheme;
        #}
    }

    # 路由子域名 demo 到 app3 容器实例
    #server {
    #    listen 80;
    #    server_name demo.abbenyyyyyy.cn;
    #
    #    location / {
    #        proxy_pass http://app3:80;
    #        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_set_header X-Forwarded-Proto $scheme;
    #    }
    #}
}

然后运行 Nginx 容器并加载配置成为网关

docker pull nginx:stable-alpine3.19
docker run -d --name nginx_proxy  --network custom_network -p 80:80 -v /etc/docker-nginx/nginx.conf:/etc/nginx/nginx.conf nginx:stable-alpine3.19

最后可以直接访问服务器ip就是部署的web应用了。后续如果需要增加新的应用,直接启动新应用实例加入到自定义网络,例如

docker run -d --name app2 --network custom_network my_app_image2

再修改挂载在宿主机上的 nginx.conf 文件,配置正确路由,然后再重新加载配置就可以正确反向代理到新应用实例了。

# 
vim /etc/docker-nginx/nginx.conf
# 重新加载 Nginx 配置
docker exec -it nginx_proxy nginx -s reload

总结

本文从一次云服务器的 Docker 应用部署实践,让阅读者了解到一个宿主机上多个 Docker 实例如何使用 Nginx 反向代理正确访问的,当然还有很多复杂的场景待补充,如应用之间如何通讯等,这些有待后续讲解,希望本文对大家有所启发,感谢阅读。