はじめに
既に書き尽くされたような記事のタイトルですが、 自分がわかりやすいように 書いた備忘録です。
独学でやってて詰まったポイントや設定ファイルの記述内容など、コメントを付けつつ書いていきます。
Djangoチュートリアルのpollsアプリをマイグレートするところまでやります。
注意:結構長いです
最終的なソースコードはこちら(github)
環境
- OS: Mac
-
Docker Desktop
- Docker version 19.03.12
- docker-compose version 1.26.2
エディタはVSCodeで、Docker拡張機能を使用しています。
コンテナへのログインや、コンテナ再起動などGUIで操作できて便利です。
開発環境を構築する
webサービス(Django)とdbサービス(MySQL)のコンテナを立てていきます。
1.作業ディレクトリ作成
最初はターミナルで操作します。
docker-compose.ymlファイルが置いてあるディレクトリ名が、コンテナ名やボリューム名の接頭辞になります。
コンテナ名が既にあるものだとうまく立ち上がらないため、他で使ってないプロジェクト名などにします。
$ mkdir sample-pj
$ cd sample-pj/ # 作業ディレクトリに移動
ファイルの配置
作った作業ディレクトリの中に、Dockerfile、docker-compose.yml、requirements.txtを配置します。
$ touch Dockerfile docker-compose.yml requirements.txt
Dockerfile編集
ここからはVSCodeで操作していきます。
[cmd + shift + m] -> [ターミナルタブ]でターミナル操作も一緒にできます。
webサービス(Django)用のdockerイメージを作成するためのコマンドを書いていきます。
Docker Hubで提供されているpython:3実行環境のイメージに、いろいろ付け加えた新しいイメージを作ります。
FROM python:3 # 元となるdockerイメージを指定
ENV PYTHONUNBUFFERED 1 # この環境変数に値を入れることでバッファを無効化する('1'じゃなくてもいい)
RUN mkdir /code # codeディレクトリを作成
WORKDIR /code # codeディレクトリに移動
COPY requirements.txt /code/ # txtファイルをcodeディレクトリに配置
RUN pip install --upgrade pip && pip install -r requirements.txt
# pipコマンドを最新にし、txtファイル内のパッケージ(後述)をpipインストール
COPY . /code/ # sample-pj/配下のファイルをcodeディレクトリにコピー
requirements.txt編集
webサービスにインストールするパッケージを指定
Django==3.1 # Django3.1
mysqlclient # pythonでMySQLに接続するためのドライバ
docker-compose.yml編集
コンテナ作成の命令
version: '3' # 1
services: # 2
db:
image: mysql:5.7 # 3
environment: # 4
MYSQL_ROOT_PASSWORD: root
MYSQL_DATABASE: django-db
MYSQL_USER: django
MYSQL_PASSWORD: django
TZ: 'Asia/Tokyo'
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
# 5
web:
build: . # 6
command: python3 manage.py runserver 0.0.0.0:8000 # 7
volumes: # 8
- .:/code
ports: # 9
- "8000:8000"
depends_on: # 10
- db
10箇所、解説します。
- version: '3'
- docker-compose.ymlのファイル形式のバージョンを指定します
- services
- dbサービスとwebサービス、2つのコンテナが起動します
- サービス名は好きな名前で大丈夫です。
[docker-compose.ymlがあるディレクトリの名前]_[サービス名]
という名前のコンテナが立ち上がります
-
image: mysql:5.7
- Docker Hubで提供されているmysql:5.7のイメージをそのまま使うため、Dockerfileは使いません
- 最新でなく5.7にしているのは、mysqlの認証方式が8.0から変わっており、webサーバからうまく接続できなかったためです
- 参考記事:PythonからMySQLへの接続でcaching_sha2_passwordのエラーが出た場合
- environment
-
MYSQL_ROOT_PASSWORD: root
- ルートユーザのパスワードを設定します
- ルートユーザ自体は自動で作成されているようです
-
MYSQL_DATABASE: django-db
- Djangoのプロジェクトで使うDBの名前を設定します
-
MYSQL_USER: django
- Djangoのプロジェクトから接続する際のユーザ名を設定します
-
MYSQL_PASSWORD: django
- 上で設定したユーザのパスワードを設定します
-
TZ: 'Asia/Tokyo'
- dbサーバのタイムゾーンを設定します
-
-
command: mysqld --character-set-server=utf8 --collation-server=utf8_unicode_ci
- コンテナ起動時に実行されるコマンドです
- MySQLのデフォルト文字コードがlatin1なので、utf8に変換します
- 参考記事:Docker公式イメージのMySQLで文字コードを指定する
-
build: .
- Dockerfileをもとにイメージをビルドします
-
.
はDockerfileがある場所です
-
command: python3 manage.py runserver 0.0.0.0:8000
- コンテナ起動時に(引数にコマンドを指定しなかったときだけ)実行されるコマンドです
- Djangoの軽量サーバーを、ポート指定して立ち上げます
- volumes
- .:/code
- カレントディレクトリを
/code
にバインドマウントします
- ports
- "8000:8000"
- 左は公開用のポート、右は転送先コンテナのポート
- 転送先ポートは、7で指定したDjangoサーバーのポートに合わせる必要があります
- depends_on:
- 先にdbサービスを起動してからwebサービスを起動するように設定します
これで、2つのコンテナを立ち上げるための準備が完了しました。
Djangoのプロジェクトを作成
webサービスのコンテナを起動し、Djangoのプロジェクト作成コマンドを実行
docker-compose run web django-admin.py startproject djangopj .
- docker-compose run web
- webサービスだけを指定します
- django-admin.py startproject djangopj .
- djangopjという名前のプロジェクトを作成します
- このカレントディレクトリは、Dockerfileで指定した
/code
です
コマンドを実行すると、プロジェクトディレクトリとmanage.pyが作られています。
コンテナの/code
ディレクトリと、現在のカレントディレクトリがバインドマウントされているためです。
$ ls
Dockerfile docker-compose.yml requirements.txt
djangopj manage.py
DBの設定を編集
djangopj/settings.py
を開き、DATABASESの項目を編集します。
DATABASES = {
'default': {
'ENGINE': 'django.db.backends.mysql',
'NAME': 'django-db',
'USER': 'django',
'PASSWORD': 'django',
'HOST': 'db',
'PORT': '3306'
}
}
NAME、USER、PASSWORDにはdocker-compose.ymlで設定したものを記載します。
HOSTにはサービス名を記載します。
各サービスを起動
$ docker-compose up -d
-dオプションはデタッチドモードです。
後ろでコンテナが動き続けます。
http://localhost:8000 にアクセスすると、Djangoのトップページが表示されると思います。
表示されない場合、コンテナの実行ログを確認してみましょう。
VSCodeのDocker拡張機能を入れている場合、左のDockerタブから簡単にログにアクセスできます。
確認したいコンテナの上で右クリック -> View Logs
dbサービスの起動完了が遅く、webサービスの起動がこけることがあるので
webサービス右クリックで Restart
をかけると解決します。
アクセスできたら、MySQL側にDjango用のDBが作られているかどうかも確認してみましょう。
同じようにdbサービスのコンテナの上で右クリックし、
Attach Shell
をクリックします。
すると、ターミナル画面でdbサービスに入った状態になるので、
mysqlにログインします。
# mysql -u root -proot
DB一覧を表示させると、、
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| information_schema |
| django-db |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
無事、django-dbが作成されていました!
pollsアプリでデータ連携の確認
webサービスとdbサービスが連携できているか確認するために、
Djangoの公式チュートリアルを参考に小さなアプリを作ります。
https://docs.djangoproject.com/ja/3.1/intro/tutorial01/#creating-the-polls-app
アプリケーションをつくる
docker-compose.ymlのあるディレクトリ(sample-pj)に移動し、以下コマンドを叩きます。
$ docker-compose run web python3 manage.py startapp polls
ls
して、pollsというディレクトリができていれば作成完了です。
モデルを作る
pollsディレクトリにあるmodels.pyを編集
from django.db import models
class Question(models.Model):
question_text = models.CharField(max_length=200)
pub_date = models.DateTimeField('date published')
class Choice(models.Model):
question = models.ForeignKey(Question, on_delete=models.CASCADE)
choice_text = models.CharField(max_length=200)
votes = models.IntegerField(default=0)
djangopj/settings.pyのINSTALLED_APPSにpollsアプリケーションを追加します。
INSTALLED_APPS = [
'polls.apps.PollsConfig', # 追加
'django.contrib.admin',
'django.contrib.auth',
'django.contrib.contenttypes',
'django.contrib.sessions',
'django.contrib.messages',
'django.contrib.staticfiles',
]
モデルをDBに適用
docker-compose.ymlのあるディレクトリ(sample-pj)に戻り、以下コマンドを叩きます。
$ docker-compose run web python3 manage.py makemigrations polls
$ docker-compose run web python3 manage.py migrate
これでDBにモデルが適用されました。MySQL側で確認してみます。
mysql> use django-db;
mysql> show tables;
+----------------------------+
| Tables_in_django-db |
+----------------------------+
| auth_group |
| auth_group_permissions |
| auth_permission |
| auth_user |
| auth_user_groups |
| auth_user_user_permissions |
| django_admin_log |
| django_content_type |
| django_migrations |
| django_session |
| polls_choice |
| polls_question |
+----------------------------+
12 rows in set (0.00 sec)
polls_choice、polls_questionテーブルが作成されました。
こちらを参考に、管理画面からデータを入れてみると、
テーブルの中身にデータが登録されているのも確認できます。
mysql> select * from polls_question;
+----+---------------+----------------------------+
| id | question_text | pub_date |
+----+---------------+----------------------------+
| 1 | test | 2020-08-21 08:58:07.000000 |
+----+---------------+----------------------------+
1 row in set (0.00 sec)
これで、webサービスとdbサービスでデータのやりとりができていることが確認できました。
あとがき
docker-compose.ymlの記述内容と、settings.pyのDATABASESの書き方が謎で
ずっとモヤモヤしていたのが、最近やっとすっきりしたので記事にしてみました。
個人的には、webコンテナをリスタートしないといけないのがイケてないので
改善の余地ありかなと思います。
VSCode拡張機能の良さが伝わってたら幸いです。