使用Docker Compose时Spring无法识别MySQL环境变量连接串问题
我在使用Docker Compose部署Spring Boot应用和MySQL时,遇到数据库连接失败的问题:Docker Compose环境变量中配置的数据库连接串无法被Spring的application.yml识别,直接粘贴连接串也无效,出现Hibernate相关错误。
原始配置文件
docker-compose.yml
version: '3' services: mysqldb: image: mysql:8.3.0 ports: - "3307:3306" environment: MYSQL_ROOT_PASSWORD: 23012003aA@ MYSQL_DATABASE: checklist restart: always spring: build: context: ./back_end dockerfile: Dockerfile depends_on: - mysqldb environment: - BE_PORT=9292 - DATASOURCE_URL=jdbc:mysql://localhost:3307/checklist - DATASOURCE_USERNAME=root - DATASOURCE_PASSWORD=123456789aA@ ports: - "9292:9292"
application.yml
spring: datasource: url: jdbc:mysql://localhost:3306/checklist?useSSL=false&createDatabaseIfNotExist=true username: ${DATASOURCE_USERNAME} password: ${DATASOURCE_PASSWORD} jpa: show-sql: false hibernate: ddl-auto: update multipart: max-file-size: 10MB max-request-size: 10MB
问题原因及解决方案
问题出在以下几个关键点,逐一修复即可解决:
application.yml未引用环境变量连接串
原始配置中spring.datasource.url是硬编码值,完全没用到Docker Compose里定义的DATASOURCE_URL变量。修改为:spring: datasource: url: ${DATASOURCE_URL}容器间通信地址错误
Docker内部服务不能用localhost访问其他容器,必须用服务名(这里是mysqldb);且容器内MySQL端口是默认的3306,不是宿主机映射的3307。同时添加MySQL 8.x适配参数:
修改Docker Compose中的DATASOURCE_URL为:DATASOURCE_URL=jdbc:mysql://mysqldb:3306/checklist?useSSL=false&createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true&serverTimezone=UTC数据库密码不匹配
Docker Compose中MySQL的MYSQL_ROOT_PASSWORD是23012003aA@,但Spring服务的DATASOURCE_PASSWORD是123456789aA@,密码不一致导致连接被拒绝。将Spring的密码改为和MySQL一致的23012003aA@。Multipart配置位置错误
原始配置中multipart放在jpa节点下属于无效配置,Spring无法识别。移到servlet节点下:spring: servlet: multipart: max-file-size: 10MB max-request-size: 10MBMySQL启动就绪问题
depends_on仅保证启动顺序,不保证MySQL完成初始化。添加健康检查确保Spring在MySQL就绪后启动:
在mysqldb服务中添加:healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 5s timeout: 5s retries: 5同时修改Spring服务的
depends_on:depends_on: mysqldb: condition: service_healthy
修改后的完整配置
docker-compose.yml
version: '3' services: mysqldb: image: mysql:8.3.0 ports: - "3307:3306" environment: MYSQL_ROOT_PASSWORD: 23012003aA@ MYSQL_DATABASE: checklist restart: always healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 5s timeout: 5s retries: 5 spring: build: context: ./back_end dockerfile: Dockerfile depends_on: mysqldb: condition: service_healthy environment: - BE_PORT=9292 - DATASOURCE_URL=jdbc:mysql://mysqldb:3306/checklist?useSSL=false&createDatabaseIfNotExist=true&allowPublicKeyRetrieval=true&serverTimezone=UTC - DATASOURCE_USERNAME=root - DATASOURCE_PASSWORD=23012003aA@ ports: - "9292:9292"
application.yml
spring: datasource: url: ${DATASOURCE_URL} username: ${DATASOURCE_USERNAME} password: ${DATASOURCE_PASSWORD} jpa: show-sql: false hibernate: ddl-auto: update servlet: multipart: max-file-size: 10MB max-request-size: 10MB
内容的提问来源于stack exchange,提问作者ya3k

