Docker部署失败?5大高频问题全解析
不知道大家有没有遇到过这种窒息时刻。前段时间我把一个 SpringBoot 小服务写完,本地启动,所有接口全部通,数据库连接也没问题。写完 Dockerfile 构建镜像,启动容器,看容器日志,没有报错,打印出Started Application in xxx seconds,看起来服务妥妥启动完成。
然后我在宿主机访问接口,直接连接超时。容器内部 curl 能通,宿主机访问就不行。我来回折腾了两个多小时,反复改配置、重新构建镜像,一度怀疑是镜像缓存的问题。后来一点点排查,才发现是几个很基础但是极易忽略的细节。
很多人遇到 Docker 访问失败第一反应就是端口映射没写对,但是实际场景远不止端口问题。下面把高频问题一个个复盘出来。

场景一:服务监听 127.0.0.1,容器外部无法访问
这是最高频的坑,很多新手栽在这里。本地开发的时候,服务监听127.0.0.1没问题,本机可以访问。但是在 docker 容器内部,如果程序只绑定 127.0.0.1,代表只允许容器本机回环地址访问,宿主机哪怕做了端口映射,也转发不进去。
SpringBoot 默认配置,如果不指定 server.address,新版本默认绑定 0.0.0.0。但是如果 application.yml 手动写死了 127.0.0.1,容器部署直接凉凉。
错误配置 application.yml
server:
port: 8080
address: 127.0.0.1 # 错误写法,容器内外部无法访问
正确配置:
server:
port: 8080
address: 0.0.0.0
小技巧:进入容器内部验证,执行下面命令,在容器里面访问自己服务,如果容器内部 curl 可以通,宿主机不通,大概率就是绑定地址问题。
#进入容器
docker exec -it 容器id /bin/bash
curl 127.0.0.1:8080
场景二:Dockerfile EXPOSE 只是声明,不会自动开放端口
不少初学者有一个误区,以为 Dockerfile 写了 EXPOSE,就代表端口可以对外访问。这里要划重点:EXPOSE 仅仅是文档声明,不会实际开放端口,端口映射必须在 docker run 的时候通过‑p 参数指定。
错误示例 Dockerfile
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/demo‑0.0.1‑SNAPSHOT.jar app.jar
EXPOSE 8080
ENTRYPOINT ["java","‑jar","app.jar"]
构建镜像之后,如果直接docker run 镜像id,没有加‑p,就算写了 EXPOSE,宿主机依旧访问不到。
正确启动命令,做端口映射:
docker run -d -p 8080:8080 --name demo-service demo-image
-p 宿主机端口:容器内部端口,千万不要写反,写反同样访问失败。
场景三:容器内部访问数据库使用localhost
本地开发数据库装在本机,配置写localhost或者127.0.0.1完全没问题。但是放到 docker 容器中,localhost代表容器自身,不是宿主机。这就会出现:服务启动报数据库连接失败,本地跑正常,docker 里面直接报错。
application.yml 错误配置
spring:
datasource:
url: jdbc:mysql://localhost:3306/testdb
解决方式:
- 如果数据库部署在宿主机,使用宿主机真实内网 IP,不要写localhost。
- 使用 docker‑compose 编排,通过服务名作为 hostname 互相访问。
docker‑compose 简单示例:
version: '3.8'
services:
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root123
ports:
- "3306:3306"
demo-app:
image: demo-image
ports:
- "8080:8080"
depends_on:
- mysql
此时服务连接数据库 url 写成jdbc:mysql://mysql:3306/testdb。
场景四:容器防火墙、宿主机防火墙拦截
前面配置全部没问题,依旧访问失败,就要考虑防火墙。 1. 云服务器安全组,没有放开对外端口,宿主机端口虽然映射成功,外网无法进来。 2. 宿主机 firewalld/iptables 防火墙拦截 docker 转发。
排查思路:先在服务器本机 curl 127.0.0.1:8080,如果服务器本机可以访问,但是浏览器外网访问不通,几乎就是云服务器安全组没放行端口。
完整可用的 Dockerfile 示例
FROM openjdk:17-jdk-slim
WORKDIR /app
COPY target/demo-0.0.1-SNAPSHOT.jar app.jar
#EXPOSE仅作为说明
EXPOSE 8080
ENTRYPOINT ["java","-jar","app.jar"]
构建 & 启动命令
#构建镜像
docker build -t demo-app:v1 .
#运行容器,端口映射
docker run -d -p 8080:8080 --name demo demo-app:v1
#查看日志
docker logs -f demo
一套通用排错流程,遇到访问失败按顺序排查
1. 查看容器状态:docker ps确认容器是 Up 状态,如果反复重启,说明程序启动直接报错,看日志定位异常。 2. 进入容器内部docker exec -it 容器id /bin/bash,容器内部 curl 127.0.0.1: 端口,判断容器内部服务是否正常。 3. 确认程序监听地址是不是 0.0.0.0,而不是 127.0.0.1。 4. 确认 docker run 是否正确写‑p 端口映射,端口前后顺序没有颠倒。 5. 确认数据库、redis 等中间件地址,不要写localhost。 6. 服务器本机 curl 测试,区分是本机问题还是外网安全组防火墙问题。
写在最后
本地正常,docker 部署后访问失败,90% 都不是代码业务逻辑 bug,而是环境网络层面的问题。本地开发环境和 docker 容器网络模型完全不一样,很多在本机成立的配置,放到容器中直接失效。
我之前踩坑的时候,一开始总怀疑是代码、jar 包打包问题,反复重新 mvn 打包,浪费大量时间。后面养成固定排错步骤,先区分容器内部能不能访问,再向外一层一层排查,问题定位速度快很多。
另外提醒一点,不要忽略镜像缓存,修改 Dockerfile 之后构建镜像,如果改动不生效,可以加上--no-cache参数构建,避免旧缓存干扰。
更多推荐


所有评论(0)