2016-07-20 186 views
2

我正在尝试使用docker设置Django开发环境。虽然我可以连接到主机上的mysql。但是,Web容器没有与下面的错误连接到MySQL容器:Django docker容器无法连接到mysql容器,错误为“无法连接到'db'(111)上的MySQL服务器”)

django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on 'db' (111)") 

下面是泊坞窗配置和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: 重启:总是 图片:Redis的:最新 端口: - “6379:6379”

-------------- Dockerfile用于Web图像----------------------

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

什么是你的my.cnf文件看起来像数据库服务?

检查bind-address的值,并确保从Web容器连接的授予权限是正确的。

要测试,您可以将docker exec ...放入Web容器中,并尝试从那里连接到db主机。

+0

离开容器向上运行一个后整个晚上。这只是工作(发生了什么,虽然????) – sinsin

+0

说不上来 - 有一个端口冲突和其他一些服务任何机会停止?或者机器重新启动? – ldg

+0

是横空出世,搬运工,撰写重启解决这个问题......你指挥 – sinsin

0

如果Django的尝试连接到您的数据库和MySQL是没有准备好,那么你可能会看到这样的错误:

django.db.utils.OperationalError: (2003, "Can't connect to MySQL server on 'db' (111)") 

这种情况的解决方案是等待数据库服务器准备就绪在运行Web服务器之前。

我们该怎么做?

不是直接运行web服务器,而是创建并运行一个脚本,它将等待db服务器准备就绪。之后,脚本将运行Web服务器。


泊坞窗,compose.yml文件(相关部分是,当我们覆盖网: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文件。 (基本上,虽然我们不能连接到我们的数据库服务器上的指定$DB_HOST:在我们env_web文件中定义$DB_PORT,我们等待3秒,并试图再次M_LOOPS时候如果我们能够连接到服务器,然后我们运行$START_CMD即得。在我们env_web文件中定义)。

#!/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 
+0

几乎工作。我可以从Web容器或服务ping分贝容器,但它反复打印'..! - 启动守护进程“,并没有做进一步的工作。 –

0

如果你想保持你的Web容器“薄”,你可能不希望添加MySQL或Postgres的客户端软件包,只是为了检查,如果你的数据库已经准备就绪。一些流行的外部等待脚本具有客户端依赖性。

我刚刚创建了一个简单的Python脚本,这使得本地调用,看看是否DB是功能性的。在这种情况下,我避免添加有效凭证,只需查找身份验证失败消息。这里的例子适用于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) 

然后设置Web容器在你的开发环境搬运工,compose.yml让您有类似

command: bash -c "python wait-for-postgres.py; python manage.py runserver 0.0.0.0:8000"