GitHub ActionでDockerコンテナをビルドしてAmazon ECRに保存する
はじめに
おはようございます、加藤です。下記のブログで、AWS認証情報の設定とAmazon ECRにログインするGitHub Actionが公開されている事を知りました。
これらを使って、GitHubで管理しているDockerイメージをビルドして、ECRに保存する方法を紹介します。タグが付けられて時にのみ動作し、そのタグをイメージに引き継ぐ仕様で作りました。
AWS IAM ユーザーの作成
GitHub ActionからAmazon ECRへアクセスする為の、IAMユーザーを発行します。マネジメントコンソールへのアクセスは必要無いので、アクセスの種類はプログラムによるアクセスのみを設定します。
今回は、AWS管理ポリシー AmazonEC2ContainerRegistryPowerUser
を関連付けします。権限を最小化したい場合は、独自でIAMポリシーを作成してください。
発行されたアクセスキー、シークレットアクセスキーは後ほど使用するのでメモして置きます。
Amazon ECRの作成
任意の名前でコンテナリポジトリを作成してください。今回は sample-nginx
という名前で作成しました。
GitHub Action ワークフローの作成
以下の3ステップで実行します。
- AWS認証情報を設定
- Amazon ECRにログイン
- ビルドとプッシュ
v*
のタグが設定された時だけ、動作します。実ワークロードでは、ビルド後にテストの実施や、タグが設定されなくても、テストまでは行うなど、変更が必要です。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 | name: Build and Push on: push: tags: - v* jobs: build-and-push: runs-on: ubuntu-18.04 timeout-minutes: 300 steps: - uses : actions/checkout@v1 - name : Configure AWS Credentials uses: aws-actions/configure-aws-credentials@v1 with: aws-access-key-id: $ { { secrets.AWS_ACCESS_KEY_ID } } aws-secret-access-key: $ { { secrets.AWS_SECRET_ACCESS_KEY } } aws-region: ap-northeast-1 - name : Login to Amazon ECR id: login-ecr uses: aws-actions/amazon-ecr-login@v1 - name : Build , tag , and push image to Amazon ECR env: ECR_REGISTRY: $ { { steps.login-ecr.outputs.registry } } ECR_REPOSITORY: $ { { secrets.AWS_ECR_REPO_NAME } } run: | IMAGE_TAG=$(echo $ { { github.ref } } | sed -e "s#refs/tags/##g" ) docker build -t $ECR_REGISTRY/$ECR_REPOSITORY : $IMAGE_TAG . docker push $ECR_REGISTRY/$ECR_REPOSITORY : $IMAGE_TAG |
GitHubリポジトリにSecretsを設定
GitHubリポジトリを開き、 Settings → Secrets からSecretsを設定します。ここで設定した値は、GitHub Action ワークフロー内で ${{ secrets.AWS_ECR_REPO_NAME }}
という記法で取り出しができます。
以下の3つを設定してください。
- AWS_ACCESS_KEY_ID
- AWS_SECRET_ACCESS_KEY
- AWS_ECR_REPO_NAME
サンプルコンテナの準備
nginxをベースに作成します。
Hello World!
と表示されるだけのシンプルな静的Webサイトです。
1 2 3 4 | . ├── Dockerfile └── html └── index.html |
1 2 3 | FROM nginx:1.17.5 COPY ./html /usr/share/nginx/html |
1 2 3 4 5 6 7 | < html > < body > < h1 >Hello World!</ h1 > </ body > </ html > |
これら、2つのファイルを作成します。
実行
まず、リポジトリにプッシュします。
1 2 3 | git add -A git commit -m 'initial commit' git push |
次に、タグを付けてプッシュします。
1 2 | git tag v1.0.0 git push --tags |
GitHub Action ワークフローのログを確認します。
今回、下記の2つのGitHub Actionを使用しましたが、アカウント番号やリポジトリ名などまで、マスクしてくれるので、Publicなリポジトリでも安心して使えますね!!(これらの情報が見えたからといって直接的に危険は無いですが)
- aws-actions/configure-aws-credentials: Configure AWS credential environment variables for use in other GitHub Actions.
- aws-actions/amazon-ecr-login: Logs into Amazon ECR with the local Docker client.
Amazon ECRにImageが登録されていれば、成功です。
※ 画像はタグ名が v1.0.3
となっていますが、手順通りなら v1.0.0
となります。
あとがき
GitHub Actionを初めて使ってみました。リポジトリのタグ名を ${{ github.ref }}
という記法で取得できるのですが、 refs/tags/v1.0.0
という感じで取り出されます。
このままだと、イメージのタグ名に使用できないので、 sed
で IMAGE_TAG=$(echo ${{ github.ref }} | sed -e "s#refs/tags/##g")
と書いて v1.0.0
を抽出しています。
社内で相談し、 奥さん、和田さん に教えて貰いましたが、良い方法は無いみたいです...
- Solved: How to get just the tag name? - GitHub Community Forum
- 他のやり方
- GitHub Actions のコンテキストおよび式の構文 - GitHub ヘルプ
join
はあるけど、split
がない
今回は、タグの設定をトリガーとしていますが、リリースをトリガーにする事もできます。コンテナのビルドからデプロイまで一気通貫のパイプラインをよく見ますが、アプリ担当者とインフラ担当がチームとして別れている様な場合は、パイプラインも合わせて分割した方が良いかなと個人的には思っています。
後続の処理としては、以下の2パターンがあると思っています。
- Amazon ECRへのプッシュをトリガーとしてAmazon ECS/EKSへのデプロイするパイプラインを動かす
- コンテナのバージョンも含めてInfrastructure as Codeで管理しているので、コードのバージョン指定部分を変更する
以上です!