この記事で書くことと注意点
- 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
長くなったので一旦ここまでにします。
続きはこちら。