You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

关键注意事项
  1. 服务间通信:在service1的应用里,访问service2直接用service2:1298,访问service3用service3:1299就行,不需要主机IP或主机端口——同一overlay网络里的服务可以通过服务名自动解析。
  2. 端口控制:真正决定容器内端口的是你的应用程序,environment里的APP_PORT是给应用传的参数(如果你的entrypoint.sh会读取它来启动服务的话),ports只是把容器端口映射到主机。
  3. 正确部署命令:
docker stack deploy -c docker-compose.yml test-stack
  1. 验证部署:部署后可以用这些命令检查:
# 查看栈内所有服务状态
docker stack services test-stack
# 查看service1的日志,排查通信问题
docker service logs test-stack_service1
# 进入容器检查端口监听情况
docker exec -it <容器ID> netstat -tulpn

内容的提问来源于stack exchange,提问作者Colas06

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.28 03:59:00