コンテナのデプロイ自動化

#はじめに
この記事では、「マイクロサービス」、「コンテナ」、「CI/CD」について初歩的な知識をまとめました。
いわゆるDXで実現したいこと、解決したい課題や目的は、企業によって様々あるかと思いますが、「マイクロサービス」、「コンテナ」、「CI/CD」といった技術を使うことで、「ビジネス追従スピードの強化」が実現できます。
コロナ影響を受ける、昨今よく言われることですが、変化の激しいビジネスの世界では柔軟な機能拡張が要求され、これを満たすようなアーキテクチャが求められています。従来のモノリスな設計思想ではなく、コンテナという技術の普及と共に、マイクロサービスという設計が注目されています。
またアジャイル開発や、DevOpsは、もう10年以上前から提唱されている、開発スピードをアップや生産性アップが期待できる開発手法ですが、コンテナ技術の普及に伴い、さらに進化しています。前半で、「マイクロサービス」、「コンテナ」、「CI/CD」について簡単に説明し、後半でコンテナをAWS環境に自動デプロイする手法を記載しました。

#マイクロサービス
まず一つ目のキーワード、「マイクロサービス」についてです。
モノリシックなシステムを、マイクロサービス化するとは、アプリケーションを機能単位で分散させ、疎結合化することです。そして分散させたアプリケーション間はAPIで連携します。その効果としては、開発範囲を限定できるので、俊敏な機能追加が可能です。またチームビルディングの面でも、開発チームの小規模化や、下部組織へシステム管理権限を委譲できるといった効果が期待できます。中央集権型組織ではなく、末端のチームや個人が、俊敏に判断し、自律的に動く組織を目指す場合に、フィットします。
一方、マイクロサービス化の課題として、設計・実装の難易度アップによる、人材コストや学習コストの増加が挙げられます。その他、権限委譲を進めたことにより、分散されたシステムや管理するチームの統制が効かなくなる点も課題として想定され、横断的な部署による支援、管理が必要になります。
マイクロサービス化を検討する際は、どの機能を分散させ権限委譲するかを考慮する必要があります。組織が大きくなってきて、より俊敏に動ける自律的な組織を目指したいという目的もなく、小さな組織が、ただ流行りのアーキテクチャだから採用しようという場合は、メリットデメリットを挙げて検討した方が良いかもしれません。
#コンテナ
上記のマイクロサービスを実現する技術として、コンテナがあります。コンテナといえばDockerが主流です。
コンテナ登場以前は、仮想マシン(OS)単位でアプリケーションを配置させるやり方でしたが、コンテナを使うと、OS上のDocker上に、コンテナ(アプリケーション)を配置することが可能です。
これにより、環境の構築が圧倒的に楽になります。従来の仮想マシンごとの環境差分はDockerが吸収してくれます。複数拠点に、同じシステムを展開する場合、以前は、各拠点の環境差分に悩まされ、構築作業が大変でしたが、仮想マシンにDockerさえインストールできれば、そのような環境差分に悩まされることはありません。またエンジニアが開発スタート時に行う、開発環境の構築も同様に楽になります。開発環境だけ、Docker使って、本番環境は従来通りというやり方も、多いのが実情なのかもしれません。
#Dockerのコマンド
Dockerの基本的なコマンドです。
### Dockerイメージの取得

```
docker pull　“123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/nginx-image”
```
"123456789012.dkr.ecr.ap-northeast-1.amazonaws.com"がホスト名で、"nginx-image"がリポジトリ名です。
### Dockerイメージ一覧を表示

```
doker images
REPOSITORY                                                                  TAG                 IMAGE ID            CREATED             SIZE
123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/nginx-image               latest              4fe1b0c04855        2 months ago        127MB
```
### コンテナの作成

```
docker run --name nginx-app -d -p 8080:80 " 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/nginx-image:latest"
1dfa0db0ed80eabe6e377481a6be25e967da78230bfb0f47c627f0742d965442
```
### コンテナの一覧表示

```
docker ps
CONTAINER ID        IMAGE                                                            COMMAND                  CREATED             STATUS              PORTS                  NAMES
1dfa0db0ed80 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/nginx-image:latest   "nginx -g 'daemon of…"   3 minutes ago       Up 3 minutes        0.0.0.0:8080->80/tcp   nginx-app
```
### Dockerイメージの作成(ビルド)

```
docker build -t 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/nginx-image:latest
```
### DockerイメージのリポジトリへのPush

```
docker push 123456789012.dkr.ecr.ap-northeast-1.amazonaws.com/nginx-image:latest
```

#CI/CD
CI/CDとは、DevOpsの中の一つの手法で、継続的インテグレーション(continuous integration)、継続的デリバリー(continuous delivery)のことを指します。システム運用後、頻繁に発生する仕様変更に対応できるよう、継続的に改修⇒結合テスト⇒デプロイメントすることをCI/CDといいます。以下のようなCI/CDパイプラインと呼ばれるパイプラインに例えられます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638724/b58c9c2f-f666-78bc-7e18-a95a482cd738.png)
最近では継続的Deploymentや、No-Deploymentという言葉も耳にするようになりました。CI/CDツールは色々ありますが、今回はCircleCIというツールを使ってみました。

以下に、DockerコンテナのAWS環境に自動デプロイするまでを示しました。Gitを使って、修正コードをPushし、AWSのECS(Elastic Container Service)にデプロイするまでの流れです。実際の環境構築は以下のサイトが詳しいです。
[CircleCI Orbsで ECR/ECS にデプロイ](https://qiita.com/shshimamo/items/76db04d5a367aa84ca92)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/638724/a90ca36c-32c5-d60a-c56f-dee98668c2cf.png)

#### 1. git push
開発者がソースコードを修正してgitでpushすると、そのpushを検知し、CirCleCIに連携されます。gitでのpush操作以降の、コンテナ起動までをCircleCIが自動で実行してくれます。
#### 2. test 
CirCleCIで、テストコードによりテストを実行します。
#### 3. build container image
設定した環境でコンテナのビルドが始まります。
#### 4. push container image
出来上がったコンテナイメージをAWSのECR(Elastic Container Registry)に登録します。
#### 5. deploy & register task definition and update service
AWSのECSでタスク定義を登録し、サービスを更新します。
#### 6. start container
更新されたサービスに従い、EC2またはFargate上でコンテナが起動します。

以下、Circleciの設定ファイル.circleci/config.ymlの記述です。コンテナのビルドとイメージのPushを記載しています。

```config.yml
version: 2.1

orbs:
  aws-ecr: circleci/aws-ecr@6.0.0
  aws-ecs: circleci/aws-ecs@0.0.8

workflows:
  build_and_push_image:
    jobs:
      - aws-ecr/build-and-push-image:
          region: AWS_REGION
          account-url: AWS_ECR_ACCOUNT_URL
          repo: '${MY_APP_PREFIX}-sample'
          tag: "${CIRCLE_SHA1}"
      - aws-ecs/deploy-service-update:
          requires:
            - aws-ecr/build-and-push-image
          family: '${MY_APP_PREFIX}-task'
          cluster-name: '${MY_APP_PREFIX}-cluster'
          service-name: '${MY_APP_PREFIX}-service'
          container-image-name-updates: 'container=${MY_APP_PREFIX}-container,tag=${CIRCLE_SHA1}'
```

#おまけ
最後にデプロイメントについて調べてみました。
#### カナリアリリース
本番環境を全ユーザに対して、一斉にリリースするのではなく、一部のユーザに先行してリリースして、段階的に全ユーザに公開していく手法です。
#### Blue-Greenリリース
現行環境とは別に新環境を用意して、ユーザのアクセス先を切り替えていく手法。新環境で問題が発生した場合は、旧環境にユーザのアクセス先を戻します。リリース後問題がない場合は、旧環境を次の新環境として利用します。