30分で試すAzure App ServiceのCI/CD

この記事は [リンク情報システム](https://www.lis.co.jp) の「[2020新春アドベントカレンダー TechConnect!](https://qiita.com/dgkz/items/5131349d56354b33ee97)」のリレー記事です。
TechConnect! は勝手に始めるアドベントカレンダーとして、engineer.hanzomon という勝手に作ったグループによってリレーされます。
（リンク情報システムの[Facebookはこちら](https://www.facebook.com/lis.co.jp/)から）

# はじめに
今さらながらCI/CDをやってみたのでまとめておきます。

Azure DevOpsを使用してApp Service(Dockerコンテナ)のCI/CD環境をつくりました。
AzureもCI/CDも初心者です。間違っているところは教えて下さい。

# 必要なもの
- git
- Azureアカウント

# ソースコードを準備
## App Serviceのクイックスタートサンプルを使う
https://github.com/yiliaomsft/python-hello-world

```bash
# クローン
git clone https://github.com/yiliaomsft/python-hello-world.git
cd python-hello-world
# リモートリポジトリの削除
git remote remove origin
```
## Azure DevOps
すべてのサービスへ移動。
![000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/de2d708e-c11e-56ce-9c94-ad98512144b4.png)
「Azure DevOps」を選択。
![001.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/66f9d9e9-3072-5c98-a445-ff299ae1f35d.png)
赤枠のリンクをクリック。
![002.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/2bcef93f-3cda-632f-f211-64a9c43a9efa.png)
### organization作成
![003.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/6fd737f6-5bdb-3faf-63aa-75bbfbdc2a67.png)
「Continue」
![004.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/afc5a0c7-92a7-070e-acc3-81e389f8d068.png)
ユニークなorganization名を付けて「Continue」
![005.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/0c6b394d-3a9a-b234-dea5-15b2d65ec09a.png)

### project作成
適当な名前を付けて「Create project」
![006.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/ea5bb837-a4af-cafd-b9ca-6f91b7db1b2c.png)
### Reposにソースコードをpush
コピペ推奨。
![007.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/8a4d8cb8-85c4-c6c7-1feb-df0a38aa3a5a.png)

コマンドはこんな感じ。

```bash
git remote add origin YOUR_REPOSITORY_URL
git push -u origin --all
```

pushされていることを確認。
![008.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/aec69f95-12db-f403-b64c-3ac2d802c8e9.png)

# コンテナーレジストリ作成
「コンテナーレジストリ」を選択。
![009.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/8a49c0c1-d368-0d47-64da-9d80ba721c75.png)
「追加」
![010.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/084667e7-4b44-911d-4df5-7219ce7ac9e0.png)
リソースグループを作成、管理者ユーザーを「有効」にして「作成」
![011.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/804535c9-3289-ce6b-5c0f-1cb8704daf7a.png)

## Docker Registry service connection作成
![012.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/526adc09-0b9c-33ef-0d80-ffffb08df3c5.png)
「Docker Registry」を選択して「Next」
![013.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/7e4d8ce3-0cb7-76cb-875c-9bed1b0602c8.png)
先程つくったコンテナーレジストリを指定。名前はお好みで。
![014.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/6821c616-b779-0806-95a6-8ac68d82dc99.png)

# ビルドパイプライン作成
![015.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/f77c3783-468b-4a9b-4b3c-97f3fbcf2730.png)
「Azure Repos Git」を選択。
![016.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/5d9edcf8-0740-9dce-0ee3-88fa3535ab7b.png)
「Starter pipeline」を選択。
![017.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/ae154c35-6c09-10cf-1638-fdee5f6499b4.png)
13行目以降を消して「Show assistant」をクリック。
![018.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/3e269703-8c6d-a400-b915-c3c52ad478b8.png)
「Docker」を選択。
![019.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/a674031a-0899-26d7-4707-5e235daef919.png)
Container registryには先程つくったservice connection、
Container repositoryは何でもOK、
Commandは「buildAndPush」を選択して「Add」
![020.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/c5567e40-0b56-326a-1199-7c1c57c57cc2.png)
yamlに反映されていることを確認して「Save」
![021.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/846babdc-1bbd-d105-25ce-f165ff4892a7.png)
![022.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/84af3e06-aad7-1202-5200-7e124c643bfe.png)
## 動かす
![023.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/89b84fba-efb5-b14c-79c9-3a617ed35e82.png)
![024.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/f4aea70b-97b9-a105-dd71-8a482f31768c.png)
問題なく動いた。
![025.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/978b26d4-9fe9-c531-be04-5eafa67a7b5f.png)
## コンテナーレジストリを確認
「myapp」イメージがpushされていることを確認。
![026.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/2e635e34-30c2-fe40-a59a-87f1d9c8875c.png)
# App Service作成
「App Service」を選択。
![027.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/edb2b7a0-7486-7f99-a529-87e88f62613c.png)
「追加」
![028.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/3d01f061-55b9-a1a9-1b10-6808c822b718.png)
ユニークな名前を付け、Dockerコンテナー、Linuxを選択して次へ。
![029.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/94b05c61-7f4b-bb24-93a4-9fc9428a5a99.png)
先程pushしたイメージを選択して「確認および作成」
![030.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/368a4827-e106-0769-c307-f7e23106c72c.png)
「作成」
![031.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/94a0876d-3568-dcda-d3ad-8eb8edd5e7ae.png)
## 確認
概要のURLから確認。
![032.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/a2a7fae1-f33c-5311-f39e-c741f7194d1b.png)
問題なく表示された。
![033.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/73d220c4-2119-eff7-1b58-3692a525651b.png)

# リリースパイプライン作成
![034.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/bb7ecf7c-f19d-0053-1fcc-3a59dde3c866.png)
「Azure App Service deployment」を選択して「Apply」
![035.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/645bd830-c0b4-3415-706a-cd415186060f.png)
赤枠のリンクをクリック。
![036.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/0b1844fa-5daf-e263-d48e-5723481b0fe7.png)
サブスクリプション選択して「Authorize」
![037.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/1df8470c-c699-c8bf-8981-1c1683972a00.png)
これまでに作成したものをそれぞれ選択もしくは設定。
<font color="Red">※Registryには「.azurecr.io」を付けるのを忘れずに</font>
![038.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/144d8476-5a99-4ec9-b970-5c4bf07d869d.png)
Artifactsは使用しないためチェックを入れて「Save」
![039.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/c8314e0b-8010-4f31-5460-b6ca749f36f9.png)
「OK」
![040.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/d90231f4-83a8-12a0-db33-82d7485092b8.png)
「Add an artifact」をクリック。
![041.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/358d49f9-a934-dcb2-a8ab-50cc4e4c0665.png)
先程つくったビルドパイプラインを選択して「Add」
![042.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/a5262623-69db-5a47-3ab4-01577831f13c.png)

![043.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/dc34c617-247b-f022-ea5e-51551314d6ab.png)
masterブランチを選択して「Save」
![044.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/d5335ed2-48a7-f74d-09e9-bb9f0a9aa30b.png)
「OK」
![045.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/b06575f6-6400-907f-0e12-de8e96e233c5.png)
# 自動ビルド・リリースを動かしてみる
「Hello World!」を「hello world!」に修正して「Commit」
![046.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/c1669221-1c59-2ab4-6874-256b56f1e602.png)
「Commit」
![047.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/35bc6abd-6858-7057-e7ad-0e55200ab286.png)
## ビルド
masterブランチに変更が入ったためビルドが始まる。
![048.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/f31c0443-b695-cdb4-1844-3a754a0b8a55.png)
ビルド完了。
![049.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/fd6329d6-1b77-60e7-41df-b514f277ce78.png)
## リリース
ビルドが終わり次第、リリースが始まる。
![050.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/b318c626-82ee-caab-dd1e-c1499e0e8735.png)
リリース完了。
![051.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/427d4508-3c8b-a127-2c54-4141ae7a1649.png)
## App Serviceを確認
「Hello World!」が「hello world!」に変わっていることを確認。
![052.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/f097b032-9339-406d-1535-4d7058159940.png)
# （おまけ）自動テスト
自動テストには[Test Plans](https://azure.microsoft.com/ja-jp/services/devops/test-plans/)を使うものかと思っていたところ、公式に以下の記載を発見。
> CI/CD ワークフローに自動テストは必要ありませんか?Azure Pipelines の使用

Azure Pipelinesに[Container Structure Test](https://github.com/GoogleContainerTools/container-structure-test)用のTaskがあったので、ビルドパイプラインに組み込んでみる。

## テスト用のファイルを作成
「hello-world.py」が存在するかチェックするだけ。
![053.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/04f84a22-50e2-b810-13d7-27384cee0082.png)

```yml:cst.yml
schemaVersion: '2.0.0'

fileExistenceTests:
- name: 'app'
  path: '/code/hello-world.py'
  shouldExist: true
```

## ビルドパイプラインを修正
これでイメージがpushされた後にContainer Structure Testが実行される。
![054.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/0d118ab9-8240-96f2-d24f-eb6ead0f7cb7.png)
![055.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/a5f41b3c-e3f0-08e1-a82e-8cc272e7a0fc.png)
![056.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/532463/06338a47-62fd-c980-a971-011561e6d9ca.png)

# おわりに
おつかれさまでした。

# 参考
- [Web AppsのCI/CDをAzure DevOpsで組んでみた](https://tech-blog.cloud-config.jp/2019-10-21-cicd-of-webapps-with-azure-devops/)
- [Service connections in Azure Pipelines & TFS - Azure Pipelines](https://docs.microsoft.com/en-us/azure/devops/pipelines/library/service-endpoints?view=azure-devops&tabs=yaml)
- [Azure App service for containers error: repository does not exist or may require ‘docker login’](http://ajitgoel.net/azure-app-service-for-containers-error-repository-does-not-exist-or-may-require-docker-login/)