Docker Compose中SpringBoot容器无法连接MySQL容器求助
Docker Compose部署SpringBoot+MySQL连接失败解决方法
问题场景
使用Docker Compose部署SpringBoot应用与MySQL 8.0容器,SpringBoot容器始终无法连接到MySQL。已尝试通过wait-for-it.sh脚本等待MySQL初始化完成、移除Docker Compose网络配置,均未解决问题。
提供的配置文件
Dockerfile
FROM maven:3.8.1-openjdk-11 AS build WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn clean package -DskipTests FROM openjdk:11-jre-slim RUN apt-get update && apt-get install -y default-mysql-client && rm -rf /var/lib/apt/lists/* WORKDIR /app COPY wait-for-it.sh . RUN chmod +x wait-for-it.sh COPY --from=build /app/target/Spring-MyParcial-MVC-DataJPA-Yamid-Punto3-0.0.1-SNAPSHOT.jar . CMD ["./wait-for-it.sh", "db:3306", "--", "java", "-jar", "Spring-MyParcial-MVC-DataJPA-Yamid-Punto3-0.0.1-SNAPSHOT.jar"]
docker-compose.yml
services: app: build: . ports: - "8080:8080" depends_on: db: condition: service_healthy environment: SPRING_DATASOURCE_URL: jdbc:mysql://db:3306/test SPRING_DATASOURCE_USERNAME: qwerty SPRING_DATASOURCE_PASSWORD: qwerty SPRING_JPA_HIBERNATE_DDL_AUTO: update networks: - app-network db: image: mysql:8.0 environment: MYSQL_DATABASE: test MYSQL_ROOT_PASSWORD: qwerty MYSQL_USER: qwerty MYSQL_PASSWORD: qwerty ports: - "3306:3306" networks: - app-network healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 10s retries: 10 networks: app-network: driver: bridge
application.properties
# Database connection settings spring.datasource.url=jdbc:mysql://db:3306/test spring.datasource.username=qwerty spring.datasource.password=qwerty spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
wait-for-it.sh
#!/bin/bash # wait-for-it.sh host="$1" shift cmd="$@" until mysqladmin ping -h "$host" --silent; do >&2 echo "MySQL is unavailable - sleeping" sleep 1 done >&2 echo "MySQL is up - executing command" exec $cmd
日志信息
MySQL容器日志(springboot-db-1)
2024-06-02 18:23:02 2024-06-02T23:23:02.745554Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: /var/run/mysqld/mysqlx.sock 2024-06-02 18:23:02 2024-06-02T23:23:02.745716Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.37' socket: '/var/run/mysqld/mysqld.sock' port: 0 MySQL Community Server - GPL. 2024-06-02 18:23:03 Warning: Unable to load '/usr/share/zoneinfo/iso3166.tab' as time zone. Skipping it. 2024-06-02 18:23:03 Warning: Unable to load '/usr/share/zoneinfo/leap-seconds.list' as time zone. Skipping it. 2024-06-02 18:23:03 Warning: Unable to load '/usr/share/zoneinfo/leapseconds' as time zone. Skipping it. 2024-06-02 18:23:05 Warning: Unable to load '/usr/share/zoneinfo/tzdata.zi' as time zone. Skipping it. 2024-06-02 18:23:05 Warning: Unable to load '/usr/share/zoneinfo/zone.tab' as time zone. Skipping it. 2024-06-02 18:23:05 Warning: Unable to load '/usr/share/zoneinfo/zone1970.tab' as time zone. Skipping it. 2024-06-02 18:23:06 2024-06-02T23:23:06.050472Z 13 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.0.37). 2024-06-02 18:23:08 2024-06-02T23:23:08.086402Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.37) MySQL Community Server - GPL. 2024-06-02 18:23:09 2024-06-02T23:23:09.284886Z 0 [Warning] [MY-011068] [Server] The syntax '--skip-host-cache' is deprecated and will be removed in a future release. Please use SET GLOBAL host_cache_size=0 instead. 2024-06-02 18:23:09 2024-06-02T23:23:09.286715Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.37) starting as process 1 2024-06-02 18:23:09 2024-06-02T23:23:09.294392Z 1 [System] [MY-013576] [InnoDB] InnoDB initialization has started. 2024-06-02 18:23:09 2024-06-02T23:23:09.474764Z 1 [System] [MY-013577] [InnoDB] InnoDB initialization has ended. 2024-06-02 18:23:09 2024-06-02T23:23:09.769065Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed. 2024-06-02 18:23:09 2024-06-02T23:23:09.769133Z 0 [System] [MY-013602] [Server] Channel mysql_main configured to support TLS. Encrypted connections are now supported for this channel. 2024-06-02 18:23:09 2024-06-02T23:23:09.778336Z 0 [Warning] [MY-011810] [Server] Insecure configuration for --pid-file: Location '/var/run/mysqld' in the path is accessible to all OS users. Consider choosing a different directory. 2024-06-02 18:23:09 2024-06-02T23:23:09.810279Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Bind-address: '::' port: 33060, socket: /var/run/mysqld/mysqlx.sock 2024-06-02 18:23:09 2024-06-02T23:23:09.810419Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.37' socket: '/var/run/mysqld/mysqld.sock' port: 3306 MySQL Community Server - GPL.
SpringBoot容器日志(springboot-app-1)
2024-06-02 18:24:11 MySQL is unavailable - sleeping 2024-06-02 18:24:12 MySQL is unavailable - sleeping 2024-06-02 18:24:13 MySQL is unavailable - sleeping 2024-06-02 18:24:14 MySQL is unavailable - sleeping
问题分析
从日志可见,MySQL容器已正常启动并监听3306端口,但SpringBoot容器的wait-for-it.sh脚本一直无法ping通MySQL,核心问题有两点:
- 调用脚本时传入参数
db:3306,脚本直接将整串作为主机名传给mysqladmin ping -h,但mysqladmin的-h仅接收主机名,端口需用-P单独指定,导致连接目标错误。 mysqladmin ping默认使用当前系统用户发起请求,容器内无对应MySQL用户,需显式指定配置的用户名密码才能成功 ping 通。
解决方案
方案1:修改wait-for-it.sh脚本,支持拆分主机和端口
更新后的脚本:
#!/bin/bash # wait-for-it.sh # 拆分传入的主机和端口参数 IFS=':' read -r host port <<< "$1" # 默认端口设为3306 port=${port:-3306} shift cmd="$@" # 显式指定MySQL用户名和密码执行ping操作 until mysqladmin ping -h "$host" -P "$port" -u qwerty -pqwerty --silent; do >&2 echo "MySQL is unavailable - sleeping" sleep 1 done >&2 echo "MySQL is up - executing command" exec $cmd
方案2:修改Dockerfile的CMD命令,简化参数传递
修改Dockerfile中的CMD行:
CMD ["./wait-for-it.sh", "db", "--", "java", "-jar", "Spring-MyParcial-MVC-DataJPA-Yamid-Punto3-0.0.1-SNAPSHOT.jar"]
同时更新wait-for-it.sh:
#!/bin/bash # wait-for-it.sh host="$1" port="3306" shift cmd="$@" until mysqladmin ping -h "$host" -P "$port" -u qwerty -pqwerty --silent; do >&2 echo "MySQL is unavailable - sleeping" sleep 1 done >&2 echo "MySQL is up - executing command" exec $cmd
额外兼容优化(可选)
若修改后SpringBoot仍无法连接,可能是MySQL 8.0默认的caching_sha2_password认证插件与驱动不兼容,可在docker-compose.yml的db服务中添加环境变量:
environment: # 保留原有变量... MYSQL_DEFAULT_AUTH: mysql_native_password
验证步骤
- 停止并删除现有容器:
docker-compose down - 重新构建镜像:
docker-compose build - 启动服务:
docker-compose up - 查看SpringBoot容器日志,确认不再循环打印“MySQL is unavailable”,应用正常启动即可。
内容的提问来源于stack exchange,提问作者sappho7124
相关产品推荐
相关产品推荐

