パッケージのnginx-unitは前回の通り問題なく使えたが、dockerの方ではなかなかうまく動かず手こずった。
公式にもあまり書いてないことが多かったので、書いておく。
dockerイメージ
公式doc↓
最初にapt叩くので、apt叩いたあとのイメージ作っててもいいかも。
(エラー出まくったときaptで待ちまくるのが面倒だったので…)
FROM nginx/unit:1.19.0-python3.7
RUN apt-get update && apt-get install -y python3-pip \
&& rm -rf /var/lib/apt/lists/*
だけにしといて、build with name(適当な名前にしておく)
docker build -t nginx-unit-python .
flaskを動かそうとした
flask自体はVisual Studioでつくってくれるサンプルを使う。
githubはこちら
https://github.com/microsoft/python-sample-vs-learning-flask
(実際はapp.pyから動くように少々変更している)
nginx-unit用のconfig.json
これはdocker版でも必要なので、作成
{
"listeners":{
"*:8000":{
"pass":"applications/webapp"
}
},
"applications":{
"webapp":{
"type":"python 3",
"path":"/www/",
"module":"app"
}
}
}
で、アプリイメージ用のdockerfile
FROM nginx-unit-python:latest
COPY requirements.txt /config/requirements.txt
RUN pip3 install --no-cache-dir -r /config/requirements.txt \
&& rm -rf /var/lib/apt/lists/*
COPY ./config /docker-entrypoint.d/ # config.json を入れる
COPY --chown=nobody:nogroup webapp/ /www/ # chown重要
EXPOSE 8000
イメージは上で作成したローカルのイメージを使っている。
もちろん一回イメージを作らなくて、そのままaptコマンド入れても大丈夫。
一応公式のコマンドに寄せて、copyしていく。(公式はbindオプションで入れてるけど)
requirements.txt
を/config
に入れて、pip
config.json
は/docker-entrypoint.d/
に入れる
重要だったこと
webapp/
にflaskが入っていて、これを/www
に入れるのだが、そのままだと
テンプレート読み出しなどのときにpremission denied
と出てきて、動かない。
2020/08/21 13:45:42 [alert] 19#19 Python failed to import module "views"
Traceback (most recent call last):
File "<frozen importlib._bootstrap>", line 983, in _find_and_load
File "<frozen importlib._bootstrap>", line 967, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 677, in _load_unlocked
File "<frozen importlib._bootstrap_external>", line 724, in exec_module
File "<frozen importlib._bootstrap_external>", line 859, in get_code
File "<frozen importlib._bootstrap_external>", line 916, in get_data
PermissionError: [Errno 13] Permission denied: '/www/views.py'
こんな感じ。(テンプレートでも同じpermission deniedと言われる)
dockerコンテナ内は基本rootで動いてるものとばっかり思ってたので、ここでかなりハマった。
いろいろアプリの場所変えたりしてもだめ。
仕方なく思い、コンテナ内に入って、/www
以下を777に変えたらちゃんと動いた。
コンテナ内ユーザー調査
これはいったい?と思ったので、どんなプロセスがコンテナ内で動いているのか調査する。
(なお、コンテナ内でのps aux
コマンドは使えません)
docker container top [container id]
で見ると
UID PID PPID C STIME TTY TIME CMD
root 27891 27874 0 13:50 ? 00:00:00 unit: main v1.19.0 [unitd --no-daemon --control unix:/var/run/control.unit.sock]
nobody 27947 27891 0 13:50 ? 00:00:00 unit: controller
nobody 27948 27891 0 13:50 ? 00:00:00 unit: router
nobody 27949 27891 0 13:50 ? 00:00:00 unit: "webapp" application
↑こんな感じだった。
で、よく見るとunitの本体はnobody
で動いているようだ。
あとnobody
のグループも確認。コンテナ内に入って、
# groups nobody
→ nogroup
と返ってくる。
なので、copyのときに--chownオプションをつける。
(最初はdockerfileにchmodなり、chownを入れないとだめなのかな、と思ったけどオプションができたらしい)
https://ken5scal.hatenablog.com/entry/2017/10/13/DockerfileのADD/COPYに--chownオプションができた
↑参考にしました。ありがとうございます。
これでやっと問題なく動くようになった。大変
思ったこと
情報が少ないものは使うのがつらい。特にlatestバージョンについての情報が少ないものは…
急がば回れ、ということでスタンダードなuWSGIなどを使え、ということなのか…