Docker Swarm中使用docker-compose v3配置专属端口部署栈的问题
咱们一步步排查并解决你遇到的问题,这里有几个核心错误导致了端口失效、服务间无法通信的情况:
1. Docker Compose 语法严重错误(最核心)
你的docker-compose.yml写法完全不对!services节点下的每个服务必须有专属的服务名称,不能直接写image: image1。比如要写成service1:,再在这个节点下配置image、environment等参数。语法错误会直接导致Docker无法正确解析配置,这是所有问题的根源。
2. 对
EXPOSE指令的误解 你在Dockerfile里用EXPOSE $EXPOSE_PORT是无效的:
EXPOSE是镜像构建阶段的指令,构建时就会把端口信息写入镜像元数据,但你用的$EXPOSE_PORT是运行时才注入的环境变量,构建镜像时这个变量根本不存在,所以镜像里的EXPOSE端口完全没被正确设置。- 退一步说,
EXPOSE本身只是个文档性声明,不会实际暴露端口给主机或其他服务。真正要让端口可用,分两种情况:- 要暴露给外部主机:用
ports(Swarm模式下也可以用publish)做端口映射 - 仅服务间通信:不需要暴露到主机,只要服务在同一个网络里,直接用服务名+容器内实际监听的端口访问就行
- 要暴露给外部主机:用
3. Swarm 服务间通信的逻辑没搞对
在Docker Swarm里,同一栈的服务默认会加入一个同名的overlay网络,服务之间可以直接通过服务名称(比如service2)访问对方的容器内端口,根本不需要依赖主机端口。你说image1连不上image2/3,很大概率是因为服务名称写错了,或者语法错误导致网络没正常创建。
4.
docker stack deploy 命令写错了 你用的docker stack deploy -test -c docker-compose.yml是错误的,正确格式是把栈名放在最后:
docker stack deploy -c docker-compose.yml test
修正后的完整配置
调整后的Dockerfile
不需要用环境变量设置EXPOSE,直接声明容器内的端口(或者去掉也没关系,因为它只是文档用的):
FROM centos7 # 保留你的其他构建步骤:安装依赖、复制entrypoint.sh等 # 可选:声明容器内的端口,纯文档作用 EXPOSE 80 1298 1299 ENTRYPOINT [ "/entrypoint.sh"]
重点:你的应用程序本身必须在容器内监听对应的端口(比如service1监听80,service2监听1298),Docker只是做端口转发,不能替应用改监听端口。如果你的应用支持通过环境变量改监听端口,那要在
environment里传变量给entrypoint.sh处理。
修正后的docker-compose.yml
version: "3.8" # 用较新的版本,兼容性更好 services: service1: # 给服务起个清晰的名称 image: image1 # 如果需要把service1的80端口暴露给主机(外部访问),加这个ports配置 ports: - "80:80" # 主机端口:容器内端口 environment: # 这里传环境变量给应用,让它监听80端口(如果你的entrypoint.sh支持的话) APP_PORT: "80" depends_on: - service2 - service3 networks: - app-network # 显式指定网络,更清晰 service2: image: image2 environment: APP_PORT: "1298" # 告诉应用监听1298端口 networks: - app-network service3: image: image3 environment: APP_PORT: "1299" # 告诉应用监听1299端口 networks: - app-network # 显式定义overlay网络,Swarm会自动创建 networks: app-network: driver: overlay
关键注意事项
- 服务间通信:在
service1的应用里,访问service2直接用service2:1298,访问service3用service3:1299就行,不需要主机IP或主机端口——同一overlay网络里的服务可以通过服务名自动解析。 - 端口控制:真正决定容器内端口的是你的应用程序,
environment里的APP_PORT是给应用传的参数(如果你的entrypoint.sh会读取它来启动服务的话),ports只是把容器端口映射到主机。 - 正确部署命令:
docker stack deploy -c docker-compose.yml test-stack
- 验证部署:部署后可以用这些命令检查:
# 查看栈内所有服务状态 docker stack services test-stack # 查看service1的日志,排查通信问题 docker service logs test-stack_service1 # 进入容器检查端口监听情况 docker exec -it <容器ID> netstat -tulpn
内容的提问来源于stack exchange,提问作者Colas06
相关产品推荐
相关产品推荐

