簡體   English   中英

django 無法在 docker-compose 中連接 mysql

[英]django cannot connect mysql in docker-compose

我對 docker 很陌生,現在我試圖通過 docker-compose 在 docker 中使用 mariadb 運行 django,但我總是收到這個錯誤:

我使用Docker version 17.09.1-ce, build 19e2cf6Docker 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 server on \\'mariadb55\\' (111 "Connection denied")')

我可以在本地或遠程運行docker-compose up db后正確連接 db,我什至可以在anaconda 虛擬環境中正確運行python manage.py runserver 0.0.0.0:6001通過設置settings.py 的參數來連接db服務文件如下:

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 撰寫 mysql 連接失敗

使用 docker-compose 鏈接 django 和 mysql 容器

Django 通過 docker-compose 連接到 postgres

終於,我想通了! 關鍵是,正如@SangminKi​​m 所說,我需要在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

所以現在我們可以直接在shell中通過mysql -h 127.0.0.1 -P 3302 -u root -p來連接這個docker-mysql ,但是我們必須在django settings.py文件中使用db3306

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

您應該在settings.py文件中使用容器名稱而不是 localhost(或 127.0.0.1)。 嘗試將提供一個容器名稱db的服務docker-compose.yml使用文件container_name屬性,在更換主機名settings.py由價值container_name (確保它們位於 docker compose 為您創建的同一網絡中。)

用這個構建容器:

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 連接。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM