DockerコンテナのTeamCityを使ってみた

## 目的

CIサーバーのパイプライン構築の学習のため。  
  
CIサーバーはSaaSを使うことが多いけどJenkinsみたいに個別立てることも想定して何か手元で使ってみたかった。

## 利用するCIサーバー

Jetbrainsの[TeamCity](https://www.jetbrains.com/teamcity/)を使ってみます。
セットアップにはDockerコンテナ版を利用します。

[jetbrains/teamcity-server - Docker-hub](https://hub.docker.com/r/jetbrains/teamcity-server/)
[jetbrains/teamcity-agent - Docker-hub](https://hub.docker.com/r/jetbrains/teamcity-agent/)

## TeamCity俯瞰図

大体こんな感じ？
エージェントがビルドまで簡単にできるかは未確認。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/e94d24d1-133f-30ca-1afd-a6f1aba5510a.png)


## コンテナの設定 

まずはdocker-composeを利用してCIサーバー1,エージェント1を用意する。

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

services:
  ci:
    container_name: ci
    image: jetbrains/teamcity-server
    ports:
      - 8111:8111
    volumes: 
      - ./ci/logs:/opt/teamcity/logs
      - ./ci/data:/data/teamcity_server/datadir
    environment:
      - TEAMCITY_SERVER_MEM_OPTS="-Xmx750m"
  ci-agent:
    image: jetbrains/teamcity-agent
    environment: 
      - SERVER_URL=ci:8111
```

ライセンスはエージェント３つまで永年フリーなので、
本番運用などでは多エージェントが必要になるだろう。
一旦３つにスケールアウトしてみる。（ローカルで動かすだけならやらなくていい）

```sh
# エージェントを３つにスケールアウトする
cd /usr/local/src && sudo `which docker-compose` scale ci-agent=3
```

## 起動

まずコンテナを`docker-compose up -d`して立ち上げる。
そうするとログとデータディレクトリが永続化(特定のパスのvolumeとしてバインドされる)ようにしてある。

dataの中身はまだ空っぽ。

```sh
$ ll ci/data/
合計 0
$ ll ci/logs/
合計 24
-rw-r----- 1 root root 5352  1月 29 15:47 catalina.2020-01-29.log
-rw-r----- 1 root root    0  1月 29 15:47 host-manager.2020-01-29.log
-rw-r----- 1 root root    0  1月 29 15:47 localhost.2020-01-29.log
-rw-r----- 1 root root    0  1月 29 15:47 manager.2020-01-29.log
-rw-r----- 1 root root  532  1月 29 15:47 teamcity-javaLogging-2020-01-29.log
-rw-r----- 1 root root 3630  1月 29 15:47 teamcity-server.log
-rw-r--r-- 1 root root  103  1月 29 15:47 teamcity-wrapper.log
-rw-r--r-- 1 root root    0  1月 29 15:47 teamcity.lock
-rw-r--r-- 1 root root    4  1月 29 15:48 teamcity.pid
```

## 初回アクセス時の初期設定

初期設定をどんどんと行っていくよ。
`http://localhost:8111/mnt`にアクセスする。
proceedをクリックする。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/8d12f819-8a99-1eeb-6d3e-586354592988.png)

DBを選択する。
proceedをクリックする。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/7fa26aec-29c9-c276-6e04-c2c67bbd2e82.png)

選択できるDBの一覧。Internal以外は事前に自前で準備してあるDBを利用する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/3cd389fa-42f5-a0df-a668-ea46cdda7c3b.png)

DB初期化が終わるとライセンス条項の同意確認があるのでしっかりと良くよんで。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/444055aa-1758-5a49-e7ab-189e19eea499.png)
同意にチェックしてつぎへ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/2cf3dfb2-6fe1-833f-bdbd-62ac0448ddf6.png)

管理者ユーザーを作成する。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/d11dc42c-e156-6aa4-2db5-9147f1d118ad.png)

## ログイン後の設定

エージェント一覧。
接続されているエージェントを認証しましょう。
docker-composeのscaleで起動しなおしたエージェントは別扱いになってしまうようだ。
なにかフォルダをvolumesで永続化しないとイケないのかも？
運用では複数のエージェントをscaleコマンドで増やして利用することはないかなと思うので無視。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/b05bd170-786d-ec0e-2387-43342a60564f.png)

認証画面。所属するpoolも割当られるっぽい、本番ではリポジトリ単位とかプロダクト単位とかいろいろ使うかも。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/25618b00-89d3-93e2-bb30-60137cecbed6.png)

さて、ここでメモリがカツカツなのでスケールしたエージェントを１に戻して続きを行う。

```text:3Agents
Tasks: 115 total,   1 running,  72 sleeping,   0 stopped,   0 zombie
%Cpu(s):  1.2 us,  0.9 sy,  0.0 ni, 97.9 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  4039320 total,   453380 free,  1930564 used,  1655376 buff/cache
KiB Swap:  1008636 total,   995520 free,    13116 used.  1865048 avail Mem 
```

```text:1Agent
Tasks: 107 total,   1 running,  62 sleeping,   0 stopped,   0 zombie
%Cpu(s):  0.7 us,  0.5 sy,  0.0 ni, 98.7 id,  0.0 wa,  0.0 hi,  0.0 si,  0.0 st
KiB Mem :  4039320 total,  1631812 free,  1334484 used,  1073024 buff/cache
KiB Swap:  1008636 total,   996032 free,    12604 used.  2474988 avail Mem 
```

とりあえずはプロジェクトを作成する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/eb54a7e2-d2cd-d721-8798-cbad18557b9f.png)

リポジトリのURLから作成できる。
URLの横にあるアイコンをクリックするとGitHub,BitBucket,GitLab,Azure DevOpsのアクセス設定ができる。
設定するとタブに表示される（例：GitLab.com)
設定しておくとリポジトリを選んで指定できるようになるので楽。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/406d4742-9c70-2902-8a18-d1dfacab7bbc.png)

メモリがカツカツのまま進めているとこういう画面がロードされなかったりするので変な挙動になったらエージェントを減らしましょう。それかメモリ増設。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/e3e015a7-c43d-0d0f-4c56-b10a18d5a0d4.png)

作成されたあとはリポジトリをスキャンしてビルドステップを自動で作成してくれるが
手動でも設定できる。
※リストをキャプチャしようとしましたが消えちゃってうまく取れなかった図。自らの曇りなき眼（まなこ）でたしかみてみろ。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/465f7651-4136-9a2e-7ace-d038ce1f361d.png)

さて、せっかくなので自動で設定してもらおう。
Gradleで作成したプロジェクトのリポジトリの場合：
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/70dc154f-6010-8241-24d6-6442f150e487.png)

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/49d70ca0-b866-0fc1-2aaa-3381499a73c8.png)
早速ビルドしようぜ！といわれるままにRun.
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/8a5a568d-dad7-05dc-2a1e-d0db80372d48.png)

記念すべき最初のビルドの途中経過。
エージェントから逐次ステータスがサーバーに送られてくる。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/240bee8c-0b60-63b4-6758-ec9178a41d38.png)

無事完了。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/62b4df73-d215-986c-bdc7-591fe8e5ab72.png)

なお、内容(Artifacts)はまだ無いようです。（激ウマギャグ）
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/21555480-0738-1f7d-f607-fe083ae24935.png)

とりあえずはここまで。
このあとは静的コード解析やらデプロイやらをやっていこうと思います。

いじょ。

## バージョンアップ（アップデート）について

【今後確認予定】
**アップデートボタンでのアップデート成否**
**メジャーアップデートなどでデータフォルダの内容が影響を受ける場合の成否**

2020/02/27追記：

TeamCity 2019.2.2 (build 71923)が来ているとアプリ画面のフッターに出ていたので
コンテナを`docker-compose pull`してみました。
再起動するとめでたく新バージョンの初期化が始まりました。
また、データフォルダをバインドしているため初期化が終わるとそのまま継続使用できました。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/d5eb8784-7dad-e060-d07f-2afd18519238.png)

このバージョン情報のところにNew Version Availableみたいに表示され、クリックすると
管理画面(Administration)のアップデート(Updates)に飛びます。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/166036/06b1f24b-19cb-01be-d56a-41d46729c9e8.png)

ワーニングに表示されている通り、Docker版を使っている場合は自動アップデートが対応していないみたい。
次もマイナーバージョンアップならこのボタン押そうと思います。
データファイルなんかに影響があるアップデートならpullします。
（Initializeで変更してくれるかなぁと推測してますが）

2020/02/28追記：
ビルドエージェントのイメージを更新して再起動するとビルドエージェントは別物扱いになり
再度エージェントの認証(Authorize)が必要になる。


## ビルドエージェントのコンテナ作成について

2020/03/03追記：
java11でのビルドが必要になったのでビルドエージェントのコンテナをカスタマイズしてみました。
[TeamCityビルドエージェントコンテナにJDKを追加する](https://qiita.com/syamagami666/items/342928df285678149819)

## 参考情報

[本番仕様時の設定観点](https://www.jetbrains.com/help/teamcity/installing-and-configuring-the-teamcity-server.html#InstallingandConfiguringtheTeamCityServer-ConfiguringServerforProductionUse)