使用Docker Compose时Spring Boot连MySQL遇权限拒绝,Hibernate初始化JPA失败
核心问题分析
Access denied for user 'RoadHaulageUser'@'172.18.0.3'是直接触发点,后续Hibernate无法识别数据库方言、初始化EntityManagerFactory都是数据库连接失败导致的连锁问题。
排查与修复步骤
检查数据库用户的主机权限范围
MySQL用户权限绑定访问主机,应用容器从172.18.0.3发起请求,但你的初始化脚本可能仅授予了localhost或特定主机的权限。修改初始化SQL,确保用户允许从任意主机或应用所在网段访问:CREATE USER 'RoadHaulageUser'@'%' IDENTIFIED BY 'your-password'; GRANT ALL PRIVILEGES ON RoadHaulageDB.* TO 'RoadHaulageUser'@'%'; FLUSH PRIVILEGES;注意:不要用
localhost作为主机,Docker容器间通信使用的是容器IP,而非MySQL容器内部的localhost。确保服务启动顺序与MySQL就绪状态
应用容器可能在MySQL完全初始化前就尝试连接,导致用户权限未生效。在docker-compose.yml中添加健康检查和依赖配置:services: mysql: image: mysql:8.0 environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - MYSQL_DATABASE=${MYSQL_DB_NAME} - MYSQL_USER=${MYSQL_USER_NAME} - MYSQL_PASSWORD=${MYSQL_USER_PASSWORD} healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "${MYSQL_USER_NAME}", "-p${MYSQL_USER_PASSWORD}"] interval: 5s timeout: 5s retries: 5 app: build: . depends_on: mysql: condition: service_healthy environment: - SPRING_DATASOURCE_URL=jdbc:mysql://mysql:3306/${MYSQL_DB_NAME}?useSSL=false&serverTimezone=UTC - SPRING_DATASOURCE_USERNAME=${MYSQL_USER_NAME} - SPRING_DATASOURCE_PASSWORD=${MYSQL_USER_PASSWORD}用
service_healthy确保MySQL完全就绪后再启动应用。修正application.yml数据源配置
确保用Docker Compose的服务名mysql作为数据库主机(而非IP,Docker内部DNS会自动解析),同时显式指定Hibernate方言避免连接失败后的识别错误:spring: datasource: url: jdbc:mysql://mysql:3306/${MYSQL_DB_NAME}?useSSL=false&serverTimezone=UTC username: ${MYSQL_USER_NAME} password: ${MYSQL_USER_PASSWORD} jpa: hibernate: ddl-auto: update properties: hibernate: dialect: org.hibernate.dialect.MySQL8Dialect清理Docker缓存与重新初始化
旧容器可能残留错误的权限配置,执行以下命令彻底重置:docker-compose down -v # 删除容器及绑定的数据卷 docker-compose build --no-cache # 无缓存重新构建应用镜像 docker-compose up # 重新启动所有服务验证环境变量传递是否正确
进入应用容器检查环境变量是否正常加载:docker exec -it app-1 env | grep MYSQL # 替换app-1为你的应用容器名确认
MYSQL_USER_NAME、MYSQL_USER_PASSWORD、MYSQL_DB_NAME与.env文件完全一致。
内容的提问来源于stack exchange,提问作者Abrohamovich

