-p 参数可直接映射 TCP 端口,语法为 宿主机端口:容器端口(默认 TCP),支持绑定指定 IP、显式写 /tcp,无需修改 Docker 服务配置;docker ps 显示的 /tcp 是自动补全,非手动输入。

直接在 Docker Desktop 启动容器时用 -p 就能映射 TCP 端口,不需要改 Docker 服务配置、也不用碰 dockerd 的 -H tcp:// 参数——那是给远程 API 调用用的,和容器端口暴露无关。
docker run -p 映射 TCP 端口最常用写法
绝大多数场景下,-p 后跟 宿主机端口:容器端口 即可,默认就是 TCP:
-
docker run -d -p 8080:80 nginx→ 宿主机8080(TCP)转发到容器80 -
docker run -d -p 127.0.0.1:5432:5432 postgres→ 仅本机可连容器 PostgreSQL,避免外网扫描 -
docker run -d -p 8000:8000/tcp -p 8001:8001/udp myapp→ 显式声明协议,更清晰
注意:docker ps 输出里看到的 0.0.0.0:8080->80/tcp 中的 /tcp 是自动补上的,不是你手动写的;只要没加 /udp,就默认是 TCP。
为什么 docker ps 显示 0.0.0.0:8080->80/tcp,但 localhost:8080 访问不通?
常见原因不是映射失败,而是服务根本没监听对的地址或端口:
- 容器内应用绑定的是
127.0.0.1:80,而不是0.0.0.0:80→ 外部请求进不来,得改应用配置或启动参数(如flask --host=0.0.0.0) - 宿主机防火墙拦截了该端口(尤其是 Windows/macOS 上的系统防火墙或第三方安全软件)
- Docker Desktop 的 WSL2 后端中,
localhost在 Windows/macOS 主机上能通,但某些旧版 WSL 配置可能需访问host.docker.internal或检查/etc/hosts - 端口被占用:
Address already in use错误会直接导致容器启动失败,不会静默忽略
想给已运行的容器加 TCP 端口映射?别硬改配置文件
修改 hostconfig.json 和 config.v2.json 并重启 Docker Desktop 不可靠:WSL2 文件系统锁、JSON 格式错一位就启动失败、容器 IP 变化后规则失效。更稳妥的做法是:
- 停掉容器:
docker stop myapp - 用新端口重新运行:
docker run -d -p 8080:80 -p 9000:9000 --name myapp ... - 如果必须保留原容器状态(比如有未持久化的数据),优先考虑用
docker commit打包镜像再重跑 - 极少数无法停机场景才用
iptables -t nat -A DOCKER ...手动加 DNAT 规则,但这条规则不会出现在docker port输出里,排查时容易漏掉
Docker Desktop 的 TCP 端口映射不等于 Docker daemon 的 TCP API 端口
这是最容易混淆的点:-p 2375:2375 是把容器里的某个服务映射到宿主机 2375,而 Docker Desktop 自身的 daemon 默认只监听 unix:///var/run/docker.sock;要开启远程 API(比如让 Jenkins 连 Docker),才需要改 dockerd 的 -H tcp://0.0.0.0:2375 ——但这和容器端口映射完全无关,且开启后必须配 TLS 或防火墙白名单,否则极度危险。
真正影响容器 TCP 暴露的,只有 docker run -p、docker-compose.yml ports: 或 Docker Desktop GUI 里填的端口字段。











