django 无法在 docker-compose 中连接 mysql
Posted
技术标签:
【中文标题】django 无法在 docker-compose 中连接 mysql【英文标题】:django cannot connect mysql in docker-compose 【发布时间】:2018-06-07 08:04:45 【问题描述】:我对docker很陌生,现在我正在尝试通过docker-compose在docker中使用mariadb运行django,但我总是收到这个错误:
我使用Docker version 17.09.1-ce, build 19e2cf6
,docker-compose version 1.18.0, build 8dd22a9
django.db.utils.OperationalError: (2003, 'Can\'t connect to mysql \'mariadb55\' 上的服务器 (111 "Connection denied")')
我可以在本地或远程运行docker-compose up db
后正确连接db,我什至可以在anaconda虚拟环境中正确运行python manage.py runserver 0.0.0.0:6001
通过设置参数来连接docker中的db
服务settings.py 文件如下:
DATABASES =
'default':
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'belter',
# 'HOST': 'mariadb55',
'HOST': '127.0.0.1',
'PORT': '3302',
'PASSWORD': 'belter_2017',
'default-character-set': 'utf8',
'OPTIONS':
'sql_mode': 'traditional',
这是我的 docker-compose.yml 文件
version: '3'
services:
db:
image: mariadb:5.5
restart: always
environment:
- MYSQL_HOST=localhost
- MYSQL_PORT=3306
- MYSQL_ROOT_HOST=%
- MYSQL_DATABASE=test
- MYSQL_USER=belter
- MYSQL_PASSWORD=belter_2017
- MYSQL_ROOT_PASSWORD=123456_abc
volumes:
- /home/belter/mdbdata/mdb55:/var/lib/mysql
ports:
- "3302:3306"
web:
image: onlybelter/django_py35
command: python3 manage.py runserver 0.0.0.0:6001
volumes:
- /mnt/data/www/mysite:/djcode
ports:
- "6001:6001"
depends_on:
- db
links:
- db:mariadb55
我几乎尝试了所有我能找到的东西,但仍然无法弄清楚,任何帮助都会很好!
我尝试过的:
Docker compose mysql connection failing
Linking django and mysql containers using docker-compose
Django connection to postgres by docker-compose
【问题讨论】:
docker-compose.yml
文件中的 MySQL 服务在哪里?
我用mariadb
,它们是一样的。
您能否提供用于从 Web 连接到数据库的 url。
@yamenk 什么网址?
【参考方案1】:
用这个构建容器:
docker run --name mysql-latest \
-p 3306:3306 -p 33060:33060 \
-e MYSQL_ROOT_HOST='%' -e MYSQL_ROOT_PASSWORD='strongpassword' \
-d mysql/mysql-server:latest
确保MYSQL_ROOT_HOST='%'
,这意味着root可以从任何IP连接。
【讨论】:
【参考方案2】:我终于明白了!
关键是,正如@SangminKim 所说,我需要在settings.py
中使用3306
而不是3302
,并使用db
作为HOST
而不是127.0.0.1
。
这是我现在的 docker-compose.yml 文件:
version: '3'
services:
db:
image: mariadb:5.5
restart: always
environment:
- MYSQL_HOST=localhost
- MYSQL_PORT=3306 # cannot change this port to other number
- MYSQL_ROOT_HOST=%
- MYSQL_DATABASE=test
- MYSQL_USER=belter
- MYSQL_PASSWORD=belter_2017
- MYSQL_ROOT_PASSWORD=123456_abc
volumes:
- /home/belter/mdbdata/mdb55:/var/lib/mysql
ports:
- "3302:3306"
web:
image: onlybelter/django_py35
command: python3 manage.py runserver 0.0.0.0:6001
volumes:
- .:/djcode
ports:
- "6001:6001"
depends_on:
- db
所以现在我们可以通过mysql -h 127.0.0.1 -P 3302 -u root -p
在shell中直接连接这个docker-mysql,但是我们必须在djangosettings.py
文件中使用db
和3306
:
DATABASES =
'default':
'ENGINE': 'django.db.backends.mysql',
'NAME': 'test',
'USER': 'belter',
# 'HOST': 'mariadb55',
'HOST': 'db', #<---
'PORT': '3306', #<---
'PASSWORD': 'belter_2017',
'default-character-set': 'utf8',
'OPTIONS':
'sql_mode': 'traditional',
我们仍然可以通过在docker-compose.yml
文件中运行额外的命令来检查此端口是否打开:
...
web:
image: onlybelter/django_py35
command: /bin/sh -c "python check_db.py --service-name mysql --ip db --port 3306"
volumes:
- .:/djcode
...
这是 check_db.py 文件:
# check_db.py
import socket
import time
import argparse
""" Check if port is open, avoid docker-compose race condition """
parser = argparse.ArgumentParser(description='Check if port is open, avoid\
docker-compose race condition')
parser.add_argument('--service-name', required=True)
parser.add_argument('--ip', required=True)
parser.add_argument('--port', required=True)
args = parser.parse_args()
# Get arguments
service_name = str(args.service_name)
port = int(args.port)
ip = str(args.ip)
# Infinite loop
while True:
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
result = sock.connect_ex((ip, port))
if result == 0:
print("0 port is open! Bye!".format(service_name))
break
else:
print("0 port is not open! I'll check it soon!".format(service_name))
time.sleep(3)
顺便说一句,这是我的 Dockerfile 用于构建django-py35
:
FROM python:3.5-alpine
MAINTAINER Xin Xiong "xiongxin20008@126.com"
ENV PYTHONUNBUFFERED 1
RUN set -e; \
apk add --no-cache --virtual .build-deps \
gcc \
libc-dev \
linux-headers \
mariadb-dev \
python3-dev \
postgresql-dev \
freetype-dev \
libpng-dev \
g++ \
;
RUN mkdir /djcode
WORKDIR /djcode
ENV REFRESHED_AT 2017-12-25
ADD requirements.txt /djcode/
RUN pip install --no-cache-dir -r /djcode/requirements.txt
RUN pip install uwsgi
ADD . /djcode/ # copy . to /djcode/
EXPOSE 6001
从这里查看更多详细信息:https://github.com/OnlyBelter/django-compose
【讨论】:
【参考方案3】:您应该在 settings.py
文件中使用容器名称而不是 localhost(或 127.0.0.1)。尝试使用container_name
属性为docker-compose.yml
文件中的db
服务提供容器名称,并将settings.py
中的主机名替换为container_name
的值。 (确保它们位于 docker compose 为您创建的同一网络中。)
【讨论】:
我使用docker ps
查找正在运行的容器的名称,即djangopy35_db_1
,并更改了我的settings.py
文件。但我得到了同样的错误:django.db.utils.OperationalError: (2003, 'Can\'t connect to MySQL server on \'djangopy35_db_1\' (111 "Connection refused")')
@Belter,您还应该在settings.py
中将端口更改为3306
而不是3302
。
是的,你是对的!如果我使用db
作为HOST
,我需要使用3306
作为PORT
。以上是关于django 无法在 docker-compose 中连接 mysql的主要内容,如果未能解决你的问题,请参考以下文章
Django / Docker-compose:重试数据库连接时:django.db.utils.OperationalError:(2002,“无法连接到'db'(115)上的MySQL服务器”)
使用 docker-compose 链接 django 和 mysql 容器
docker-compose 与 postgres 的 Django 连接
构建 docker-compose 映像时无法连接到 MySQL