DEBUG.WIKI
京东云;让 AI 进入真实业务;零售 · 物流 · 客服 · 硬件;查看方案 →
ZgoCloud:多地区部署,按需选节点;日本、美国、香港、德国
Evoxt;最高 6.0GHz CPU;高频云服务器 · 免费每周备份;查看配置 →

Docker Compose run 启动后 ports 未映射到宿主机

Compose 文件声明了 ports,但 run 默认不为任务容器发布这些端口。通过容器 ID 核对映射,再选择 --service-ports、临时 -p 映射或 up 启动常驻服务。

Compose 文件已经写了 ports,容器里的 Web 服务也在运行,但浏览器访问宿主机端口时连接失败,应用访问日志没有新请求。如果启动命令是 docker compose run web,需要先核对这个子命令的端口行为。

run 默认不会发布目标服务配置中的端口。它创建一次性任务容器,省略端口发布可以避免与已经运行的服务争用同一个宿主机端口。配置写对了,并不意味着这次启动已经创建映射。

下面针对现代 Docker Compose 插件的 docker compose 命令,以及使用普通 bridge 网络的 Linux 容器。旧版 docker-compose 也有同类行为,但命令选项应以安装版本的帮助为准。使用 host 网络、远程 Docker daemon 或自定义路由时,还要分别确认网络模式与宿主机位置。

先确认是哪一个容器没有端口

以这个简化配置为例,镜像名是占位值,需替换为已准备好的应用镜像,并保留实际服务所需的环境变量、挂载与启动配置。假设 Web 服务已经在容器内可被访问的地址上监听 TCP 80:

services:
  web:
    image: your-web-image:your-tag
    ports:
      - "127.0.0.1:8080:80"

运行 docker compose run web 后,没有看到 127.0.0.1:8080->80/tcp,符合 run 的默认行为。即使列表中有单独的 80/tcp,也不能据此认定宿主机的 8080 已经开放。

在原项目目录查看容器:

docker compose version
docker compose ps --all

如果启动时指定了项目名或其他 Compose 文件,检查时也要使用相同参数。例如:

docker compose -p demo -f compose.test.yaml ps --all

demo 和文件名只是示例。注意区分常驻服务容器与 run 新建的任务容器;不要看着另一个容器的端口列表判断这次启动。选中目标容器的实际 ID 后,单独查询映射:

docker port CONTAINER_ID 80/tcp

将 CONTAINER_ID 替换为刚才确认的 ID。若提示没有发布该端口,继续处理启动方式;若已经返回正确宿主机地址和端口,本篇的“没有创建映射”条件就不成立,应检查进程监听、请求协议及访问路径。没有访问日志本身不足以证明根因。

临时运行时显式启用端口

临时启动 Web 调试实例时,可以让 run 使用服务中已有的全部端口声明:

docker compose run --rm --service-ports web

这是重新创建任务容器,不会给之前的容器补上端口。再次运行前,确认原任务已经停止,所需数据已保存,且 8080 没有被其他实例使用。应用需要的依赖也应准备就绪;run 可能启动相关依赖服务。

--service-ports 会启用该服务配置中的全部端口,因此先检查完整配置,避免同时发布不需要的管理接口。示例把宿主机地址明确写成 127.0.0.1,用于本机访问。省略地址通常会扩大发布范围。Docker Engine 28.0.0 之前还有同一二层网络中的其他主机可访问回环发布端口的已知限制,旧版本不能只靠这个写法保证隔离。

如果原服务已经占用 8080,临时实例可以单独使用另一个空闲宿主机端口,例如:

docker compose run --rm -p 127.0.0.1:18080:80 web

这条命令显式发布宿主机 18080 到容器 80;访问地址相应改成 http://127.0.0.1:18080。它与上面的 --service-ports 是两种选择,不需要顺序执行,也不要再同时启用会冲突的原端口。

命令里的选项都放在服务名 web 前面。服务名后面的位置用于容器要执行的命令及其参数;如果额外写了 sh 或其他程序,会覆盖服务配置的命令。只启动一个 shell 并不保证 Web 服务也会运行。

常驻服务用 up 应用配置

要按 Compose 文件长期运行 Web 服务,使用 up 更符合这个用途:

docker compose up -d web

它会按服务配置创建或更新容器,并使用其中的端口声明。已有服务的镜像或配置发生变化时,可能停止并重建容器,因此应先保存配置、确认持久化数据和备份,并安排允许中断的操作时段。它还可能启动依赖,不能把这条命令当成只读检查。

切换前先处理旧的任务容器,避免重复运行会写同一份数据的进程。也不要为了改用 up 就删除卷。若 up 本身报错或启动后仍不通,需要依据它的具体输出继续排查;run 默认不发布端口的规则不能解释所有启动故障。

验证端口和应用,再结束临时实例

新容器运行后,再用 docker compose ps --all 找到它的 ID,执行前面的 docker port。使用配置端口时应看到 127.0.0.1:8080;使用临时映射时则应看到 127.0.0.1:18080。

随后在 Docker 宿主机上用浏览器访问对应的 HTTP 地址,确认返回的是预期应用内容,并检查服务日志中是否出现请求。远程 Docker daemon 的发布端口位于远端主机,客户端电脑的 127.0.0.1 并不是那台主机;此时应通过已有的合规访问路径验证,不能直接照搬本机地址。

端口已发布但仍然连不上时,检查应用是否真正运行、监听端口是否为 80、是否只绑定了容器自己的回环地址,以及应用使用的是 HTTP 还是 HTTPS。端口发布不会替应用启动进程或修改监听设置。

临时容器不再需要时,先保存日志和必要结果,再按实际 ID 停止:

docker stop CONTAINER_ID

停止会向容器主进程发送停止信号,超时后可能强制终止;应按应用要求留出正常关闭时间。带 --rm 创建的任务容器退出后会自动删除,其可写层里的临时结果也会丢失。它对绑定目录、持久化存储或外部系统已经造成的写入,不会因删除容器而撤销。

恢复原启动方式时,撤掉本次临时端口参数;如果修改过 Compose 文件,则恢复保存的配置并重新应用到对应服务。只停止这次确认的临时实例,保留其他仍在使用的服务与数据。