【三日目】最小限の構成でdocker-composeからKubernetesにデプロイする勉強会

# 概要

表題の勉強会を行った三日目の内容を記載します。全日の内容は以下のまとめページをご覧ください。

[【まとめ】最小限の構成でdocker-composeからKubernetesにデプロイする勉強会] (https://qiita.com/tamoco/items/5a5ffb448d59b3b03831/)

# 三日目のできたこと

- テスト用のコンテナイメージの作成
- CI/CD pipelinesにテストを組み込む

# 三日目の内容

## テスト用のコンテナイメージの作成

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412322/43d73096-72ca-7163-6325-e976ea3f3640.png)


簡単なテストを実行するコンテナを作成します。`python`を使ってリクエスト送り、その結果を判別します。具体的に処理を説明する、リクエストに返ってきた内容で`ぷよぷよ`という文字列が含まれていれば`sys.exit(0)`で正常終了。逆に含まれてなければ`sys.exit(1)`で異常終了になります。これは後の`GitLab CI/CD`につながります。

```python
import os
import requests
import sys

url = os.getenv('URL', 'http://localhost:3000')
check_str = os.getenv('CHECK_STR', 'ぷよぷよ')

try:
    r_get = requests.get(url)
    response = True if r_get.ok else r_get.reason
    print(r_get.text)
    if r_get.text.find(check_str) == -1:
        print(check_str + "ではないので問題です！！")
        sys.exit(1)
    else:
        print(check_str + "なので大丈夫です。")
        sys.exit(0)
except requests.exceptions.RequestException as e:
    response = str(e)
    sys.exit(1)
```

### pythonだけでテストを試す
このテストはローカルの`python`でも実行できます。予めローカルの`python`の環境で、`requests`は`Import`しておく必要があります。以下の手順でテストを実行できます。

- Pythonをインストール
  - `requests`がない場合は`pip install requests` 
- `docker-compose`で`app`を`up`しておく
  - 一番上のフォルダに移動 
  - `docker-compose up -d app`
  - `http://localhost:3000`でアクセスできることを確認
- ローカルの`python`でテストを実行
  - `python test/test.py`

### docker-compose.ymlにtestを追加

まずはコンテナを作るために`Dockerfile`を準備します。`alpine`には`requests`は含まれていないのでインストールしています。

■ Dockerfile

```dockerfile
FROM python:3.6-alpine

WORKDIR /app

COPY ./*.py /app/

RUN pip install requests

CMD ["python", "test.py" ]
```

この`Dockerfile`を元に`docker-compose.yml`でtestのサービスを追加します。

■ docker-compose.yml

```yaml
version: '3'
services:
  app:
    build:
      context: ./app      # Dockerfile保存場所
    image: registry.gitlab.com/tamoco-mocomoco/k8s-test/express:latest
    ports:                          # ポート接続
      - 3000:5000
    environment:
      PORT: 5000

  test:
    build:
      context: ./test
    environment:
      URL: http://app:5000
      CHECK_STR: "ぷよぷよ"
```

環境変数で接続先のURLやチェックする文字列を上書きしています。ここで注目すべきはコンテナの中から接続するため、`app`だったりポートがアプリ内のポート番号である`5000`になっている点です。先ほどのローカルの`python`で実行した場合は、`docker-compose`で転送された後のURLやポート番号にアクセスしていましたが、コンテナの中から接続するところを意識することが重要になります。

### docker-comopseでテストを実行する（テスト用コンテナで実行）

docker-compose でコンテナを作成してテストすることができます。

■ コンテナでテストを実行する（成功）

```bash
$ docker-compose run test
<!DOCTYPE html>
<html>
  <head>
    <title>ぷよぷよワダオ</title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1>ぷよぷよワダオ</h1>
    <p>Welcome to ぷよぷよワダオ</p>
  </body>
</html>

ぷよぷよなので大丈夫です。
```

コンテナで実行する場合は、元のソースが変更した場合は`build`しなおす必要があります。ここらへんはホットリロード（自動的にコンテナ内のソースを更新する仕組み）などの機能を追加した方がよさそうです。

ちなみにテストを失敗させたい場合は`app/express/routes/index.js`の`ぷよぷよ`という文字列を`むきむき`などに変更すると失敗します。

■ コンテナでテストを実行する（失敗）

```bash
$ docker-compose run test
<!DOCTYPE html>
<html>
  <head>
    <title>むきむきワダオ</title>
    <link rel='stylesheet' href='/stylesheets/style.css' />
  </head>
  <body>
    <h1>むきむきワダオ</h1>
    <p>Welcome to むきむきワダオ</p>
  </body>
</html>

ぷよぷよではないので問題です！！
```

## CI/CD pipelinesにテストを組み込む

`.gitlab-ci.yml`にテスト用のコンテナでテストする仕組みを追加します。テストがパスすればコンテナイメージを`build`するようにしました。

■ .gitlab-ci.yml

```yaml
image: docker:latest

stages:
  - test
  - build

variables:
  DOCKER_DRIVER: overlay

services:
- docker:dind

before_script:
- docker info
- apk update
- apk upgrade
- apk add docker-compose
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker-compose build

test:
  stage: test
  script:
  - docker-compose up -d app
  - sleep 5s
  - docker-compose run test

build:
  stage: build
  script:
  - docker-compose push
```

### Pipelineを確認する

以下の画像のとおりテストが実行されていることが確認できました。

![コメント 2020-07-16 232531.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412322/5166f0b9-a3bd-e9a5-6ce4-94e323a0cdd3.jpeg)

成功した場合は以下のような実行結果が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412322/53cac229-f09d-af3c-3814-ed1c515ba5b1.png)


失敗した場合は以下のような実行結果が確認できます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/412322/661d00e0-1c3b-dbff-a364-2a8d168f5755.png)

# 三日目を振り返って

当初はシェルスクリプトで`curl`を実行して結果を判別するカンタンなテストを準備していました。`apk add curl`を実行してCI上のコンテナに`curl`を追加してテストする仕組みを想定していましたが、若干ハマってしまったので`python`で小さく作ることにしました。

実際にテスト用のコンテナを作る場合は、`cypress`などの`e2e`のテストを実行できるコンテナを使うのがよいと思います。

[cypress] (https://www.cypress.io/)