Google の container-structure-test を CircleCI で流す

# はじめに

- コンテナのテストを行う container-structure-test を使ってみる
- CircleCI に組み込み、CI/CD パイプライン上で container-structure-test を活用してみる

# container-structure-test とは

- Google が公開しているコンテナテストツール
  - https://github.com/GoogleContainerTools/container-structure-test
- コンテナイメージのバリデーションができる
  - 例: イメージ内に期待したファイルがあるか、エントリポイントの実行結果は想定通りか、など

# container-structure-test を使ってみる

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

### Dockerfile

```dockerfile:Dockerfile
FROM busybox
LABEL maintainer="tsubasaogawa"

WORKDIR /root

ENV STAGE "dev"

COPY ./docker-entrypoint.sh /root/

RUN date > /tmp/date.log

ENTRYPOINT ["sh", "./docker-entrypoint.sh"]
```

### docker-entrypoint.sh

```bash:dockedr-entrypoint.sh
#!sh -eu

# say hello
echo 'hello'

exit 0
```

## container-structure-test 用の config を作成

```yaml:.container-structure-test/config.yaml
schemaVersion: "2.0.0"

commandTests:
  - name: "it says hello"
    command: "sh"
    args:
      - "./docker-entrypoint.sh"
    expectedOutput:
      - "hello"

fileExistenceTests:
  - name: "date file exists"
    path: "/tmp/date.log"
    shouldExist: true
    permissions: "-rw-r--r--"

metadataTest:
  env:
    - key: "STAGE"
      value: "dev"
  labels:
    - key: "maintainer"
      value: "tsubasaogawa"
  exposedPorts: []
  volumes: []
  entrypoint:
    - "sh"
    - "./docker-entrypoint.sh"
  cmd: []
  workdir: "/root"
```

## container-structure-test の実行

```bash
# コンテナビルド
docker build -t tsubasaogawa/test-for-cst:0.1 .

# container-structure-test のインストール
curl -LO https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-amd64 \
  && chmod +x container-structure-test-linux-amd64 \
  && sudo mv container-structure-test-linux-amd64 /usr/local/bin/container-structure-test

# 実行
container-structure-test test \
  --image tsubasaogawa/test-for-cst:0.1 \
  --config .container-structure-test/config.yaml

====================================
====== Test file: config.yaml ======
====================================
=== RUN: Command Test: it says hello
--- PASS
stdout: hello

=== RUN: File Existence Test: date file exists
--- PASS

=== RUN: Metadata Test
--- PASS


=============================================================
========================== RESULTS ==========================
=============================================================
Passes:      3
Failures:    0
Total tests: 3

PASS
```

テストに成功するとコマンドの終了コードは `0`, Failure が生じると `1` となる。

# CircleCI に組み込む

```yaml:.circleci/config.yml
version: "2.1"

jobs:
  test:
    docker:
      - image: docker:19.03.5-git
    steps:
      - checkout
      - setup_remote_docker
      - run:
          name: "Install contrainer-structure-test"
          command: |
            apk update && apk add curl
            curl -LO https://storage.googleapis.com/container-structure-test/latest/container-structure-test-linux-amd64
            chmod +x container-structure-test-linux-amd64
            mv container-structure-test-linux-amd64 /usr/local/bin/container-structure-test
      - run:
          name: "Build container"
          command: docker build -t tsubasaogawa/test-for-cst:test .
      - run:
          name: "Run test"
          command: |
            container-structure-test test \
              --image tsubasaogawa/test-for-cst:test \
              --config .container-structure-test/config.yaml

workflows:
  version: "2"
  run_test:
    jobs:
      - test
```

## ポイント
- Docker in Docker となるので `setup_remote_docker` を有効にする
   - cf. https://circleci.com/docs/ja/2.0/building-docker-images/#%E3%81%AF%E3%81%98%E3%82%81%E3%81%AB
- container-structure-test のインストールに `curl` を利用するので、必要に応じて curl をインストールする

# 備考

- 利用したコードは以下リポジトリから clone 可
  - https://github.com/tsubasaogawa/test-for-container-structure-test