中級者に贈るｲｹｲｹDockerクイズ

# 読み飛ばしてください。
こんにちは、あるいはこんばんは。まいです。

普段意識しないような、あるいは苦しめられているDockerに関する知識をクイズにしてみました。
~~役立つかと言われればそうでもないものもありますが、~~ ぜひ楽しんでいってください。

# Q1
マウント先のディレクトリが存在しない場合、自動で作成されるのは以下のうちどちらか

```bash:A
docker run -it -v $(pwd)/hogehoge:/hoge alpine sh
```

```bash:B
docker run -it --mount type=bind,src=$(pwd)/hogehoge,dst=/hoge alpine sh
```

<details><summary>こたえ</summary>
A

`-v`オプションを使用するとからのディレクトリが生成されます。
</details>


# Q2
次のDockerfileの問題点は何ですか？

```dockerfile:Dockerfile
FROM python:3.9
ENV DEBUG_MODE=true
COPY . /app
WORKDIR /app
RUN pip install -r requirements.txt
CMD ["python", "main.py"]
```

A) ENVでデバッグモードを有効にしているため、セキュリティリスクがある
B) 環境変数がイメージに焼き付けられるため、柔軟性が低い
C) pip installの前にWORKDIRを設定しているため、インストールに失敗する可能性がある
D) 問題はない

<details>
<summary>こたえ</summary>
B

環境変数がイメージに焼き付けられるため、柔軟性が低くなってしまいます。

本番環境と開発環境で異なる設定を使用したい場合、これでやるのはちと厳しいです。
代わりに、`docker run`コマンドの`-e`引数を使用するか、`compose.yaml`ファイルで環境変数を定義するのがいいかんじです。
</details>

# Q4
次のComposeファイルの問題点は何ですか？

```yaml:compose.yaml
services:
  web:
    build: .
    volumes:
      - .:/app
    ports:
      - "5000:5000"
  db:
    image: postgres:13
    volumes:
      - /var/lib/postgresql/data
```

A) webサービスのボリュームマウントがセキュリティリスクを引き起こす可能性がある
B) dbサービスのデータが永続化されない
C) ポートマッピングが不適切
D) 問題はない

<details>
<summary>こたえ</summary>
B

現在の設定では、名前付きボリュームやホストマシンへのマウントではなく、匿名ボリュームを使用しています。これはコンテナが削除されると失われます。

データを永続化するには、こんな感じにする必要があります。

```yaml
volumes:
  - postgres_data:/var/lib/postgresql/data

volumes:
  postgres_data:
```
</details>

# Q5
次のComposeファイルの問題点は何ですか？

```yaml:compose.yaml
services:
  web:
    build: .
    ports:
      - "80:80"
  api:
    build: ./api
    ports:
      - "8080:8080"
  db:
    image: postgres:13
    ports:
      - "5432:5432"
```

A) webサービスとapiサービスが通信できない
B) すべてのサービスがホストマシンからアクセス可能で、セキュリティリスクがある
C) dbサービスが外部からアクセス可能で、セキュリティリスクがある
D) 問題はない

<details>
<summary>こたえ</summary>
C

DBへの外部からアクセス可能で、非常によろしくないです。

データベースポートを公開することは、必要でない限り避けるべきです。
代わりに、internalなネットワークを使用して他のサービスからデータベースにアクセスし、外部へ公開しないようにするべきです。

```yaml:compose.yaml
services:
  web:
    build: .
    ports:
      - "80:80"
  api:
    build: ./api
    ports:
      - "8080:8080"
  db:
    image: postgres:13
    expose:
      - "5432"
```

こんな感じに定義してあげると 、dbサービスは外部に公開されず、同一のdocker networkにある他のサービスからのみアクセス可能になります。
</details>

# Q6
次のDockerfileの問題点は何ですか？

```dockerfile:Dockerfile
FROM nginx:latest
COPY ./app /usr/share/nginx/html
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
  CMD curl -f http://localhost/ || exit 1
```

A) HEALTHCHECKコマンドが長すぎる
B) curlがnginxイメージにインストールされていない可能性がある
C) ヘルスチェックの間隔が短すぎる
D) 問題はない

<details>
<summary>こたえ</summary>
B

curlがnginxイメージにインストールされていない可能性があります。
標準のnginxイメージにはcurlが含まれていないため、このヘルスチェックはおそらく失敗するでしょう。 
</details>


# Q7
次のDockerfileの問題点は何ですか？

```dockerfile:Dockerfile
FROM python:3.9
RUN useradd -m myuser
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
CMD ["python", "app.py"]
```

A) rootユーザーでアプリケーションが実行される
B) ユーザーが作成されているが使用されていない
C) pipが最新版でないため、セキュリティリスクがある
D) 問題はない

<details>
<summary>こたえ</summary>
B

ユーザーが作成されているが使用されていません。

セキュリティ的には、アプリケーションは非rootユーザーで実行すべきです。

```dockerfile:Dockerfile
FROM python:3.9
RUN useradd -m myuser
WORKDIR /app
COPY . /app
RUN pip install -r requirements.txt
USER myuser
CMD ["python", "app.py"]
```

これであれば、myuserユーザーとして実行されます。
</details>