在 1Panel 上利用 Docker Swarm 实现负载均衡
Docker Swarm的概念我们就不再赘述了,这里有详细的解释。其机制类似Kubernetes(当下流行的容器编排系统),但是Swarm会更加简单易用,更适合小型项目的部署。
本文我将介绍一下如何在1Panel上利用Docker Swarm实现服务负载均衡。
前提
服务是无状态的
主服务器已经安装1Panel
了解过Docker Compose
以下步骤均不支持Podman
为了简单起见,本文不涉及多节点的搭建过程。
启用Swarm模式
如果我们想要使用Swarm模式,则需要在当前服务器上执行以下命令启用:
❯ docker swarm init
Swarm initialized: current node (ygyleqoqkt185xl2l4zczvzdm) is now a manager.
To add a worker to this swarm, run the following command:
docker swarm join --token SWMTKN-1-5r3y44czszyyy25650hfnwtuplhar92kz9wx1ihwbh-4k8rdxxxvv2cismvw7 192.168.233.191:2377
To add a manager to this swarm, run 'docker swarm join-token manager' and follow the instructions.
这意味着当前节点已经成为了Swarm模式中的管理节点,我们可以执行以下命令获取当前节点信息:
❯ docker node ls
ID HOSTNAME STATUS AVAILABILITY MANAGER STATUS ENGINE VERSION
ygyleqoqkt185xl2l4zczvzdm * fedora Ready Active Leader 28.3.2
当STATUS
字段为READY
则表示健康。
容器编排
我们可以利用已有的Compose规范(Compose V1)来定义容器编排,不过需要注意的是,截至目前,暂不支持最新的Compose规范(Compose V2)。
定义Compose文件
这里我们简单地定义三个Nginx服务的Compose文件,请参考下面的示例:
services:
web:
image: nginx:latest
ports:
- "8088:80"
deploy:
mode: replicated
replicas: 3
update_config:
parallelism: 1
delay: 5s
order: start-first
networks:
web-network:
driver: overlay
attachable: true
自定义overlay驱动的网络,主要是用于隔离各个部署(例如测试,生产环境)。
执行部署
执行以下命令可直接部署三个Nginx服务:
❯ docker stack deploy --detach=false -c nginx-compose.yaml web
Creating network web_default
Creating service web_web
overall progress: 3 out of 3 tasks
1/3: running [==================================================>]
2/3: running [==================================================>]
3/3: running [==================================================>]
verify: Service 865esjcm2u9yh910koxgwj7u0 converged
执行以下命令可查看服务的细节:
❯ docker stack ls
NAME SERVICES
web 1
❯ docker stack services web
ID NAME MODE REPLICAS IMAGE PORTS
865esjcm2u9y web_web replicated 3/3 nginx:latest *:8088->80/tcp
执行以下命令可查看当前服务运行的日志:
❯ docker service logs web_web
web_web.1.2r74tcsruvr5@fedora | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
web_web.1.2r74tcsruvr5@fedora | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
web_web.1.2r74tcsruvr5@fedora | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
web_web.1.2r74tcsruvr5@fedora | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
web_web.1.2r74tcsruvr5@fedora | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
web_web.1.2r74tcsruvr5@fedora | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
web_web.1.2r74tcsruvr5@fedora | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
web_web.1.2r74tcsruvr5@fedora | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
web_web.1.2r74tcsruvr5@fedora | /docker-entrypoint.sh: Configuration complete; ready for start up
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: using the "epoll" event method
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: nginx/1.29.0
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14+deb12u1)
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: OS: Linux 6.15.5-200.fc42.x86_64
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1073741816:1073741816
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker processes
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 29
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 30
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 31
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 32
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 33
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 34
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 35
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 36
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 37
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 38
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 39
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 40
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 41
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 42
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 43
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 44
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 45
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 46
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 47
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 48
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 49
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 50
web_web.2.orv9gsn8fxa3@fedora | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
web_web.2.orv9gsn8fxa3@fedora | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
web_web.2.orv9gsn8fxa3@fedora | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
web_web.2.orv9gsn8fxa3@fedora | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
web_web.2.orv9gsn8fxa3@fedora | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
web_web.2.orv9gsn8fxa3@fedora | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
web_web.2.orv9gsn8fxa3@fedora | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
web_web.2.orv9gsn8fxa3@fedora | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
web_web.2.orv9gsn8fxa3@fedora | /docker-entrypoint.sh: Configuration complete; ready for start up
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: using the "epoll" event method
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: nginx/1.29.0
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14+deb12u1)
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: OS: Linux 6.15.5-200.fc42.x86_64
web_web.3.k3pacajqobit@fedora | /docker-entrypoint.sh: /docker-entrypoint.d/ is not empty, will attempt to perform configuration
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1073741816:1073741816
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker processes
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 29
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 30
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 31
web_web.3.k3pacajqobit@fedora | /docker-entrypoint.sh: Looking for shell scripts in /docker-entrypoint.d/
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 32
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 33
web_web.3.k3pacajqobit@fedora | /docker-entrypoint.sh: Launching /docker-entrypoint.d/10-listen-on-ipv6-by-default.sh
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 34
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 35
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 36
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 37
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 38
web_web.3.k3pacajqobit@fedora | 10-listen-on-ipv6-by-default.sh: info: Getting the checksum of /etc/nginx/conf.d/default.conf
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 39
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 40
web_web.3.k3pacajqobit@fedora | 10-listen-on-ipv6-by-default.sh: info: Enabled listen on IPv6 in /etc/nginx/conf.d/default.conf
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 41
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 42
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 43
web_web.3.k3pacajqobit@fedora | /docker-entrypoint.sh: Sourcing /docker-entrypoint.d/15-local-resolvers.envsh
web_web.3.k3pacajqobit@fedora | /docker-entrypoint.sh: Launching /docker-entrypoint.d/20-envsubst-on-templates.sh
web_web.3.k3pacajqobit@fedora | /docker-entrypoint.sh: Launching /docker-entrypoint.d/30-tune-worker-processes.sh
web_web.3.k3pacajqobit@fedora | /docker-entrypoint.sh: Configuration complete; ready for start up
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: using the "epoll" event method
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 44
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: nginx/1.29.0
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: built by gcc 12.2.0 (Debian 12.2.0-14+deb12u1)
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 45
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: OS: Linux 6.15.5-200.fc42.x86_64
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1073741816:1073741816
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 46
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker processes
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 29
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 47
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 30
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 31
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 48
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 32
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 33
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 49
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 34
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 35
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 36
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 50
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 37
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 38
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 39
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 40
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 41
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 42
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 43
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 44
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 45
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 46
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 47
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 48
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 49
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 50
执行以下命令可以查看实时日志:
❯ docker service logs web_web -f --tail 2
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 49
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 49
web_web.3.k3pacajqobit@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 50
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 49
web_web.2.orv9gsn8fxa3@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 50
web_web.1.2r74tcsruvr5@fedora | 2025/07/20 16:32:53 [notice] 1#1: start worker process 50
我们再次打开新的终端,执行三次 curl -i 127.0.0.1:8088
命令查看日志输出,具体日志示例如下所示:
web_web.3.k3pacajqobit@fedora | 10.0.0.2 - - [20/Jul/2025:16:41:25 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.11.1" "-"
web_web.1.2r74tcsruvr5@fedora | 10.0.0.2 - - [20/Jul/2025:16:41:26 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.11.1" "-"
web_web.2.orv9gsn8fxa3@fedora | 10.0.0.2 - - [20/Jul/2025:16:43:51 +0000] "GET / HTTP/1.1" 200 615 "-" "curl/8.11.1" "-"
我们发现有三个服务(web_web.1、web_web.2和web_web.3)轮流响应我们的请求。
至此,我们的服务已经成功部署好了。接下来,我们需要去1Panel侧去添加网站即可实现对外访问。
添加网站
请参考官方文档-创建网站部分。需要注意的是,端口需选择Compose文件中定义的8088端口。
伸缩服务
对外访问成功后,我们可以根据实际访问情况,添加或减少Swarm节点,伸缩服务实例。例如,我们执行下面的命令可以新增两个服务实例:
❯ docker service scale web_web=5
web_web scaled to 5
overall progress: 5 out of 5 tasks
1/5: running [==================================================>]
2/5: running [==================================================>]
3/5: running [==================================================>]
4/5: running [==================================================>]
5/5: running [==================================================>]
verify: Service web_web converged
总结
总的来说,Docker Swarm的门槛相对Kubernetes较低,基本可以满足小型项目的部署需求。
针对有状态的服务会稍微麻烦一些,因为涉及到状态,可能需要保证服务只能在特定的节点运行,可能需要配置 NFS 保证多个节点上的实例访问同一个文件系统。
希望本文能让你对Docker Swarm有一个初步的了解。