Django, PostgreSQL, nginx, Docker を使ってwebアプリを作ったので、備忘録も兼ねて環境構築周りの話とか残しておきます。
作ったのはこんな感じのサイトで、MVみたいな映像作品を映像作家と紐づけて管理するためのシステムを作りました。
ディレクトリ構成
. ├── .env ├── docker-compose.prod.yml # 本番環境用のcomposeファイル ├── docker-compose.yml # 開発環境用のcomposeファイル ├── Dockerfile ├── gunicorn.conf ├── README.md ├── requirements.txt └── src # Djangoのソースコード
開発環境、本番環境を共にDockerコンテナで動かしています。
それぞれ構成が異なるため、composeファイルを分けています。
使用するファイルの指定は -f
オプションでできるので、 docker compose -f docker-compose.prod.yml up -d
のようにすると本番環境が立ち上がります。
docker-compose.yml
の場合は指定は必要ありません。
開発環境
開発環境ではDjango用のコンテナとPostgreSQL用のコンテナの2つを起動します。 composeファイルはこんな感じ。
version: "3" services: db: image: postgres:16.0 env_file: .env ports: - "54320:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 volumes: - db-data:/var/lib/postgresql/data/ web: build: . command: python manage.py runserver 0.0.0.0:8000 env_file: .env environment: - ENV="dev" volumes: - .:/code ports: - "8000:8000" depends_on: db: condition: service_healthy volumes: db-data:
.env
でPOSTGRES_USER
とPOSTGRES_PASSWOR
を定義しておきます。
注意すべきなのはhealthcheckの部分です。 普通に書くだけだと PostgreSQL が立ち上がる前に Django がDBに接続しようとしてしまうので、ヘルスチェックで立ち上がったことを確認するようにすることが必要です。
また、Django の settings.py
で次のように記述すると、開発環境でのみ DEBUG=True
になります。
ENV = os.getenv('ENV') if ENV == "dev": DEBUG=True else: DEBUG=False
composeファイルで環境変数 ENV
を設定しているのでそれを読み出し、'dev'
の場合はデバッグを有効にしています。
pythonの os.getenv()
などはstr型を返すので、 DEBUG=True
のようにして直接ブール値を設定することはできません。
Dockerfile はこんな感じです。
FROM python:3 ENV PYTHONUNBUFFERED 1 RUN mkdir /code WORKDIR /code ADD requirements.txt /code RUN pip install -r requirements.txt ADD . /code/ WORKDIR /code/src RUN mkdir -p /var/run/gunicorn RUN python3 manage.py collectstatic --noinput CMD ["gunicorn", "app.wsgi", "--bind=unix:/var/run/gunicorn/gunicorn.sock"]
CMD
に本番環境用のコマンドがありますが、composeファイルで開発サーバー起動のコマンド(python manage.py runserver 0.0.0.0:8000
)に上書きされます。
本番環境
本番環境ではDjango用コンテナ、PostgreSQL用konntena、nginx用コンテナの3つを起動します。 composeファイルはこんな感じ。
version: '3' version: '3' services: db: image: postgres:16.0 container_name: god-movie-collection-db env_file: .prod.env ports: - "54320:5432" healthcheck: test: ["CMD-SHELL", "pg_isready -U postgres"] interval: 5s timeout: 5s retries: 5 volumes: - db-data:/var/lib/postgresql/data/ restart: always web: build: . container_name: god-movie-collection-web env_file: .env volumes: - .:/code - gunicorn:/var/run/gunicorn restart: always depends_on: db: condition: service_healthy nginx: image: nginx:1.17.7 container_name: god-movie-collection-nginx depends_on: - web ports: - "80:80" volumes: - ./gunicorn.conf:/etc/nginx/conf.d/default.conf - gunicorn:/var/run/gunicorn restart: always volumes: db-data: gunicorn: driver: local
webサーバーとDjangoの間のインターフェースとしてgunicornを使うので requirements.txt
に追記します。
僕のはこんな感じです。
Django==5.0 psycopg2==2.9.9 django-bootstrap4==23.2 gunicorn==21.2.0
gunicorn.conf
にはこのように書きます。
upstream gunicorn-django { server unix:///var/run/gunicorn/gunicorn.sock; } server { listen 80; server_name localhost; location / { try_files $uri @gunicorn; } location @gunicorn { proxy_pass http://gunicorn-django; } }
おまけ
webアプリを外部に公開するのはCloudflare Tunnel を使うと便利だったのでおすすめです。
最後に
Djangoでwebアプリを開発するときの環境構築について忘れないうちにまとめておこうと思って書いてみました。 少しでも力になれたら嬉しいです。