我正在尝试使用docker设置Django开发环境。虽然我可以连接到主机上的mysql。但是Web容器无法连接到mysql容器,并出现以下错误:
django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on 'db' (111)")
以下是docker配置和django配置:
---------搬运工-compose.yml ---------
version: '2'
services:
web:
build: .
volumes:
- ".:/code/current"
ports:
- "8000:8000"
depends_on:
- db
- redis
links:
- db
- redis
command: ./manage.py runserver 0.0.0.0:8000
db:
image: mysql:5.7
volumes:
- "./.data/db:/var/lib/mysql"
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=goat_db
restart: always
ports:
- "3306:3306"
redis的: 重启:总是 image:redis:最新 端口: - " 6379:6379"
--------------用于网络图片的Dockerfile ----------------------
FROM ubuntu:14.04
MAINTAINER Alice
RUN apt-get update
RUN apt-get install -y tar git curl wget emacs build-essential python python-dev python-distribute python-pip libpcre3 libpcre3-dev libmysqlclient-dev python-m2crypto openssl libssl-dev swig freetds-dev python-pymssql nginx subversion
RUN mkdir -p var/www/goat.garenanow.com/current/log
WORKDIR /var/www/goat.garenanow.com/current
ADD requirements.txt /var/www/goat.garenanow.com/current
RUN pip install -r requirements.txt
ADD . /var/www/goat.garenanow.com/current
EXPOSE 8000
------ django数据库配置---
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'goat_db',
'USER': 'root',
'PASSWORD': 'root',
'HOST': 'db',
'PORT': '3306',
},
答案 0 :(得分:0)
您的my.cnf文件对于db服务是什么样的?
检查bind-address
值,并确保从Web容器连接的授权权限正确。
要进行测试,您可以docker exec ...
进入网络容器并尝试从那里连接到db
主机。
答案 1 :(得分:0)
如果Django尝试连接到您的数据库且MySql尚未就绪,那么您可能会看到此错误:
django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on 'db' (111)")
此案例的解决方案是在运行Web服务器之前等待数据库服务器准备就绪。
我们如何做到这一点?
我们不是直接运行Web服务器,而是创建并运行一个脚本,它将等待数据库服务器准备就绪。之后,脚本将运行Web服务器。
docker-compose.yml 文件(相关部分是我们覆盖web:command
指令,我们运行脚本而不是立即运行Web服务器。
version: '3'
services:
db:
restart: always
image: mysql:5.7
container_name: my_db
env_file: env_db
ports:
- "3306:3306"
web:
restart: always
build: ./web
env_file: env_web
command: ./wait_for_db_and_start_server.sh
ports:
- "8000:8000"
depends_on:
- db
现在 env_web 文件(相关部分为START_CMD
变量)。
# Add Environment Variables
DB_NAME=docker
DB_USER=docker_user
DB_PASS=docker_password
DB_SERVICE=db
DB_HOST=db
DB_PORT=3306
START_CMD=python manage.py runserver 0.0.0.0:8000
现在,我们的网站 Dockerfile (相关部分是我们添加wait_for_db_and_start_server.sh
时)。
FROM python:2.7
ADD wait_for_db_and_start_server.sh .
ADD requirements.txt .
RUN pip install -r requirements.txt
ADD . .
现在 wait_for_db_and_start_server.sh 文件。 (基本上,虽然我们无法连接到我们的env_web文件中定义的指定$DB_HOST
:$DB_PORT
上的数据库服务器,但我们会等待3秒钟再次尝试M_LOOPS
次。如果我们能够要连接到服务器,我们运行在我们的env_web文件中定义的$START_CMD
。)
#!/bin/sh
# Wait for database to get available
M_LOOPS="10"
#wait for mysql
i=0
# http://stackoverflow.com/a/19956266/4848859
while ! curl $DB_HOST:$DB_PORT >/dev/null 2>&1 < /dev/null; do
i=`expr $i + 1`
if [ $i -ge $M_LOOPS ]; then
echo "$(date) - ${DB_HOST}:${DB_PORT} still not reachable, giving up"
exit 1
fi
echo "$(date) - waiting for ${DB_HOST}:${DB_PORT}..."
sleep 3
done
echo "$(date) - ${DB_HOST}:${DB_PORT} Reachable ! - Starting Daemon"
#start the daemon
exec $START_CMD
答案 2 :(得分:0)
如果您试图保持Web容器“瘦”,您可能不想添加mysql或postgres客户端软件包,只是为了检查您的数据库是否已准备就绪。一些流行的等待脚本有客户端依赖。
我刚刚创建了一个简单的Python脚本,该脚本进行本机调用以查看数据库是否正常运行。在这种情况下,我避免添加有效凭据,只是查找身份验证失败消息。这里的示例适用于Postgres,但应该很容易适应MySQL。
<强> wait_for_db.py 强>
import psycopg2.extras
from time import sleep
connect_str = "dbname='postgres' user='nobody' host='db' " + \
"password='foobar'"
while True:
try:
conn = psycopg2.connect(connect_str)
except psycopg2.OperationalError as e:
if "authentication failed" in e.args[0]:
print("Postgres is ready. Launching site.")
break
else:
print("Waiting for postgres...", e.args[0])
sleep(1)
然后在您的开发环境docker-compose.yml中设置您的Web容器,以便您有类似
的内容command: bash -c "python wait-for-postgres.py; python manage.py runserver 0.0.0.0:8000"