Docker环境下FastAPI应用无法连接MySQL:'Can't connect to MySQL server on 'db''
问题
在Docker环境中部署搭配MySQL的FastAPI应用时,遇到数据库连接错误,报错信息:
sqlalchemy.exc.OperationalError: (pymysql.err.OperationalError) (2003, "Can't connect to MySQL server on 'db' ([Errno -2] Name or service not known)") (Background on this error at: https://sqlalche.me/e/20/e3q8)
对应的docker-compose.yml配置:
services: backend: build: . ports: - "8001:8000" networks: - music-app volumes: - .:/app env_file: - .env environment: - DATABASE_URL=${BACKEND_DATABASE_URL} - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} depends_on: - db command: bash -c "alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload" db: image: mysql:8.0 volumes: - mysql_data:/var/lib/mysql env_file: - .env environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - MYSQL_DATABASE=${MYSQL_DATABASE} ports: - "3307:3306" networks: - music-app healthcheck: test: [ "CMD-SHELL", "mysqladmin ping -h 127.0.0.1 -u root -p$$MYSQL_ROOT_PASSWORD", ] timeout: 20s retries: 10 volumes: mysql_data: networks: music-app: driver: bridge
已做排查:
- 确认
.env中BACKEND_DATABASE_URL格式为mysql://[username]:[password]@[host]:[port]/[database_name] - 验证
backend和db服务处于同一music-app网络 - 配置了数据库健康检查
原因分析与解决方案
1. depends_on不等待数据库就绪
depends_on: [db]仅保证db服务先启动,但MySQL启动后需要时间完成初始化,后端执行alembic upgrade head时数据库可能还未就绪,导致连接失败。
解决方法:
修改backend的启动命令,加入等待数据库就绪的逻辑:
command: bash -c "until mysqladmin ping -h db -u root -p${MYSQL_ROOT_PASSWORD}; do sleep 2; done; alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload"
如果后端镜像没有mysqladmin,可以用nc命令替代(需确保镜像安装了netcat,比如在Dockerfile中添加RUN apt-get update && apt-get install -y netcat-traditional):
command: bash -c "until nc -z db 3306; do sleep 2; done; alembic upgrade head && uvicorn app.main:app --host 0.0.0.0 --port 8000 --reload"
2. 数据库URL配置错误
检查.env中的BACKEND_DATABASE_URL:
- 服务间通信必须使用容器内部端口
3306,而非宿主机映射的3307 - 主机地址必须是
db(docker-compose中服务的名称),不能是localhost或127.0.0.1 - 确认用户名、密码、数据库名称正确,示例格式:
mysql+pymysql://root:${MYSQL_ROOT_PASSWORD}@db:3306/${MYSQL_DATABASE}
3. MySQL 8.0认证插件兼容性问题
MySQL 8.0默认使用caching_sha2_password认证插件,pymysql可能存在兼容性问题导致连接失败。
解决方法:
在db服务的environment中添加认证插件配置:
environment: - MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD} - MYSQL_DATABASE=${MYSQL_DATABASE} - MYSQL_DEFAULT_AUTH=mysql_native_password
4. 数据库容器初始化失败
如果上述方法无效,先排查数据库容器的启动日志,确认是否存在初始化错误(比如密码不符合复杂度要求):
docker-compose logs db
根据日志提示修正配置,比如调整MYSQL_ROOT_PASSWORD的复杂度。
内容的提问来源于stack exchange,提问作者yotaro
相关产品推荐
相关产品推荐

