先日、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 で動作する、というのをどこかで読んだ。
つまり、こういうことだ。
- コンテナが起動すると、
CMD
で指定されている uWSGI がプロセス ID 1 で実行される。 - uWSGI はデーモンモードで動作するように設定ファイルで指定されているので、デーモンをフォークして自分自身は死ぬ。
- プロセス 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 で動いている。
教訓:コンテナで起動するプログラムはデーモンモードにするな