Dockerfileを書いてDockerイメージを作る練習→解決編

先日、Dockerfile を書いてイメージをビルドしたものの、コンテナが期待通りに動いてくれない、という記事を書いた。今日はその解決編。

結論を先に書くと、問題は Dockerfile じゃなくて Python のアプリケーションサーバである uWSGI の設定ファイルにあるつぎの行だった。

daemonize = file:/usr/bruschetta/bruschetta.log

この行をつぎのように書き換えたところ、期待通りに動いてくれて web アプリにアクセス、使用できるようになった。

logger = file:/usr/bruschetta/bruschetta.log

これは、なんとか原因を見つけようとして試行錯誤しながら「docker uwsgi」で検索に引っかかったいくつかのページを見ている時に気づいた。それらのページに載っている uWSGI の設定ファイルには daemonize = ... という記述がない。この記述は uWSGI にデーモンモードで動作するように指示する記述だ。そして、Dockerfile の CMD で指定したコマンドはコンテナの中でプロセス ID 1 で動作する、というのをどこかで読んだ。

つまり、こういうことだ。

  1. コンテナが起動すると、CMD で指定されている uWSGI がプロセス ID 1 で実行される。
  2. uWSGI はデーモンモードで動作するように設定ファイルで指定されているので、デーモンをフォークして自分自身は死ぬ。
  3. プロセス ID 1 のプロセスが死ぬと、コンテナも終了する。

実際に試してみよう。これが書きなおした uWSGI の設定ファイル。

[uwsgi]
http = :5000
chdir = /usr/bruschetta
wsgi-file = /usr/bruschetta/manage.py
callable = app
master = true
pidfile = /usr/bruschetta/bruschetta.pid
logger = file:/usr/bruschetta/bruschetta.log

上述したように最後の daemonize の行を logger に書き換えてある。Dockerfile も載せておく。

FROM ubuntu:20.04

RUN apt update && apt install -y python3 python3-pip git
RUN pip3 install uwsgi
RUN git clone https://github.com/takatoh/Bruschetta.git /usr/bruschetta
RUN cd /usr/bruschetta && pip3 install -r requirements.txt
COPY files/bruschetta.ini /usr/bruschetta/
RUN cd /usr/bruschetta && python3 manage.py init_db

CMD [ "/usr/local/bin/uwsgi", "/usr/bruschetta/bruschetta.ini" ]

こちらは、書き方は先日とちょっと変わっているが、実質的に変更無し。

これでビルドしたイメージからコンテナを起動する。

takatoh@apostrophe $ docker run -it -d -p 8080:5000 --name bruschetta-5 bruschetta:5

ブラウザで localhost:8080 アクセスすると、期待どおり web アプリが動作しているのを確認できた。

ちなみに、起動中のコンテナの中に入ってプロセスを確認してみると:

takatoh@apostrophe $ docker exec -it bruschetta-5 bash
root@423460e65b10:/# ps ax
  PID TTY      STAT   TIME COMMAND
    1 pts/0    Ss+    0:01 /usr/local/bin/uwsgi /usr/bruschetta/bruschetta.ini
    8 pts/0    S+     0:00 /usr/local/bin/uwsgi /usr/bruschetta/bruschetta.ini
    9 pts/0    S+     0:00 /usr/local/bin/uwsgi /usr/bruschetta/bruschetta.ini
   10 pts/1    Ss     0:00 bash
   21 pts/1    R+     0:00 ps ax

やっぱり、uWSGI がプロセス ID 1 で動いている。

教訓:コンテナで起動するプログラムはデーモンモードにするな