2016-07-20 206 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"