21
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Code4兄弟(3兄弟)を使ってリポジトリにPushしたらDockerイメージをECRにPushする

Last updated at Posted at 2018-03-19

はじめに

みなさんはどのようにソースコードをデプロイしていますでしょうか?
今更ながらですが、弊社のデプロイフローはAWSの Code兄弟 を利用しておりまして、その流れと各サービスの概要を私風にまとめて書きます。
決して4,5月から増える新入社員用の教育資料に使おうとか考えてませんよ…

※追記した内容でCodeDeployを使わないパターンを書きました。

使用するサービス

使用しているサービスを簡単に紹介します。

AWS CodeCommit

AWSが提供するフルマネージド型のソースコントロールサービス。おそらく本体はGithubだと思ってます。
ほぼ無料でプライベートなGitリポジトリを使用することができます。
ただGithubと比べてしまうと、issueが立てられなかったり、PRがなかなか使いづらかったりと不便な点はあります。
([参考ページ] (https://docs.aws.amazon.com/ja_jp/codecommit/latest/userguide/welcome.html))

AWS CodeBuild

AWSが提供する完全マネージド型のビルドサービス。テストやCIを実行することができます。
独自のビルドサーバーのプロビジョニング、管理、スケーリングが不要になります。
(参考ページ)

AWS CodeDeploy

AWSが提供するAmazon EC2 インスタンスやオンプレミスインスタンス、サーバーレス Lambda 関数に対するアプリケーションのデプロイを自動化するデプロイメントサービス。
今回はpushしたソースコードからDockerイメージを作成してECRにDockerイメージをpushしています。
(参考ページ)

AWS CodePipeline

AWSが提供するソフトウェアをリリースするために必要な手順のモデル化、視覚化、および自動化に使用できる継続的な配信サービス。
上記の各サービスを組み合わせて一連のデプロイフローなどを設計することができます。
(参考ページ)

Amazon Elastic Container Registry (ECR)

AWSが提供する完全マネージド型の Docker コンテナレジストリ。
CodeDeployで作成したDockerイメージをECRにPushし、管理しています。
(参考ページ)

大まかな流れ

CodePipelineの画面はこんな感じです。

スクリーンショット 2018-03-19 10.35.46.png

流れとしては

1. CodeCommitにソースコードをPushする

2. CodeBuildでテストやCIが実行される

3. CodeDeployでDockerイメージを作成しECRにイメージをPushする

といった感じになります。

CodeCommitの流れ

CodePipelineのトリガーとなるブランチにソースコードがPushされたときに、次のアクションとなるリソース(今回はCodeBuild)に、最新のソースコードを渡します。

CodeBuildの流れ

CodeBuildはCodeCommitからソースコードを渡され、その中の buildspec.yml というファイルを元にコマンドを実行します。
おそらく実行されるときに、あらかじめ設定しておいた環境のEC2が立ち上がっていると思います。ユーザーの目には見えませんが…
buildspec.yml にて各フェーズごとに実行するコマンドを書いたりとか、ソースコードをS3にアップ対象のファイルの設定など書きます。
フォーマットとしてはこんな感じです。( yarn run ** というコマンドは package.json で定義しているコマンドのことです。)

buildspec.yml
version: 0.2
phases:
  install:
    commands:
      # パッケージ等のインストール実行
      # ex. apt-get update -y, npm install -g yarn, yarn install
  pre_build:
    commands:
      # Lintチェック等を実行
      # ex. yarn run eslint, yarn run tslint
  build:
    commands:
      # テスト等実行
      # ex. yarn run ava, yarn run test-client
  post_build:
    commands:
      # S3にアップ前のインストールなどを実行
      # ex. rm -rf node_modules, yarn install --production
# S3にアップする対象ファイル等と形式の設定
artifacts:
  type: zip
  files:
    - hogehoge
    - fugafuga

上記ファイルのどこか一つでも正常に処理が終了しなければ、CodePipelineは処理を終了します。
要するにテストやLintチェックなどでこけるとそこでデプロイが終了するということです。とても健全的ですね。

CodeDeployの流れ

CodeDeployはCodeBuildが正常に処理が完了したらCodePipelineによってキックされます。
CodeBuildが実行されるのは、実際に稼働しているEC2上で実行されます。(他にもやりかたはありますが弊社の例で書いていきます。)
こちらのページを参考にして、AWSCodeDeployエージェントをインストールしておきます。
このEC2の中でDockerイメージを作成するので、EC2にDockerをインストールしておいてください。

$ sudo yum install -y docker

Dockerをインストールしたあと再起動すれば下準備完了です。

弊社のCodeDeployでは「インプレースデプロイ」という方法を選択しています。
実際に実行されて行く流れはこんな感じです。(AWSドキュメントから抜粋)

スクリーンショット 2018-03-19 11.59.44.png

上の画像のように、各イベントで処理を実行していきます。
簡単な流れとしては

1. リビジョン(今回はS3)からソースコードを取得して解凍する。
(このときのディレクトリは:/opt/codedeploy-agent/deployment-root/hogehoge/fugafuge/deployment-archive)

2. 解凍したソースコードを指定のディレクトリにコピーする

3. Dockerイメージを作成し、ECRにPushするShellを実行する

4. ECRにDockerイメージにタグ付けされて、Pushされる

となります。
各イベントの説明はAWSのドキュメントで確認してください。

少し詳細を書いていきます。
CodeDeployの設定ファイルとしては appspec.yml というファイルに各設定を書いていきます。
簡単なフォーマットの例としてはこんな感じです。

appspec.yml
version: 0.0
os: linux
# Installのイベントでインストールする
files:
  - source: /
    destination: /var/www/hogehoge
# トリガーとなるイベントでの設定
hooks:
  ApplicationStart:
    - location: fugafuga.sh
      timeout: 300
      runas: root

上記の appsepc.yml では、Installイベント実行時に、CodeDeployAgentがS3から取得したソースコードを、 /var/www/hogehoge にコピーし、ApplicationStartイベント実行時に fugafufa.sh をroot権限で実行します。
弊社ではこの fugafuga.sh の中でDockerイメージを作成してECRにPushするようにしています。
※下記は色々改変しています。

fugafuga.sh
#!/usr/bin/env bash
cd /var/www/hogehoge

# ECRのエンドポイント
repository=xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com/hogefuga:latest

# Dockerへのログイン情報を取得
$(aws ecr get-login --no-include-email --region ap-northeast-1)

# Dockerイメージの個数をカウント
image_count=$(docker images | grep hoge/hogefuga.app | wc -l)
zero=0

image_count=$(docker images | grep ${repository} | wc -l)
if [ ${image_count} -gt ${zero} ]; then
	docker rmi -f ${repository}
fi

# プロキシの設定を確認
echo http_proxy:${http_proxy}
echo https_proxy:${https_proxy}

# Dockerコンテナをbuildする
echo 'build Docker container'
docker build --no-cache=true \
 --build-arg http_proxy=${http_proxy} \
 --build-arg https_proxy=${https_proxy} \
 -t hoge/hogefuga.app:latest \
 .

# ECRにPushする
echo 'push image to ECR'

docker tag hoge/hogefuga.app:latest ${repository}
docker push ${repository}

# Dockerイメージの削除
image_count=$(docker images -f "dangling=true" -q | wc -l)
if [ ${image_count} -gt ${zero} ]; then
  echo 'clean'
  docker rmi -f $(docker images -f "dangling=true" -q)
fi

docker rmi hoge/hogefuga.app:latest
docker rmi ${repository}

ちなみに小話ですが、Dockerへのログイン情報を取得する際に

$ aws ecr get-login --no-include-email --region ap-northeast-1

と実行していますが、Dockerのバージョンが 17.06 以上だと、廃止された -e オプションが返ってくるので、--no-include-email オプションがないとエラーになります。
ちなみに --no-include-email オプションをつけずに実行すると

$ aws ecr get-login --region ap-northeast-1

docker login -u AWS -p authStrings -e none https://xxxxxxxxxx.dkr.ecr.ap-northeast-1.amazonaws.com

-e none がいらないということですね。

料金はどないなん?

サービス名 料金
CodeCommit ほぼ無料
CodeBuild 0.010 / min (Build実行時間 インスタンスタイプはmedium)
CodeDeploy 無料(CodeDeployを実行するEC2の料金のみ)
CodePipeline 1USD / month

ほう…やっすいですな。

さいごに

こんな感じで、ローカルからCodeCommitにソースコードをPushすると、CI/テストを実行して、Dockerイメージを作成して、ECRにPushしてくれるフローが出来上がります。
CodePipelineはCodeCommitだけでなくGithubにも対応していますので、ソースコードの管理はGithubでされている方でも、問題ないと思います。
自動でCI/テストを実行してくれて、自動でDockerイメージを作成してくれるので、CIサーバの面倒を見なくても良いし、毎回手動でDockerイメージを作成する手間も省けます。
こうやって新人たちに自動化の素晴らしさを伝えて行くんですね。わかります。

おまけ(追記)

記事を投稿しましたところ

CodeBuildでDockerイメージをPushした方がもっと楽ですよ?

というコメントをいただいたので、早速試してみました。
改良版のCodePipelineはこんな感じになりました。

スクリーンショット 2018-03-19 10.35.46.png

ひとつ目のCodeBuildで実行環境(Node.js)のCI/テストを実行して、その後ふたつ目のCodeBuildでDockerイメージをPushするようにしました。
CodeBuildの設定で、実行する buildspec.yml を個別に設定できるので、ふたつ目のCodeBuildで実行するymlファイルを buildspec_docker.yml のように変えて対応しました。
これで、いちいちEC2立ち上げて〜Agentなどを入れて〜といった作業がいらなくなりました。
さらに便利になりましたね!

あとは、この構成をymlファイルにまとめて、CloudFormationで構築できるようにしたら完璧なのかな?

ではまた!

21
23
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
21
23

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?