docker-compose 中 ports 和 expose 有什么区别?

ports 把容器端口发布到宿主机(外部可访问),expose 仅在 compose 内部网络向其他服务开放端口(不对外)。内部依赖用 expose,对外服务用 ports。

最佳实践
docker-compose 中 ports 和 expose 有什么区别?封面

一句话区别:ports 会把端口发布到宿主机**(宿主机端口:容器端口,外部网络可达);expose在 compose 服务间网络内开放端口,宿主机和外部都访问不到。数据库这类只供内部服务连的用 expose,需要浏览器/外部访问的才用 ports。**

ports:对外发布

services:
  mysql:
    image: mysql:8
    ports:
      - "3306"          # 容器 3306 → 宿主机随机端口

docker compose ps 会看到 0.0.0.0:32769->3306/tcp——宿主机的 32769 被映射过去,局域网里任何人都能连。固定端口写法 "3306:3306"

expose:仅内部可见

services:
  mysql:
    image: mysql:8
    expose:
      - "3306"          # 只有同一 compose 网络里的服务能访问
  app:
    image: myapp
    # app 里用 mysql:3306 连接

app 服务通过服务名 mysql:3306 正常连接;宿主机上 curl localhost:3306 不通。

一个常见误解

其实同一 compose 文件里的服务本来就能互相访问任意容器端口(通过内部 DNS 和服务名),expose 更多是文档性声明+与老版 link 语义的兼容。真正的边界是:

  • 要不要从宿主机/外部访问?要 → ports
  • 只在服务间访问 → 什么都不写也行,写 expose 表明意图

安全建议

  • 数据库、Redis、消息队列默认不要用 ports 暴露到宿主机,尤其宿主机有公网 IP 时
  • 调试期临时需要,可用 "127.0.0.1:3306:3306" 只绑定回环地址

观测云对照

内部服务的可观测一样不能少。 不对外暴露的数据库、缓存,DataKit 照样能在宿主机层面采集其指标与日志,慢查询、连接数异常通过监控器告警——端口不开放不等于状态不可见。

常见问题(FAQ)

Q:ports 写 "3306" 和 "3306:3306" 有什么区别?
A:前者宿主端口随机分配(每次启动可能变),后者固定映射到宿主 3306。

Q:expose 会影响容器间通信吗?
A:不会限制——即使不写 expose,同网络服务也能访问容器所有端口;它主要起声明作用。

Q:生产环境数据库该暴露 ports 吗?
A:不该。只留应用服务的端口,数据层全部走内部网络。

获取专属方案

联系我们

加入社区

微信扫码
加入官方交流群

立即体验

在线开通,按量计费,真正的云服务!

立即开始

选择观测云版本

代码托管平台