ConcourseCIをWindows環境(Docker)で試してみる

# 概要
パイプラインベースのCI/CD(継続的インテグレーション/デリバリー)ツール **Concourse CI** を試してみた時の備忘録です。
https://concourse-ci.org/

Windows環境でDockerを使って起動します。一部ハマった箇所があったのでそのメモも含みます。
更にwindows-workerの起動も試してみます。

## 環境
Windows10 pro 64bit
Docker Desktop Community ver.2.0.0.3(31259)
git for windows ver.2.21.0
Concourse ver.5.1.0


# 実装
## 作業ディレクトリの準備
作業ディレクトリを作成します、以下はその作業ディレクトリで行います。

## sshキーの生成
[keys]ディレクトリを作成し、その下に[web]と[worker]を作成します。
sshキーを作成＆コピーを行います。

```
mkdir keys\web keys\worker

ssh-keygen -t rsa -f .\keys\web\tsa_host_key -N ""
ssh-keygen -t rsa -f .\keys\web\session_signing_key -N ""
ssh-keygen -t rsa -f .\keys\worker\worker_key -N ""

copy .\keys\worker\worker_key.pub .\keys\web\authorized_worker_keys
copy .\keys\web\tsa_host_key.pub .\keys\worker
```

以下の様なツリーになります。

```
└─[workdir/]
　　└─keys/
　　　　├─web/
　　　　│　├─authorized_worker_keys
　　　　│　├─session_signing_key
　　　　│　├─session_signing_key.pub
　　　　│　├─tsa_host_key
　　　　│　└─tsa_host_key.pub
　　　　└─worker/
　　　　　　├─tsa_host_key.pub
　　　　　　├─worker_key
　　　　　　└─worker_key.pub
```

## docker-compose.ymlの用意
https://github.com/concourse/concourse-docker
から入手する。
（ID/パスワード等は実際の運用時には変更する。）
以下のような感じ。サービス名やバージョンは少し変更しています。

```docker-compose.yml
version: '3'

services:
  concourse-db:
    image: postgres:9.5
    environment:
      POSTGRES_DB: concourse
      POSTGRES_USER: concourse
      POSTGRES_PASSWORD: changeme
      PGDATA: /database

  concourse-web:
    image: concourse/concourse
    links: [concourse-db]
    depends_on: [concourse-db]
    command: web
    privileged: true
    restart: unless-stopped
    ports: ["8080:8080", "2222:2222"]
    volumes: ["./keys/web:/concourse-keys"]
    environment:
      CONCOURSE_EXTERNAL_URL: http://localhost:8080
      CONCOURSE_POSTGRES_HOST: concourse-db
      CONCOURSE_POSTGRES_USER: concourse
      CONCOURSE_POSTGRES_DATABASE: concourse
      CONCOURSE_POSTGRES_PASSWORD: changeme
      CONCOURSE_ADD_LOCAL_USER: test:test
      CONCOURSE_MAIN_TEAM_LOCAL_USER: test

  concourse-worker:
    image: concourse/concourse
    privileged: true
    links: [concourse-web]
    depends_on: [concourse-web]
    command: worker
    volumes: ["./keys/worker:/concourse-keys"]
    environment:
      CONCOURSE_TSA_HOST: concourse-web:2222
```

## docker-composeで起動
`docker-compose up -d` で起動させる。

## web画面の確認
http://localhost:8080/ にアクセスすると以下のような画面になります。

![SnapCrab_Dashboard - Concourse ‎- Microsoft Edge_2019-4-22_14-0-15_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/fd1a48ad-3dc6-e1a0-517d-5c6dd65a8bcb.png)


### web画面が表示されなかった時のメモ
`CONCOURSE_ADD_LOCAL_USER` と `CONCOURSE_MAIN_TEAM_LOCAL_USER` がないとweb画面へアクセスできないようです。
参考にした`docker-compose.yml`には上記の設定がなくアクセスできませんでした。Concourseのバージョン違いによるものかもしれません。（未検証）

また、`CONCOURSE_EXTERNAL_URL` を環境変数にして http://localhost:8080 ではなく、ローカルIPで設定する説明がありましたが、上記でも特に問題なく動きました。

### 各コンテナへのログイン
3つのコンテナが立ち上がっているので各コンテナへログインするためのdockerコマンドメモ。

```
docker exec -u root -it concourse-docker_concourse-web_1 /bin/bash
docker exec -u root -it concourse-docker_concourse-worker_1 /bin/bash
docker exec -u postgres -it concourse-docker_concourse-db_1 /bin/bash
```

## Command Line Interface(fly)のインストール
表示されたweb画面のアイコンがそれぞれ mac, windows, linux用のCLI(fly)のダウンロードリンクになっているので、環境にあったものをダウンロードする。

### バージョン確認
```
>fly -v
5.1.0
```

# 実行テスト
## fly でターゲットの確認
```
>fly targets
name   url                   team  expiry
sample http://localhost:8080 main  (省略)
```

## ログイン
```
>fly -t sample login
```
で表示されたURLにブラウザでアクセスしてログインする。

## テスト用サンプルジョブymlを用意
dockerイメージを取得して `date`コマンドを実行するだけのサンプルです。

```build_sample.yml
jobs:
  - name: job-sample
    plan:
      - task: task-sample
        config:
          platform: linux
          image_resource:
            type: docker-image
            source:
              repository: alpine
              tag: 3.5
          run: 
            path: /bin/sh
            args:
              - -c
              - -x
              - |
                date
```

## flyでジョブを登録設定
flyでジョブを登録します、`-t`が対象ターゲット指定、`sp`が`set-pipeline`のエイリアスのようです。

```
> fly -t sample sp -p build_sample -c build_sample.yml

target saved
jobs:
  job job-sample has been added:
+ name: job-sample
+ plan:
+ - task: task-sample
+   config:
+     platform: linux
+     image_resource:
+       type: docker-image
+       source:
+         repository: alpine
+         tag: 3.5
+     run:
+       path: /bin/sh
+       args:
+       - -c
+       - -x
+       - |
+         date

apply configuration? [yN]:
```

変更があれば差分を表示してくれる。
問題なければ[Y]を押下する。

webページに`build_sample`が追加される。
![SnapCrab_NoName_2019-4-22_17-27-46_No-00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/61f45b78-6abd-7b4f-2321-eb246fbbe0a9.png)

追加された状態ではステータスが[pause]になっているので、動作させるには再生ボタンを押下する。

![buid_sample_pending.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/587d9590-ccfe-ae67-44c2-1cf9d6dc45fc.png)

まだ何もしていないため、ステータスは[pending]になります。

## ジョブ起動
![build_sample_job.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/2f3b6f8c-e5fe-3f5a-da19-36cc00a77490.png)

ジョブの中にはいって右上の[+] **Trigger Build** を押下する。
開始すると以下のような画面に。

![build_sample_job_start.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/234b779c-43af-82cb-cbf9-279953ec0033.png)

成功すると以下のような画面になる。
![build_sample_job_success.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/a5e15e45-27a3-991b-73d7-3f9e2ea5e2f1.png)


# Windows-Workerの設定
windows環境下でのビルド等を行うためのwindowsワーカーの設定方法です。

## workerの確認
ワーカーは現在はlinuxのみになっています。(Dockerで立ち上げているため)

```
>fly -t sample workers
name          containers  platform  tags  team  state    version
7105cfd27737  2           linux     none  none  running  2.1
```

## 準備
1. windowsPCにてワーカー用ディレクトリを用意します。
1. サブディレクトリにワークディレクトリを作成します。
1. https://concourse-ci.org/ の[download]から `concourse-5.1.0-windows-amd64.zip` をDLし、`concourse.exe`をワークディレクトリに置きます。
1. 次に、TSAホストの公開鍵`tsa_host_key.pub` と ワーカーの秘密鍵`worker_key` も一緒におきます。

以下のような構成になります。

```
└─[workerdir]
　　└─work/
　　　　└─concourse.exe
　　　　　　├─tsa_host_key.pub
　　　　　　└─worker_key
```

## 起動
ワーカー用ディレクトリにて以下を実行します。

```
> concourse worker /work-dir .\work /tsa-host localhost:2222 /tsa-public-key .\tsa_host_key.pub /tsa-worker-private-key .\worker_key
```

起動に成功すると以下のコマンドで確認ができます。
`<win-worker>` はwindows-workerになったPC名が入ります。

```
> fly -t sample workers
name          containers  platform  tags  team  state    version
7105cfd27737  2           linux     none  none  running  2.1
<win-worker>  0           windows   none  none  running  2.1
```

## 確認
確認用に最低限の.NETコンソールアプリケーション("Hello World"を出すだけ)をビルドします。MSBuildを使用しますのでパスを通す必要があります。

```build_datdotnet.yml
resources:
  - name: code
    type: git
    source:
      uri: https://github.com/unknown-ds/DatDotNet.git
      branch: master
jobs:
  - name: build
    plan:
    - aggregate:
      - get: code
        trigger: true
    - task: compile
      privileged: true
      file: code/Pipeline/compile.yml
```

上記ymlファイルをジョブに設定します。

```
> fly -t sample sp -p build_datdotnet -c build_datdotnet.yml
```

結果は以下の様になりました。~~色が微妙です。~~結果がワーニングになってしまいました。
![win_worker_build.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/303806/44c8485e-a891-2438-bfc7-91447c8f1be7.png)

exeファイルは `concourse.exe` のワークディレクトリ以下から 
`\containers\<?????>\tmp\build\<?????>\code\DatDotNet\bin\Debug\DatDotNet.exe` 
にありました。（<?????>は毎回変わる）
動作も問題ないようですので、ビルドは成功しているようです。

### エラー対処例
実行時に
`failed to create hardlink for bind mount: symlink (省略) A required privilege is not held by the client.`
というエラーが出る場合は、`concourse.exe`を管理者権限で起動すると良いです。


# まとめ
とりあえず動かすだけができたが、windowsワーカーについてはまだ検証不足です。
制御は `fly` コマンドで行うようになっているようで、ここら辺をもう少し調べていかないとならないが日本語情報が少ない。。:expressionless: