LoginSignup
3
2

More than 3 years have passed since last update.

Django + MySQLの環境構築を通じてDockerの使い方を学ぶ

Last updated at Posted at 2020-08-26

はじめに

プログラミングスクールでRubyRailsを学んだあと、個人的な関心からPythonDjangoを触り始めたのですが、Djangoを扱い始めて最初に感じた個人的な印象は「(機能実装のための)コードを書き始めるまでの準備がそもそも、Railsと比べて難しい」というものでした。

今後、個人的に色々なアプリを作ったり、新しく学んだことを手を動かして実践したりする際の効率性を向上させるためには、その環境構築作業そのものに慣れることはもちろん、機能の実装や学習内容の実践に集中できるような体勢を整えることも必要だと感じ、コンテナ技術 ( の扱い ) について学んでみることにしました。

この記事 ( 群 ) の目的は、Django + MySQLの環境構築を通じて、Dockerの使い方の流れを学ぶこと、そして、自分用に使い回しのできるDjangoプロジェクトの雛形を作成することです。

1つ1つの記述の意味をなるべく丁寧に追っていくことによって、別言語/フレームワークを扱うときにも再現性のある知識の習得を目指していきたいと思っています。
Docker初心者による備忘録となりますが、よろしければお付き合いください。

実行環境

利用環境

- MacOS catalina 10.15.6
- Docker 19.03.8
    (- docker-desktop for Mac 2.2.0.3)
- pyenv 1.2.20

構築を目指す環境

- Python 3.7.7
- Django 3.0.8
- MySQL 5.7.31

目次

  1. venvを利用して仮想環境を準備する
    venvを利用して、特定のバージョンのPython環境を準備します。Djangoプロジェクトの作成も行います。

  2. Dockerfileの記述を考える
    Dockerfileの記述を通してDockerイメージについて考えます。

  3. docker-compose.ymlの記述を考える
    docker-compose.ymlを作成し、Djangoとそれを接続するMySQLの設定を通してDockerコンテナについて学びます。

  4. 設定ファイルを編集し docker-compose up を実行する
    Django側の各種設定を行い、$ docker-compose upを実行します。

  5. 依存関係にあるサービス間のコンテナ立ち上げタイミングを調整する
    これまでの工程だと、特定の条件下でMySQLのコンテナがDjangoコンテナより先に立ち上がらず、接続に失敗することがあります専用のPythonファイルを作って問題の解決を目指します。

  6. 開発作業
    あとは状況に応じて変更を加えつつ、開発作業に集中するだけです。

ソースコード

主な関連ファイルのソースコードを予めこちらにまとめておきます。
それぞれのファイルの記述内容については、前述した工程別記事にて説明します。

Dockerfile
FROM python:3.7
ENV PYTHONUNBUFFERED 1

RUN mkdir /code
WORKDIR /code

COPY requirements.txt /code/
RUN pip install --upgrade pip
RUN pip install -r requirements.txt

COPY . /code/

EXPOSE 8000
docker-compose.yml
version: "3"
services:
    web:
        container_name: djst_django
        build: .
        restart: always
        command: >
            bash -c "
                pip install -r requirements.txt &&
                python config/wait_for_db.py &&
                python manage.py runserver 0.0.0.0:8000
            "
        working_dir: /code
        ports: 
            - 127.0.0.1:8000:8000
        volumes:
            - .:/code
        depends_on:
            - db
    db:
        container_name: djst_mysql
        image: mysql:5.7
        restart: always
        environment: 
            MYSQL_DATABASE: $DB_NAME
            MYSQL_USER: $DB_USER
            MYSQL_PASSWORD: $DB_PASSWORD
            MYSQL_ROOT_PASSWORD: $DB_ROOT_PASSWORD
            MYSQL_TCP_PORT: 3306
            TZ: 'Asia/Tokyo'
        volumes: 
            - ./mysql/data:/var/lib/mysql/
            - ./mysql/my.cnf:/etc/mysql/conf.d/my.cnf
        ports: 
            - 3306:3306
config/wait_for_db.py
import os
import MySQLdb
from time import sleep
from pathlib import Path

os.chdir(Path(__file__).parent)
from local_settings import DB_NAME, DB_USER, DB_PASSWORD


count_to_try = 0
LIMIT_OF_COUNT = 20 # 値は必要に応じて調整


def check_connection(count, limit):
    """
    docker-compose up実行時用、時間調整のための関数。
    """
    try:
        conn = MySQLdb.connect(
            unix_socket = "/var/run/mysqld/mysqld.sock",
            user=DB_USER,
            passwd=DB_PASSWORD,
            host="db",
            port=3306,
            db=DB_NAME,
        )
    except MySQLdb._exceptions.OperationalError as e:
        count += 1
        print("Waiting for MySQL... (", count, "/ 20 )")
        sleep(3)
        if count < limit:
            check_connection(count, limit)
        else:
            print(e)
            print("Failed to connect mySQL.")
    else:
        print("Connected!\n")
        conn.close()
        exit()


if __name__ == "__main__":
    check_connection(count_to_try, LIMIT_OF_COUNT)

ご指摘などありましたら、コメントいただけますと幸いです。
よろしくお願い致します。

3
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
2