尧图网站设计 尧图网站设计YAOTU DESIGN
ARTICLE DETAIL

资讯详情

深耕网站设计与一线实操的经验洞察。

Docker部署失败?5大高频问题全解析

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.ymlserver: 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 参数指定。错误示例 DockerfileFROM 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参数构建避免旧缓存干扰。
返回列表