Liquibase无法连接MySQL数据库,请求排查Docker Compose配置
问题排查与解决
报错信息
liquibase_1 | Starting Liquibase at 21:40:22 (version 4.23.1 #12042 built at 2023-08-10 13:48+0000) liquibase_1 | Liquibase Version: 4.23.1 liquibase_1 | Liquibase Open Source 4.23.1 by Liquibase liquibase_1 | liquibase_1 | Unexpected error running Liquibase: Connection could not be created to jdbc:mysql://mysql_db:3307/patshala with driver com.mysql.cj.jdbc.Driver. Communications link failure liquibase_1 | liquibase_1 | The last packet sent successfully to the server was 0 milliseconds ago. The driver has not received any packets from the server. liquibase_1 | - Caused by: Connection refused
Docker Compose配置
version: '3.8' services: mysql_db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: patshala MYSQL_USER: mysql MYSQL_PASSWORD: password volumes: - ./db:/docker-entrypoint-initdb.d/ ports: - "3307:3306" networks: - app-network liquibase: image: liquibase/liquibase:latest command: ["--url=jdbc:mysql://mysql_db:3307/patshala", "--username=mysql", "--password=password", "--changeLogFile=/db/changelog/db.changelog.xml", "update"] volumes: - ./db:/liquibase/changelog - ./mysql-connector-j-8.1.0.jar:/liquibase/lib/mysql-connector-j-8.1.0.jar depends_on: - mysql_db networks: - app-network networks: app-network: driver: bridge
问题分析与修复步骤
1. 错误的数据库端口配置
Docker容器间通信时,不能使用宿主机映射的端口(3307),而是要使用MySQL容器内部的默认端口3306。ports: "3307:3306"仅用于宿主机访问容器,容器之间通过服务名mysql_db通信时,直接用内部端口3306即可。
修改Liquibase的JDBC URL:
--url=jdbc:mysql://mysql_db:3306/patshala
2. 数据库就绪检测缺失
depends_on仅保证Liquibase在MySQL容器之后启动,但不保证MySQL服务已完成初始化、可以接受连接。需要添加健康检查,让Liquibase等待MySQL就绪后再运行。
修改mysql_db服务配置,添加健康检查:
mysql_db: # ... 原有配置 healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-ppassword"] interval: 5s timeout: 5s retries: 5
同时修改liquibase服务的depends_on,依赖MySQL的健康状态:
liquibase: # ... 原有配置 depends_on: mysql_db: condition: service_healthy
3. 驱动兼容与连接参数补充
MySQL 5.7与新版JDBC驱动配合时,建议添加兼容参数避免连接异常:
--url=jdbc:mysql://mysql_db:3306/patshala?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC
4. ChangeLog文件路径修正
你挂载了./db:/liquibase/changelog,但命令中指定的路径/db/changelog/db.changelog.xml与容器内实际路径不匹配。调整挂载和路径:
修改liquibase的挂载配置:
liquibase: volumes: - ./db:/liquibase/db - ./mysql-connector-j-8.1.0.jar:/liquibase/lib/mysql-connector-j-8.1.0.jar
同步修改命令中的changeLogFile路径:
--changeLogFile=/liquibase/db/changelog/db.changelog.xml
修复后的完整Docker Compose配置
version: '3.8' services: mysql_db: image: mysql:5.7 environment: MYSQL_ROOT_PASSWORD: password MYSQL_DATABASE: patshala MYSQL_USER: mysql MYSQL_PASSWORD: password volumes: - ./db:/docker-entrypoint-initdb.d/ ports: - "3307:3306" networks: - app-network healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-ppassword"] interval: 5s timeout: 5s retries: 5 liquibase: image: liquibase/liquibase:latest command: ["--url=jdbc:mysql://mysql_db:3306/patshala?useSSL=false&allowPublicKeyRetrieval=true&serverTimezone=UTC", "--username=mysql", "--password=password", "--changeLogFile=/liquibase/db/changelog/db.changelog.xml", "update"] volumes: - ./db:/liquibase/db - ./mysql-connector-j-8.1.0.jar:/liquibase/lib/mysql-connector-j-8.1.0.jar depends_on: mysql_db: condition: service_healthy networks: - app-network networks: app-network: driver: bridge
内容的提问来源于stack exchange,提问作者Mabel Oza
相关产品推荐
相关产品推荐

