Docker容器中Django项目无法连接MySQL的问题求助
问题:Docker容器内Django无法连接MySQL数据库
在Windows 10系统中安装Docker v4.20.1,通过docker-compose启动了db(MySQL)、phpmyadmin、web三个容器。phpmyadmin可正常访问MySQL数据库,本地主机运行Django项目也能成功连接该数据库,但在web容器内运行Django执行migrate命令时,出现无法连接127.0.0.1:3306的错误。
错误日志
root@80c6e906cf7e:/usr/src/app# python caravan/manage.py migrate Traceback (most recent call last): File "/usr/local/lib/python3.10/dist-packages/mysql/connector/connection_cext.py", line 291, in _open_connection self._cmysql.connect(**cnx_kwargs) _mysql_connector.MySQLInterfaceError: Can't connect to MySQL server on '127.0.0.1:3306' (111) The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 289, in ensure_connection self.connect() File "/usr/local/lib/python3.10/dist-packages/django/utils/asyncio.py", line 26, in inner return func(*args, **kwargs) File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 270, in connect self.connection = self.get_new_connection(conn_params) File "/usr/local/lib/python3.10/dist-packages/mysql/connector/django/base.py", line 399, in get_new_connection cnx = mysql.connector.connect(**conn_params) File "/usr/local/lib/python3.10/dist-packages/mysql/connector/pooling.py", line 293, in connect return CMySQLConnection(*args, **kwargs) File "/usr/local/lib/python3.10/dist-packages/mysql/connector/connection_cext.py", line 120, in __init__ self.connect(**kwargs) File "/usr/local/lib/python3.10/dist-packages/mysql/connector/abstracts.py", line 1181, in connect self._open_connection() File "/usr/local/lib/python3.10/dist-packages/mysql/connector/connection_cext.py", line 296, in _open_connection raise get_mysql_exception( mysql.connector.errors.DatabaseError: 2003 (HY000): Can't connect to MySQL server on '127.0.0.1:3306' (111) The above exception was the direct cause of the following exception: Traceback (most recent call last): File "/usr/src/app/caravan/manage.py", line 22, in <module> main() File "/usr/src/app/caravan/manage.py", line 18, in main execute_from_command_line(sys.argv) File "/usr/local/lib/python3.10/dist-packages/django/core/management/__init__.py", line 442, in execute_from_command_line utility.execute() File "/usr/local/lib/python3.10/dist-packages/django/core/management/__init__.py", line 436, in execute self.fetch_command(subcommand).run_from_argv(self.argv) File "/usr/local/lib/python3.10/dist-packages/django/core/management/base.py", line 412, in run_from_argv self.execute(*args, **cmd_options) File "/usr/local/lib/python3.10/dist-packages/django/core/management/base.py", line 458, in execute output = self.handle(*args, **options) File "/usr/local/lib/python3.10/dist-packages/django/core/management/base.py", line 106, in wrapper res = handle_func(*args, **kwargs) File "/usr/local/lib/python3.10/dist-packages/django/core/management/commands/migrate.py", line 100, in handle self.check(databases=[database]) File "/usr/local/lib/python3.10/dist-packages/django/core/management/base.py", line 485, in check all_issues = checks.run_checks( File "/usr/local/lib/python3.10/dist-packages/django/core/checks/registry.py", line 88, in run_checks new_errors = check(app_configs=app_configs, databases=databases) File "/usr/local/lib/python3.10/dist-packages/django/core/checks/model_checks.py", line 36, in check_all_models errors.extend(model.check(**kwargs)) File "/usr/local/lib/python3.10/dist-packages/django/db/models/base.py", line 1558, in check *cls._check_indexes(databases), File "/usr/local/lib/python3.10/dist-packages/django/db/models/base.py", line 2002, in _check_indexes connection.features.supports_expression_indexes File "/usr/local/lib/python3.10/dist-packages/django/utils/functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/usr/local/lib/python3.10/dist-packages/django/db/backends/mysql/features.py", line 318, in supports_expression_indexes and self._mysql_storage_engine != "MyISAM" File "/usr/local/lib/python3.10/dist-packages/django/utils/functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/usr/local/lib/python3.10/dist-packages/django/db/backends/mysql/features.py", line 162, in _mysql_storage_engine return self.connection.mysql_server_data["default_storage_engine"] File "/usr/local/lib/python3.10/dist-packages/django/utils/functional.py", line 57, in __get__ res = instance.__dict__[self.name] = self.func(instance) File "/usr/local/lib/python3.10/dist-packages/mysql/connector/django/base.py", line 541, in mysql_server_data with self.temporary_connection() as cursor: File "/usr/lib/python3.10/contextlib.py", line 135, in __enter__ return next(self.gen) File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 705, in temporary_connection with self.cursor() as cursor: File "/usr/local/lib/python3.10/dist-packages/django/utils/asyncio.py", line 26, in inner return func(*args, **kwargs) File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 330, in cursor return self._cursor() File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 306, in _cursor self.ensure_connection() File "/usr/local/lib/python3.10/dist-packages/django/utils/asyncio.py", line 26, in inner return func(*args, **kwargs) File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 288, in ensure_connection with self.wrap_database_errors: File "/usr/local/lib/python3.10/dist-packages/django/db/utils.py", line 91, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 289, in ensure_connection self.connect() File "/usr/local/lib/python3.10/dist-packages/django/utils/asyncio.py", line 26, in inner return func(*args, **kwargs) File "/usr/local/lib/python3.10/dist-packages/django/db/backends/base/base.py", line 270, in connect self.connection = self.get_new_connection(conn_params) File "/usr/local/lib/python3.10/dist-packages/mysql/connector/django/base.py", line 399, in get_new_connection cnx = mysql.connector.connect(**conn_params) File "/usr/local/lib/python3.10/dist-packages/mysql/connector/pooling.py", line 293, in connect return CMySQLConnection(*args, **kwargs) File "/usr/local/lib/python3.10/dist-packages/mysql/connector/connection_cext.py", line 120, in __init__ self.connect(**kwargs) File "/usr/local/lib/python3.10/dist-packages/mysql/connector/abstracts.py", line 1181, in connect self._open_connection() File "/usr/local/lib/python3.10/dist-packages/mysql/connector/connection_cext.py", line 296, in _open_connection raise get_mysql_exception( django.db.utils.DatabaseError: (2003, "2003 (HY000): Can't connect to MySQL server on '127.0.0.1:3306' (111)", 'HY000') root@80c6e906cf7e:/usr/src/app#
docker-compose.yml配置
version: "3.9" services: db: image: db container_name: db restart: always ports: - 3306:3306 volumes: - mysql-data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} phpmyadmin: image: phpmyadmin container_name: phpmyadmin restart: always ports: - 8080:80 depends_on: - db environment: - PMA_PORT=3306 web: image: web container_name: web restart: always ports: - 80:80 volumes: - ./web:/usr/src/app depends_on: - db volumes: mysql-data:
Django数据库连接配置
DATABASES = { 'default': { 'NAME': 'caravan', 'ENGINE': 'mysql.connector.django', 'HOST': '127.0.0.1', 'PORT': 3306, 'USER': 'myuser', 'PASSWORD': 'mypass', 'OPTIONS': { 'autocommit': True, 'use_oure': True, }, } }
排查与解决方法
核心问题
Docker容器内的127.0.0.1指向容器自身,而非宿主机或db容器。Docker Compose默认会为所有服务创建一个共享网络,容器之间可以通过服务名(即docker-compose.yml中定义的服务名称,这里是db)互相访问。
修复步骤
- 修改Django数据库配置的HOST
将Django配置中的HOST: '127.0.0.1'替换为HOST: 'db':
DATABASES = { 'default': { 'NAME': 'caravan', 'ENGINE': 'mysql.connector.django', 'HOST': 'db', # 替换为db服务名 'PORT': 3306, 'USER': 'myuser', 'PASSWORD': 'mypass', 'OPTIONS': { 'autocommit': True, 'use_unicode': True, # 注意:原配置中的use_oure应为拼写错误,修正为use_unicode }, } }
- 额外检查点
- 确认db容器服务就绪:
depends_on仅保证容器启动顺序,不保证MySQL服务完全就绪。可查看db容器日志,确认出现ready for connections信息;也可在web容器中添加等待脚本,确保MySQL启动后再运行Django命令。 - 检查MySQL用户权限:默认创建的
MYSQL_USER可能仅允许从localhost访问,需在db容器中执行以下命令,允许用户从任意IP(容器网络内)访问:docker exec -it db mysql -uroot -p${MYSQL_ROOT_PASSWORD} # 进入MySQL后执行 GRANT ALL ON caravan.* TO 'myuser'@'%' IDENTIFIED BY 'mypass'; FLUSH PRIVILEGES; - 确认数据库存在:若db容器为首次启动,需手动创建
caravan数据库,或在docker-compose.yml的db服务环境变量中添加MYSQL_DATABASE: caravan,让容器启动时自动创建数据库:db: # ...其他配置 environment: MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD} MYSQL_USER: ${MYSQL_USER} MYSQL_PASSWORD: ${MYSQL_PASSWORD} MYSQL_DATABASE: caravan # 添加此行 - 核对环境变量一致性:确保
docker-compose.yml中MYSQL_USER、MYSQL_PASSWORD与Django配置中的对应值完全一致。
内容的提问来源于stack exchange,提问作者firestoke
相关产品推荐
相关产品推荐

