
Java应用启动后连不上MySQL:Docker Compose网络配置没对
Java服务容器默认和MySQL容器不在同一个网络,localhost在Java容器里指向自己,不是宿主机也不是MySQL容器。必须显式定义自定义网络,并让所有服务加入它。
- 在
docker-compose.yml顶部加networks块,比如app-network - 每个服务(
java-app、mysql)都加networks: [app-network] - Java里的数据库URL不能写
jdbc:mysql://localhost:3306/...,得换成jdbc:mysql://mysql:3306/...——这里mysql是services下的服务名,Docker DNS会自动解析成对应容器IP - 别依赖
depends_on来“等MySQL就绪”:它只控制启动顺序,不检查MySQL进程是否真正能响应连接;Java端需自带重试逻辑或用wait-for-it.sh
Spring Boot应用打包进镜像后配置失效:application.yml被覆盖或未生效
Docker镜像里运行的Java进程,读取配置的优先级和本地IDE不同,容易误以为配置写了就起作用。
- 确认
application.yml确实被打包进了jar内部的BOOT-INF/classes/路径下(用jar -tvf your-app.jar | grep application.yml验证) - 如果想从外部挂载配置,用
volumes映射时注意路径:Spring Boot默认只扫描config/子目录,所以建议挂载到/app/config并用--spring.config.location=file:/app/config/启动参数指定 - 环境变量优先级高于
yml,比如SPRING_DATASOURCE_URL设了,就会覆盖application.yml里的spring.datasource.url - 别把
spring.profiles.active硬编码在yml里,改用environment字段在docker-compose.yml中传入:SPRING_PROFILES_ACTIVE: "prod"
Java容器启动报Connection refused但MySQL容器状态是up:端口没暴露或健康检查失败
docker-compose ps显示MySQL是Up,不代表它已接受连接。常见原因是端口未正确暴露,或MySQL初始化未完成。
- MySQL服务必须声明
ports(如"3306:3306")才能被同网络其他容器访问——等等,不对:同一Docker网络内,容器间通信走内部端口,不需要ports;ports只对宿主机暴露。删掉MySQL的ports反而更安全 - 检查MySQL日志:
docker-compose logs mysql,看是否有mysqld: ready for connections;如果没有,可能是MYSQL_ROOT_PASSWORD没设,导致初始化卡住 - 在
mysql服务下加healthcheck,例如用mysqladmin ping -h localhost -u root -p$$MYSQL_ROOT_PASSWORD,再让Java服务通过depends_on: { mysql: { condition: service_healthy } }等待 - Java镜像里别装
mysql-client去手动测试连通性——增大镜像体积且无必要;用telnet mysql 3306或nc -zv mysql 3306更轻量
部署后接口返回500但日志没报错:JVM内存不足触发OOM Killer静默杀进程
Docker默认不限制内存,Java进程可能申请超量堆内存,被Linux内核OOM Killer干掉,docker-compose logs java-app看起来“突然中断”,无异常栈。
立即学习“Java免费学习笔记(深入)”;
- 务必在
docker-compose.yml的Java服务下设mem_limit,比如512m,并同步调小JVM参数:JAVA_OPTS: "-Xms256m -Xmx256m" - 别用
-Xmx4g这种远超容器限制的值,JVM会启动失败并报Invalid initial heap size - 加
restart: on-failure只是掩盖问题;先确认docker stats里Java容器的内存使用是否持续逼近limit - Spring Boot 2.3+支持
cgroup感知,自动按容器限制设堆大小,可加JAVA_OPTS: "-XX:+UseContainerSupport"启用
网络、配置、健康检查、资源限制这四点,漏掉任一个,Java容器都可能“看似启动成功,实则无法工作”。尤其depends_on不等于“可用”,这点最容易被忽略。










