0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

Django環境をDockerで構築(Django+Nginx+PostgreSQL)

Last updated at Posted at 2023-12-29

この記事で書くことと注意点

  • Django4.2LTSをDockerコンテナで構築する。
  • プロキシは通しません。
    プロキシのある環境で扱う場合は、環境変数(http_proxyなど)を書いて対応してください。
  • Gunicornを使ってHTTPをコンテナネットワーク内で内部公開し、それをNginxでhttpsとして外部公開(リバースプロキシ)する。
  • 構築メモのつもりで書いてるので、後々加筆修正するところも出てくるかも。

Docker&docker-composeインストール

こちらの記事を参照ください。RHEL系ならこれでいけます。
Ubuntuとかはやり方違うと思います。

コンテナ構築

一旦、このようにしたい(docker-compose up -dする前の状態)

# tree
.
├── code
├── containers
│   ├── django
│   │   ├── dockerfile
│   │   ├── init.sh
│   │   ├── requirements.txt
│   │   └── supervisord.conf
│   ├── nginx
│   │   ├── default.conf
│   │   └── dockerfile
│   └── pgsql
│       └── dockerfile
├── data
├── docker-compose.yml
└── logs

プロジェクトフォルダ作成

$ su
# mkdir django-project
# cd django-project

各種ファイル保管用ディレクトリを作成

# mkdir -p containers/django containers/nginx containers/pgsql
# mkdir -p code data logs

コンテナビルド(docker-compose)用のファイルを作成

# touch docker-compose.yml
# touch .env
# chmod 666 docker-compose.yml .env 
docker-compose.yml
version: "3.9"
services:
  db:
    container_name: ${POSTGRES_CONTAINER_NAME}
    build:
      context: .
      dockerfile: ./containers/pgsql/dockerfile
    platform: linux/x86_64
    volumes:
      - ./data:/var/lib/postgresql/data
    expose:
      - ${POSTGRES_PORT}
    env_file:
      - .env
    restart: always
    logging:
      driver: json-file
      options:
        max-size: 1m
        max-file: '3'
    networks:
      django_network:
        ipv4_address: ${POSTGRES_ADDR}

  app:
    container_name: ${DJANGO_CONTAINER_NAME}
    build:
      context: .
      dockerfile: ./containers/django/dockerfile
    volumes:
      - ./code:/code
      - ./logs/django:/log
    expose:
      - ${DJANGO_PORT}
    tty: true
    stdin_open: true
    privileged: true
    entrypoint: "/tmp/init.sh"
    env_file:
      - .env
    restart: always
    depends_on:
      - db
    logging:
      driver: json-file
      options:
        max-size: 1m
        max-file: '3'
    networks:
      django_network:
        ipv4_address: ${DJANGO_ADDR}

  web:
    container_name: ${NGINX_CONTAINER_NAME}
    build:
      context: .
      dockerfile: ./containers/nginx/dockerfile
    tty: true
    stdin_open: true
    volumes:
      - ./code:/code
      - ./containers/nginx/default.conf:/etc/nginx/conf.d/default.conf
      - ./logs/nginx:/var/log/nginx
    ports:
      - ${NGINX_HTTP_PORT}:80
    restart: always
    depends_on:
      - app
    environment:
      TZ: Asia/Tokyo
    logging:
      driver: json-file
      options:
        max-size: 1m
        max-file: '3'
    networks:
      django_network:
        ipv4_address: ${NGINX_ADDR}

networks:
  django_network:
    driver: bridge
    ipam:
      driver: default
      config:
        - subnet: ${NETWORK_SUBNET}
.env
TZ = Asia/Tokyo
NETWORK_SUBNET = 172.16.0.0/24

DJANGO_CONTAINER_NAME = app
DJANGO_PORT = 80
DJANGO_ADDR = 172.16.0.2

NGINX_CONTAINER_NAME = web
NGINX_HTTP_PORT = 80
NGINX_ADDR = 172.16.0.3

POSTGRES_CONTAINER_NAME = db
POSTGRES_PORT = 5432
POSTGRES_ADDR = 172.16.0.4
POSTGRES_USER = admin
POSTGRES_PASSWORD = password
POSTGRES_DB = appdb

Djangoコンテナ用のファイルを作成

# touch containers/django/dockerfile containers/django/requirements.txt
# touch containers/django/supervisord.conf containers/django/init.sh
# chmod 666 containers/django/*

dockerfile

Django用コンテナのイメージを生成するための設定。

containers/django/dockerfile
FROM python:3.12-bookworm
ENV PYTHONDONTWRITEBYTECODE=1
ENV PYTHONUNBUFFERED=1
RUN apt-get update && apt-get -y upgrade
RUN apt -y install iproute2 iputils-ping net-tools traceroute tcpdump
RUN apt -y install postgresql16-client
RUN curl -sL https://deb.nodesource.com/setup_20.x | bash -
RUN apt install -y nodejs npm
RUN mkdir /code
WORKDIR /code
COPY ./containers/django/requirements.txt /code/
RUN pip install --upgrade pip
RUN pip install -r requirements.txt
RUN apt-get install -y supervisor
COPY ./containers/django/supervisord.conf /etc/supervisor/supervisord.conf
COPY ./containers/django/init.sh /tmp/
RUN chmod +x /tmp/init.sh
設定 補足説明
ベースイメージ DjangoはPythonコンテナをベースに作る。2023/12時点で最新のものとした。
PYTHONDONTWRITEBYTECODE=1 __pycache__、.pycを作らせない。
PYTHONUNBUFFERED=1 標準出力、標準エラー出力のバッファリングを行わない。
Node.jsインストール TailwindCSSを使うために必要となる。
pipインストール requirements.txtに書かれたライブラリをインストールする。
codeディレクトリは、volumeマウントで上書きされるので、コンテナが立ち上がるときにはrequirements.txtごと上書きされる。
supervisor 元となるイメージファイルには、systemctlがないためプロセス管理できない。そのため、supervisorを入れてコンテナ内でプロセス管理させる。
init.sh これをinitプロセス(PID1)として起動させる。

requirements.txt

Djangoイメージを作るときにインストールさせておきたいライブラリを記述。
dockerfile内に、RUN pip install ~~~って書いてもいいのだが、
pipインストールしたいものだけ分けて書いてあった方が分かりやすいと思ってこうした。
いずれも2023/12時点の最新バージョンとした。

containers/django/requirements.txt
Django==4.2
gunicorn==21.2.0
djangorestframework==3.14.0
django-import-export==3.3.4
django_apscheduler==0.6.2
django_extensions==3.2.3
django-debug-toolbar==4.2.0
django-cors-headers==4.2.0
psycopg2-binary==2.9.9
mkdocs==1.5.3
設定 補足説明
Django 最新LTS版
restframework RESTfulAPIを作るライブラリ
import-export Django管理サイトでDBの中身をインポートしたり、エクスポートできるようになるライブラリ
apscheduler 定期実行に使うことができるライブラリ(cron使うでもいいと思う)
extensitons 色々な拡張機能が入ったライブラリ
debug-toolbar デバッグ用の拡張機能が入ったライブラリ
django-cors-headers CORSを設定するためのライブラリ
psycopg2-binary PostgreSQLに接続するためのライブラリ
mkdocs 静的ドキュメントを作るためのライブラリ
containers/django/supervisord.conf
[unix_http_server]
file=/var/run/supervisor.sock
serverurl=unix:///var/run/supervisor.sock

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock

[supervisord]
nodaemon=true
logfile=/var/log/supervisor/supervisord.log
logfile_maxbytes=50MB
logfile_backups=3
pidfile=/var/run/supervisord.pid
childlogdir=/code/log/supervisor

[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[program:gunicorn]
command=gunicorn --config /code/config/gunicorn_settings.py
autostart=true
autorestart=true
startsecs=10
startretries=3
stdout_logfile=/code/log/supervisor/gunicorn_stdout.log
stderr_logfile=/code/log/supervisor/gunicorn_stderr.log

[include]
files = /etc/supervisor/conf.d/*.conf

[supervisord]

supervisordプロセス自体の設定。

設定 補足説明
logfile supervisordプロセスのログ出力
logfile_maxbytes 指定サイズ以上になったらローテーション
logfile_backups ローテーションで残すログファイル数
nodaemon trueにするとデーモン化しない(dockerで動かす場合はtrue)
pidfile PIDファイルのパス
childlogdir 子プロセスのログ・ファイル保存先パス

[program:gunicorn]

gunicorn用に設定。

設定 補足説明
command プロセス起動コマンド
numprocs 起動するプロセス数
autostart 自動起動設定
autorestart プロセス終了時の再起動設定
startsecs 起動に指定秒数以上かかる場合は起動失敗とみなす
startretries 起動失敗した場合のリトライ回数
pidfile PIDファイルのパス
childlogdir 子プロセスのログ・ファイル保存先パス

コンテナ起動時の設定

containers/django/init.sh
#!/bin/bash
if [ -f /code/config/gunicorn_settings.py ]; then
    /usr/bin/supervisord
fi
cd /code
npm init -y
npm install -D tailwindcss@3.3.6 postcss-cli@11.0.0 autoprefixer@10.4.16 cssnano@6.0.2
npx tailwindcss init -p

while true
do
sleep 10
done
設定 補足説明
/usr/bin/supervisord supervisorを起動させる。(gunicornが起動する)
gunicornの設定ファイルがない場合は起動しないようにしている。
npm init npmフォルダを初期化する
tailwindcss ほぼCSSを書かなくても良くなって、class名も共通化できる便利なやつ
これをPostCSSのプラグインとして使う
postcss-cli CSS変換ツール(PostCSS)をnpmスクリプトとしてCLIで使用できるようにするもの、らしい
色々なプラグインを追加できる
autoprefixer ベンダープレフィックスをつけてくれるPostCSSのプラグイン
cssnano cssをminify化するやつ
while ~ done コンテナ内でシェルスクリプトを起動させて終了するとコンテナが落ちてしまうため、無限ループ処理させて落ちないようにしている

Nginxコンテナ用のファイルを作成

2023/12時点で最新のdebian版とした。(alpine版は慣れない・・・)

# touch containers/nginx/dockerfile
# chmod 666 containers/nginx/*
containers/nginx/dockerfile
FROM nginx:1.25-bookworm
containers/nginx/default.conf
upstream django {
    server app:80;
}

server {
    server_name  myapp.com;
    listen 80;

    root        /code;
    access_log  /var/log/nginx/access.log;
    error_log  /var/log/nginx/error.log;

    location /static/ {
        autoindex on;
        alias /code/static/;
    }

    location /media/ {
        autoindex on;
        alias /code/media/;
    }

    location / {
        proxy_pass http://django/;
        proxy_set_header Host $host;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_redirect off;
    }
}
設定 補足説明
location /static/ 静的ファイルのうちjsファイルやcssファイル、その他ページ構成に必要なファイル(画像ファイルなど)を配布するディレクトリの設定
location /media/ 画像や動画などのメディアファイルを保存するディレクトリ
例えば、アプリからアップロードする画像だとかの保存先になる

PostgreSQLコンテナ用のファイルを作成

# touch containers/pgsql/dockerfile
# chmod 666 containers/pgsql/*
containers/pgsql/dockerfile
FROM postgres:15-bookworm

Dockerイメージ&コンテナビルド

docker-compose upすると、dockerイメージがない場合はイメージビルドしつつコンテナもビルドしてくれます。
-dオプションをつけることで、デーモン起動します。

# docker-compose up -d

dockerコンテナが起動していることを確認します。
STATUSがUpになっていれば正常に動作しています。

# docker ps
CONTAINER ID   IMAGE                COMMAND                  CREATED         STATUS         PORTS                               NAMES
ed1baf809bfe   django-project_web   "/docker-entrypoint.…"   3 seconds ago   Up 2 seconds   0.0.0.0:80->80/tcp, :::80->80/tcp   web
5b0d00822fca   django-project_app   "python3"                3 seconds ago   Up 2 seconds   80/tcp                              app
6db1af530d87   django-project_db    "docker-entrypoint.s…"   3 seconds ago   Up 2 seconds   5432/tcp                            db

長くなったので一旦ここまでにします。

続きはこちら。

0
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
0
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?