在 Docker Compose 文件中,expose
参数用于声明容器内部监听的端口,但其作用与 ports
参数有本质区别。以下是 expose
的核心作用和关键细节:
1. expose
的核心作用
- 声明容器内部端口:仅标记容器运行时开放的端口(供其他容器访问),但不会将端口映射到宿主机。
- 文档化用途:明确告知开发者该容器需要哪些端口(例如数据库默认端口
3306
)。 - 限制容器间通信:在 Docker 网络中,只有
expose
的端口才能被其他容器访问(需配合自定义网络使用)。
2. 与 ports
的区别
参数 | 作用 | 外部访问 |
---|---|---|
expose | 声明容器内部端口,仅允许同一 Docker 网络内的其他容器访问这些端口。 | 不可从宿主机或外部网络直接访问 |
ports | 将容器端口映射到宿主机端口(如 "8080:80" ),允许外部通过宿主机访问容器服务。 | 可通过宿主机 IP 和端口访问 |
3. 适用场景
- 微服务间通信:例如,一个后端服务(容器)需要访问另一个数据库服务(容器)的端口,但无需暴露到宿主机。
- 安全隔离:避免不必要的端口暴露到宿主机,减少攻击面。
- 多容器协作:在 Docker 自定义网络中,容器通过服务名称和
expose
的端口直接通信。
4. 示例
version: '3'
services:web:image: nginxexpose:- "80" # 声明容器内部使用 80 端口networks:- my_networkdatabase:image: mysqlexpose:- "3306" # 声明容器内部使用 3306 端口networks:- my_networknetworks:my_network:
- 结果:
web
容器可通过database:3306
访问数据库。- 宿主机无法直接访问
3306
或80
端口(除非使用ports
映射)。
5. 注意事项
- 必须配合自定义网络:默认的
bridge
网络不支持通过服务名称访问,需定义自定义网络(如上述my_network
)。 - 不替代
ports
:若需从宿主机或外部访问服务,仍需使用ports
。 - 优先级低于
ports
:若同时使用expose
和ports
,实际开放的端口以ports
为准。
总结
- 用
expose
:容器间内部通信,安全隔离。 - 用
ports
:允许外部通过宿主机访问服务。
根据场景合理选择,既保证功能又提升安全性。