Closed12

GitHub ActionsでDockerイメージのビルドとECRへのpushをやってみるメモ

Hirotaka MiyagiHirotaka Miyagi

特定リポジトリのECRへのPushができるIAMユーザーを作る。
探してみたらチュートリアルがあった。
https://docs.aws.amazon.com/ja_jp/AmazonECR/latest/userguide/security_iam_id-based-policy-examples.html

terraformで管理しているのでこんな感じになった

resource "aws_iam_user" "this" {
  name = "github_actions_deploy_${var.name}"
}

resource "aws_iam_user_policy_attachment" "this" {
  user       = aws_iam_user.this.name
  policy_arn = aws_iam_policy.this.arn
}

resource "aws_iam_policy" "this" {
  name   = "github_actions_${var.name}"
  policy = data.aws_iam_policy_document.iam_user.json
}

data "aws_iam_policy_document" "iam_user" {
  statement {
    actions = [
      "ecr:GetAuthorizationToken",
      "ecr:BatchCheckLayerAvailability",
      "ecr:GetDownloadUrlForLayer",
      "ecr:GetRepositoryPolicy",
      "ecr:DescribeRepositories",
      "ecr:ListImages",
      "ecr:DescribeImages",
      "ecr:BatchGetImage",
      "ecr:InitiateLayerUpload",
      "ecr:UploadLayerPart",
      "ecr:CompleteLayerUpload",
      "ecr:PutImage",
    ]
    resources = [
      data.aws_ecr_repository.this.arn,
    ]
  }
}

Hirotaka MiyagiHirotaka Miyagi

失敗した。 ecr:GetAuthorizationToken は全てのリポジトリに許可しないといけないらしい

data "aws_iam_policy_document" "iam_user" {
  statement {
    actions = [
      "ecr:BatchCheckLayerAvailability",
      "ecr:GetDownloadUrlForLayer",
      "ecr:GetRepositoryPolicy",
      "ecr:DescribeRepositories",
      "ecr:ListImages",
      "ecr:DescribeImages",
      "ecr:BatchGetImage",
      "ecr:InitiateLayerUpload",
      "ecr:UploadLayerPart",
      "ecr:CompleteLayerUpload",
      "ecr:PutImage",
    ]
    resources = [
      data.aws_ecr_repository.this.arn,
    ]
  }

  statement {
    actions = [
      "ecr:GetAuthorizationToken",
    ]
    resources = [
      "*"
    ]
  }
}
Hirotaka MiyagiHirotaka Miyagi

取り急ぎ通るようになった

name: Build and Push

on:
  [push]

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_STG }}
          aws-secret-access-key: ${{ secrets.AWS_SECRET_ACCESS_KEY_STG }}
          aws-region: ap-northeast-1

      - name: Build, tag, and push image to Amazon ECR
        run: |
          make -f deploy.mk build_push # Makefileにまとめているため、それを呼び出している

Hirotaka MiyagiHirotaka Miyagi

buildターゲットをこんな感じにしてみる

build:
	DOCKER_BUILDKIT=1 docker build \
	--cache-from=$(DOCKER_IMAGE):latest --build-arg BUILDKIT_INLINE_CACHE=1 \
	--pull -t $(DOCKER_IMAGE):$(GIT_REVISION) .

が、実行してみるとキャッシュが効いている感じがない。

#4 importing cache manifest from ***.dkr.ecr.ap-northeast-1.amazon...
#4 ERROR: ***.dkr.ecr.ap-northeast-1.amazonaws.com/hogehoge:latest not found

ログを見るとlatestはないと言われていた。それはそう

Hirotaka MiyagiHirotaka Miyagi

試しにlatestを抜いたらいい感じに最新のイメージを引っ張ってきてくれないかなーと思ったけれど、

build:
	DOCKER_BUILDKIT=1 docker build \
	--cache-from=$(DOCKER_IMAGE) --build-arg BUILDKIT_INLINE_CACHE=1 \
	--pull -t $(DOCKER_IMAGE):$(GIT_REVISION) .

結果は変わらず latest を探しに行ってしまっていた。タグ指定がない場合は latestを探しに行くとのこと。

#4 importing cache manifest from ***.dkr.ecr.ap-northeast-1.amazon...
#4 ERROR: ***.dkr.ecr.ap-northeast-1.amazonaws.com/hogehoge:latest not found
Hirotaka MiyagiHirotaka Miyagi

最新イメージのタグを力技で取得して明示的にキャッシュ元を取得するようにした

build: latest_tag := $(shell aws ecr describe-images --registry-id ${ECR_REGISTRY_ID} --repository-name ${REPOSITORY_NAME} --query 'reverse(sort_by(imageDetails[], &imagePushedAt)[].imageTags[]) | [0]' | sed "s/\"//g")
build: 
	DOCKER_BUILDKIT=1 docker build -f ./deployment/Dockerfile \
	--cache-from=$(DOCKER_IMAGE):${latest_tag} --build-arg BUILDKIT_INLINE_CACHE=1 \
	-t $(DOCKER_IMAGE):$(GIT_REVISION) .

「これlatestタグを付け替え続ければ最新イメージを取得する処理簡単では…」と頭によぎったが、心を鬼にしてJMESPathと向き合いました

Hirotaka MiyagiHirotaka Miyagi

おおお!キャッシュされている!!!

DOCKER_BUILDKIT=1 docker build -f ./deployment/Dockerfile \
--cache-from=***.dkr.ecr.ap-northeast-1.amazonaws.com/hoge:fuga --build-arg BUILDKIT_INLINE_CACHE=1 \
-t ***.dkr.ecr.ap-northeast-1.amazonaws.com/hoge:piyo .
#1 [internal] load .dockerignore
#1 transferring context: 69B done
#1 DONE 0.0s

#2 [internal] load build definition from Dockerfile
#2 transferring dockerfile: 920B done
#2 DONE 0.0s

#3 [internal] load metadata for docker.io/library/ruby:2.6.6
#3 DONE 1.2s

#9 [internal] load build context
#9 DONE 0.0s

#5 [1/8] FROM docker.io/library/ruby:2.6.6@sha256:358f16e92d0f66599103318f7...
#5 DONE 0.0s

#4 importing cache manifest from ***.dkr.ecr.ap-northeast-1.amazon...
#4 DONE 1.4s

#9 [internal] load build context
#9 transferring context: 7.93MB 0.1s done
#9 DONE 0.2s

#10 [5/8] COPY Gemfile Gemfile.lock /app/
#10 CACHED

#6 [2/8] RUN mkdir /app
#6 CACHED

#7 [3/8] WORKDIR /app
#7 CACHED

#8 [4/8] RUN curl -sL https://dl.yarnpkg.com/debian/pubkey.gpg | apt-key ad...
#8 CACHED

#12 [7/8] RUN bundle config set deployment 'true' &&     bundle config set w...

実行順序がバラバラになっている。これがBuildKitの並列実行?

Hirotaka MiyagiHirotaka Miyagi

5分程度かかっていたビルドが1分程度で終わるように。これは嬉しい。

Hirotaka MiyagiHirotaka Miyagi

一定期間運用していて問題なく回っているので、このままで良さそう。閉じます。

このスクラップは2020/12/12にクローズされました