はじめに
祝・壮瞥町コラボ👏 英国コラボもきっとあるよね? nikkieです。
DBだけでなく、Djangoアプリもdocker compose up
で動かすというテーマに取り組みました。
まだまだ突き詰められる余地があるのですが、一度セーブポイントを作ります
目次
- はじめに
- 目次
- これまで:DBだけdocker compose up
- ドキュメントの例
- 仮想環境で動かしていたDjangoアプリをdocker compose upで動かせるようにする
- 宿題事項
- 終わりに
これまで:DBだけdocker compose up
これまではDBのDockerイメージだけをdocker compose up -d
してきました。
WebアプリはDockerを使わずに、Pythonの環境(仮想環境利用)でpython manage.py runserver
を叩きます。
DBを立ち上げるためのdocker-compose.yml
はこちら
version: '3.9' services: db: image: postgres:15.3 environment: - POSTGRES_DB=badapp - POSTGRES_USER=developer - POSTGRES_PASSWORD=mysecretpassword volumes: - ./data/db:/var/lib/postgresql/data ports: - "5432:5432"
ここから始めて、docker compose up -d
でWebアプリもDBも立ち上がるようにします。
ドキュメントの例
Dockerのドキュメントには有志による日本語版が存在します。
https://matsuand.github.io/docs.docker.jp.onthefly/
日本語版ではこちら
英語版では以下にあたるようです: https://github.com/docker/awesome-compose/tree/e6b1d2755f2f72a363fc346e52dce10cace846c8/official-documentation-samples/django
この例では
- DjangoをインストールしたDockerイメージをビルドし
- それをweb、postgreSQLイメージをdbとして
docker-compose.yml
を定義
します。
そしてdocker-compose run web
にDjango開発コマンドを渡して、プロジェクト(さらにアプリケーション)と作っていきます1。
例はロケットの画面を出して終了します。
仮想環境で動かしていたDjangoアプリをdocker compose up
で動かせるようにする
以下のエントリのソースコード(SQLインジェクションできちゃうDjangoアプリ)を元にします
目指すのはdocker compose up -d
でDjangoアプリもDBも立ち上がる状態。
マルチステージビルドする、でしょ!
ドキュメントの例よりもサイズが小さく取り回しやすいDockerイメージを作るべく、マルチステージビルドしていきます。
FROM python:3.11-bookworm as builder WORKDIR /code COPY requirements.lock /code/ RUN pip install --no-cache-dir -r requirements.lock FROM python:3.11-bookworm WORKDIR /code COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages COPY bad_sql_injection /code/
- requirements.lockに沿って依存ライブラリをインストールしたイメージに、DjangoアプリのソースコードをCOPYしました
- 本当はslimイメージを使いたいのですが、psycopg22が動かなかったのでslimでないイメージにしています(宿題)
docker-compose.yml
元々あったservicesのdb
の定義に加えて、web
も定義します
version: '3.9' services: db: image: postgres:15.3 environment: - POSTGRES_DB=badapp - POSTGRES_USER=developer - POSTGRES_PASSWORD=mysecretpassword volumes: - ./data/db:/var/lib/postgresql/data ports: - "5432:5432" + web: + build: + context: . + dockerfile: Dockerfile + command: ["python", "manage.py", "runserver", "0.0.0.0:8000"] + ports: + - "8000:8000" + depends_on: + - db
これで動きました。
docker compose up
してから http://127.0.0.1:8000/todolist/ にアクセスします
宿題事項
ですが、動いているのは私の環境だから(Dockerを導入する前に仮想環境で動かしているから)です。
リポジトリをcloneした人の手元でdocker compose up
で済ますにはいくつか宿題が残っています。
- django-environを使っていますが、
.env
ファイルもイメージの中にCOPYしてしまっています- リポジトリをcloneした人も
.env
ファイルを作ればいいのですが、他の解き方も模索したいです
- リポジトリをcloneした人も
- 私の環境はDBにmigrate済みでした
docker compose run web
でpython manage.py migrate
を都度叩く必要があります
- 私の環境には、postgreSQLが参照しているファイルがすでにあります(migrateしたDBスキーマやデータがある)
- postgreSQLが参照するフォルダ(docker-compose.ymlのvolumes)を消してから立ち上げると、うまくいったりいかなかったりします(ガチャだ!!)
- DBが参照するファイルができあがる前にwebが動くとDBへの接続エラーとなり、DBは立ち上がったがwebは立ち上がりに失敗し落ちた状態になります
- この状態からは
docker compose down
とdocker compose up
を繰り返してwebもdbも両方立ち上がった状態に持っていっています(もっといいやり方が絶対あるはず!)
エントリ執筆時点で試行錯誤中でして、「これ!」という解決策が見つかったら別途エントリを執筆予定です
終わりに
ドキュメントに沿って、Django製WebアプリとDBをdocker compose up
で動かしました。
- クイックスタートのドキュメントを参考に動かした
- サイズの小さなイメージがほしくてマルチステージビルドを実施
- 別の開発者が環境構築するとき、DBのボリュームがない状態から始めて、DB -> Webアプリの順で立ち上げ、アプリにmigrateする手順の自動化が宿題事項
立ち上げる順番の指定や、Webアプリが立ち上がった後のコマンド実行を引き続き調べていきます!
- 何年も前にRailsチュートリアルをDockerで試みたときのことを思い出しました↩
- psycopg3も登場しています。https://pypi.org/project/psycopg/ 3にしたほうがいいのかな?↩