一、问题/场景描述
在使用 Docker Compose 管理多容器应用时,执行 docker compose up -d 命令后,容器状态显示为正常运行,但通过浏览器或 curl 访问应用提供的服务(如 HTTP 端口)时,却无法建立连接,返回连接超时或拒绝访问的错误。此问题常见于开发或测试环境,影响调试效率。
二、原因分析
容器启动后无法访问通常由以下原因导致:第一,端口映射配置错误,例如在 docker-compose.yml 中未正确将容器内部端口绑定到宿主机端口;第二,容器内服务绑定地址不正确,服务仅监听 127.0.0.1 而非 0.0.0.0,导致外部无法访问;第三,容器网络配置问题,如使用自定义网络但未正确连接;第四,宿主机防火墙或安全组规则阻止了端口访问;第五,容器内服务启动失败,但容器进程未退出(例如 Web 服务器配置错误)。需要按顺序排查这些环节。
三、详细解决步骤
步骤1:检查容器状态和日志
首先确认容器是否真正运行,并查看日志获取错误信息。
docker compose ps
docker compose logs [服务名]
如果日志显示服务启动失败(如端口被占用、配置错误),则根据日志修复。如果日志为空或正常,继续下一步。
步骤2:验证端口映射配置
检查 docker-compose.yml 中 ports 配置是否正确。标准格式为 "宿主机端口:容器端口"。
services:
web:
image: nginx:latest
ports:
- "8080:80" # 宿主机8080映射到容器80
执行以下命令查看实际映射情况:
docker compose port [服务名] [容器端口]
例如 docker compose port web 80 应返回类似 0.0.0.0:8080。若返回空或错误,修正 docker-compose.yml 后重新运行 docker compose up -d。
步骤3:检查容器内服务监听地址
进入容器查看服务是否监听在 0.0.0.0 上。
docker exec -it [容器名] /bin/sh
在容器内执行(以 Nginx 为例):
netstat -tlnp | grep 80
如果显示 127.0.0.1:80,则需修改服务配置为 0.0.0.0:80。例如 Nginx 修改 listen 80; 为 listen 0.0.0.0:80;。修改后重建容器。
步骤4:检查网络和防火墙
在宿主机上测试端口连通性:
curl -v http://localhost:[宿主机端口]
如果本地可访问但外部不行,检查防火墙:
# 对于 iptables
sudo iptables -L -n | grep [端口]
# 对于 firewalld
sudo firewall-cmd --list-ports
# 对于 ufw
sudo ufw status
确保宿主机防火墙允许对应端口入站流量。临时开放端口示例:
sudo ufw allow 8080/tcp
步骤5:检查 Docker 网络模式
确认 docker-compose.yml 中网络配置是否正确,尤其当使用自定义网络时。
services:
web:
networks:
- mynet
networks:
mynet:
driver: bridge
如果服务依赖其他容器,确保它们在同一网络:
docker compose exec [服务名] ping [其他服务名]
若无法 ping 通,调整 networks 配置后重新部署。
步骤6:重建容器
如果以上步骤均无法解决,尝试完全重建容器,避免缓存问题。
docker compose down
docker compose up -d --build
四、注意事项
修改 docker-compose.yml 后必须执行 docker compose up -d 重新创建容器,仅重启容器不会应用配置变更。使用 docker compose down -v 会移除卷数据,谨慎操作。生产环境建议设置健康检查(healthcheck)以便自动检测服务可用性。日志分析是定位问题的关键,优先查看。
五、适用环境
本文适用于 Docker Compose v2.x 及以上版本,测试环境为 Ubuntu 22.04 + Docker 24.0 + Docker Compose v2.20,其他 Linux 发行版操作类似。
