nginx-unitのdocker版でflaskやるとちょっと大変だった

パッケージのnginx-unitは前回の通り問題なく使えたが、dockerの方ではなかなかうまく動かず手こずった。
公式にもあまり書いてないことが多かったので、書いておく。

## dockerイメージ
### 公式doc↓
https://unit.nginx.org/howto/docker/#running-apps-in-containerized-unit

最初にapt叩くので、apt叩いたあとのイメージ作っててもいいかも。
（エラー出まくったときaptで待ちまくるのが面倒だったので…）

``` Dockerfile
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版でも必要なので、作成

``` config.json
{
  "listeners":{
    "*:8000":{
      "pass":"applications/webapp"
    }
  },
  "applications":{
    "webapp":{
      "type":"python 3",
      "path":"/www/",
      "module":"app"
    }
  }
}
```

で、アプリイメージ用のdockerfile

``` 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などを使え、ということなのか…