事象
Dockerコンテナ上でDjangoやGunicornを動かしている環境において、settings.py(例: ALLOWED_HOSTS や DEBUG など)を変更したため、コンテナ内のシェルに入って設定を反映させようとサービス再起動コマンドを実行した。
sudo systemctl restart gunicorn
しかし、次のようなエラーが発生し、コマンドが実行できなかった。
bash: sudo: command not found
bash: systemctl: command not found
ホスト側のNginxをリロード(systemctl reload nginx)してみたが、Djangoのプロセス自体は再起動されないため、settings.py の変更が反映されないままエラー(DisallowedHost など)が解消しない。
環境
- Docker / Docker Compose
- Django
- Gunicorn / uWSGI
- Nginx(ホスト側または別コンテナ)
- Linux / Ubuntu / Debianコンテナ
原因
主な原因は次の2点である。
1. 一般的なDockerコンテナには systemd(systemctl)が存在しない
Dockerコンテナは「1コンテナ1プロセス」で動作する設計が基本であり、コンテナ内部でInitシステム(systemd / PID 1)は動作していないことが多い。
そのため、systemctl コマンドや service コマンド自体がインストールされていない、あるいは実行できない。
2. リバースプロキシ(Nginx)のリロードとWebアプリの再起動の混同
Nginxはあくまでリクエストを転送するプロキシであり、DjangoやGunicornはその裏で動くPythonプロセスである。
Nginxをリロードしても、バックエンドで常駐しているGunicornプロセス内のメモリや読み込み済み設定は更新されない。
対策
1. ホスト側から Docker Compose でサービスを再起動する(推奨)
コンテナの中に入るのではなく、Docker Composeを操作しているホスト側から対象コンテナを再起動する。
# webサービス(Djangoコンテナ)のみを再起動する場合
docker compose restart web
# docker-compose (v1) の場合
docker-compose restart web
※ web の部分は、プロジェクトの compose.yaml(または docker-compose.yml)で定義されているサービス名に合わせて変更する。
2. ソースコードをイメージにビルドしている構成の場合
もし settings.py などのソースコードをボリュームマウント(Bind Mount)せず、Dockerfileの COPY . /app などでイメージ内に埋め込んでいる場合は、単なる restart では変更が反映されない。
その場合は、再ビルドとコンテナ再作成を行う。
docker compose up -d --build web
3. コンテナ内からGunicornプロセスを直接再起動する場合(代替策)
ホスト側の操作権限がなく、コンテナ内からどうしても再起動させたい場合は、GunicornマスタープロセスにHUPシグナルを送るか、プロセスをキルしてエントリーポイントに再起動させる。
# GunicornのマスタープロセスPIDを確認
ps aux | grep gunicorn
# HUPシグナルを送って設定をリロード(Graceful reload)
kill -HUP <マスタープロセスのPID>
または、コンテナのメインプロセス(PID 1)であれば、コンテナそのものが終了してDockerの restart: always 等で自動再起動されるように kill 1 を行う方法もある。
4. 反映の確認
コンテナログをストリーミング表示し、Djangoが再起動して新しい設定でリクエストを受け付けているか確認する。
docker compose logs -f web
先ほどまで発生していた DisallowedHost やエラーログが消え、正常に応答していれば対応完了である。
まとめ
- Dockerコンテナ内で
systemctlは使えないのが一般的である。 - Djangoの設定変更を反映したい場合は、ホスト側から
docker compose restart <サービス名>を実行するのが確実かつ安全である。 - NginxのリロードだけではバックエンドのDjango設定は更新されない。