0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

DockerからDjangoが起動するまで――`CMD`・`ENTRYPOINT`・`manage.py`の関係

0
Posted at

DockerfileのCMDENTRYPOINT、Composeのcommandを見ていると、結局何が実行されるのか分からなくなりました。起動コマンドが決まる段階と、Djangoが初期化される段階を分けて追います。

CMDは既定値、ENTRYPOINTは実行本体

まずはexec形式で考えると整理しやすくなります。

CMD ["python", "app.py"]

docker run myappならpython app.pyです。docker run myapp bashと指定すると、CMD全体がbashへ置き換わります。

一方、次の組み合わせではENTRYPOINTが実行本体、CMDが既定の引数になります。

ENTRYPOINT ["python"]
CMD ["app.py"]

実行結果は次のとおりです。

実行方法 実際のコマンド
docker run myapp python app.py
docker run myapp test.py python test.py

ENTRYPOINT ["python", "app.py"]だけなら、docker run myapp --debugpython app.py --debugです。WebアプリではCMDだけでも十分なことが多く、実行本体を固定するCLIでは両者の組み合わせが使えます。

Composeはイメージの既定値を上書きする

ComposeのcommandCMDに相当する既定値を、entrypointENTRYPOINTを上書きします。

commandはイメージのSHELL設定内で自動実行されません。&&などを使うならシェルを明示します。

services:
  web:
    build: .
    command:
      - /bin/sh
      - -c
      - |
        python manage.py migrate &&
        exec python manage.py runserver 0.0.0.0:8000

/bin/sh -cが文字列を解釈し、migrateが成功した場合だけrunserverへ進みます。execはシェルをサーバープロセスへ置き換え、停止シグナルを受け取りやすくします。

manage.pyはDjango管理コマンドの入口

manage.pyはDjango管理コマンドの共通の入口です。

python manage.py shell
python manage.py migrate
python manage.py runserver

Djangoプロジェクト作成時のmanage.pyには、概ね次の処理があります。

import os
import sys


def main():
    os.environ.setdefault("DJANGO_SETTINGS_MODULE", "config.settings")

    from django.core.management import execute_from_command_line
    execute_from_command_line(sys.argv)


if __name__ == "__main__":
    main()

DJANGO_SETTINGS_MODULEは使用するsettingsを伝えます。Composeのenv_fileなどですでに値があれば、setdefault()は上書きしません。execute_from_command_line()は渡された管理コマンドを実行し、Djangoは設定とアプリを初期化します。

通常のPythonシェルとの違い

単にpythonを起動してもDjangoは初期化されません。python manage.py shellなら初期化済みの対話シェルが起動し、Django 5.2ではインストール済みアプリのモデルも既定で自動インポートされます。

migraterunserverは別プロセス

先ほどのCompose設定では、Djangoが1回だけ初期化されるわけではありません。

python manage.py migrate
  → Python起動 → Django初期化 → migrate実行 → 終了

python manage.py runserver
  → 別のPython起動 → Django初期化 → 開発サーバー起動

1つ目のsettingsやメモリ上の状態を2つ目が引き継ぐわけではありません。共通するのは環境変数、ファイル、データベースなどです。

この構成はローカル開発向けです。runserverは本番用ではなく、複数コンテナが各自migrationを実行する設計にも注意が必要です。

まとめ

  • CMDは上書き可能な既定コマンド・引数として使われる
  • ENTRYPOINTCMDを組み合わせると、実行本体と既定引数を分けられる
  • Composeのcommandでシェル機能を使う場合は、/bin/sh -cを明示する
  • manage.pyはsettingsを指定し、Django管理コマンドを実行する入口
  • migraterunserverは別々のPythonプロセスとしてDjangoを初期化する

参考

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

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?