Docker部署Web服务遇内部服务器错误及数据库连接问题排查
咱们一步步拆解你遇到的问题,以及对应的解决办法:
第一个问题:连接被拒绝(Can't connect to MySQL server on '0.0.0.0')
你一开始把DB_HOST设为0.0.0.0是典型的Docker网络误区——在Docker Compose的默认桥接网络里,容器之间是通过服务名称互相访问的,而不是用0.0.0.0或者宿主机IP。你改成db(对应docker-compose.yml里的db服务名)是完全正确的方向,这一步没问题。
第二个问题:权限被拒绝(Access denied for user 'user'@'172.19.0.3')
这个问题的核心是你的init.sql权限语句有误,还可能和MySQL官方镜像的初始化逻辑冲突,具体来说:
1. GRANT语句语法错误
你的init.sql里写的是:
GRANT ALL PRIVILEGES ON test TO 'user'@'%';
正确的MySQL权限授予语法需要指定数据库下的所有对象,必须加上.*:
GRANT ALL PRIVILEGES ON test.* TO 'user'@'%'; FLUSH PRIVILEGES;
如果不加.*,你只授予了对test数据库本身的权限,而非库内的表、视图等具体对象,这会导致后续操作数据库时触发权限拒绝错误。
2. 避免重复授权的优化(可选)
MySQL官方镜像启动时,会自动根据你设置的MYSQL_USER、MYSQL_PASSWORD、MYSQL_DATABASE环境变量,创建指定用户并授予该用户对目标数据库的全部权限。所以其实你的init.sql授权语句是多余的,甚至可能因为执行时机问题导致权限覆盖。如果不需要额外的权限配置,直接删除init.sql也能解决问题。
3. 确保数据库完全就绪后再启动Web服务
depends_on: [db]只保证db服务先启动,但不保证MySQL已经完成初始化(比如创建数据库、用户、加载init.sql)。如果Web服务启动过快,可能会在数据库初始化完成前尝试连接,也可能出现类似权限的错误(实际是连接时机问题)。
你可以给web服务加一个等待脚本,比如用wait-for-it:
- 先在Dockerfile里安装工具:
RUN apt-get update && apt-get install -y wait-for-it
- 再修改docker-compose.yml里的web command:
command: wait-for-it db:3306 -- gunicorn --bind 0.0.0.0:8000 manage:app
这样Web服务会等待MySQL的3306端口就绪后再启动,彻底避免初始化未完成导致的连接问题。
修复步骤总结
- 修正
sql/init.sql里的GRANT语句(或直接删除该文件); - (可选)添加等待脚本确保数据库就绪;
- 彻底清理旧容器和数据卷(避免缓存干扰),重新构建启动:
docker-compose down -v docker-compose build docker-compose up
内容的提问来源于stack exchange,提问作者Jack Fenn

