20
14

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 3 years have passed since last update.

【GitHub Actions】GitHub Package Registryを利用して同一Dockerイメージをjobで共有する

Last updated at Posted at 2019-11-07

皆さんはGitHub ActionsやGitHub Registryを利用していますか?
まだGAになっていないので使っていない方もいるかもしれませんが、来週の11/13(水)にGAとなるので今のうちにお試しで使ってみることをお勧めします。

それでは本題ですが、GitHub ActionsでビルドしたDockerイメージを後続のjobで使い回したい時にどのようにしていますか?
元々パブリックなリポジトリならDocker Hubにプッシュしたりできますが、プライベートリポジトリではそうできません。プライベートレジストリをもっていれば全て解決しますが、自前で立てたり、課金しなくてはならないので少し大変です。
ちなみに私は以前書いた記事にあるように毎回ビルドしていました :cry:
これでは同じイメージではないので、よろしくありません。せっかくTrivyやDockleを使ってスキャンをしているのに...
そこで今回は、GitHub Package Registryを利用してGitHub Actionsのworkflowの中で1度ビルドしたDockerイメージを使いまわす方法を説明していきたいと思います。workflowは以前書いた記事を使用します。

GitHub Package Registryとは?

GitHub Package Registryとはソフトウェアパッケージのホスティングサービスです。Docker HubやPyPIなどをイメージしてもらえれば分かりやすいと思います。
以下が公式ドキュメントの冒頭の説明文です。

GitHub Package Registry is a software package hosting service, similar to npmjs.org, rubygems.org, or hub.docker.com, that allows you to host your packages and code in one place. You can host software packages privately or publicly and use them as dependencies in your projects.

GitHub Package Registry使用方法

セットアップ

こちらのリンクへ飛んでボタンを二回程クリックすればすぐに使うことができます。めっちゃ簡単:wink:

screenshot 2019-11-07 21.34.17.png

Dockerイメージのプッシュ

GitHubのDocker Registryにプッシュする方法はとても簡単です。他のプライベートレジストリやサードパーティーレジストリへのプッシュ方法と基本的に同じです。
ただ、GitHubへのログインに二段階認証を有効にしている場合は、Registryへログインする際にアクセストークンが必要になります。こちらを参考にトークンを取得してください。

# DockerのRegistryにログイン
docker login docker.pkg.github.com -u owner -p password

# DockerfileはCWDにあるとする
docker build -t docker.pkg.github.com/owner/repository_name/sample .

# GitHub Package Registryへプッシュ
docker push docker.pkg.github.com/owner/repository_name/sample

イメージ名は後から変更可能なので以下のようにしてもOKです。

docker build -t sample .
docker tag sample docker.pkg.github.com/owner/repository_name/sample

Dockerイメージのプル

# DockerのRegistryにログイン
docker login docker.pkg.github.com -u owner -p password

docker pull docker.pkg.github.com/owner/repository_name/sample

とりわけ難しい部分もないのでGitHub Actionsでやってみましょう:bangbang:

GitHub Actions

GitHub ActionsからGitHub Package Registryを利用するTipsは、docker loginパスワードに環境変GITHUB_TOKENの指定することです。GitHub Actionsが自動生成してくれるので、わざわざボタンをポチポチしてトークンを生成して管理する必要はなくなります。

処理の流れ

                 +-----------------+
                 | ①             |
                 |     build       |
                 | Dockerイメージを  |
                /| ビルドしてプッシュ  |\
               / |                 | \
              /  +-----------------+  \
             /                         \ 
 +-----------------+                +-----------------+
 | ②             |                | ②'            |
 |     Trivy       |                |     Dockle      |
 |                 |                |                 |
 +-----------------+                +-----------------+
             \                          /
              \                        /
               \                      /
                \                    /
                 +-----------------+
                 |  ③            |
                 |   Push to ECR   |
                 |                 |
                 +-----------------+

Workflow例

name: Push Docker image to ECR

# リモートブランチにプッシュされたらWorkflowが起動
on: push

env:
  # BuildKitを有効化
  DOCKER_BUILDKIT: 1
  IMAGE_NAME: sample
  IMAGE_TAG: test

jobs:
  build:
    name: Build image
    runs-on: ubuntu-18.04
    steps:
      - uses: actions/checkout@master

      - name: Login GitHub Registry
        # 自動生成されるGITHUB_TOKENを使用する
        run: echo ${{ secrets.GITHUB_TOKEN }} | docker login docker.pkg.github.com -u owner --password-stdin
      - name: Build image
        # `github.repository`で`owner/repository_name`が取得できる
        run: docker build -t docker.pkg.github.com/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG} --file Dockerfile .

      - name: Push image to GitHub Registry
        run: docker push docker.pkg.github.com/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG}

      - name: Notify Result to Slack
        uses: homoluctus/slatify@master
        if: always()
        with:
          type: ${{ job.status }}
          job_name: ':docker: *Build image*'
          channel: '#general'
          url: ${{ secrets.SLACK_WEBHOOK }}

  trivy:
    name: Trivy Scan Vulnerability
    runs-on: ubuntu-18.04
    needs: build
    steps:
      - uses: actions/checkout@master

      - name: Login GitHub Registry
        run: echo ${{ secrets.GITHUB_TOKEN }} | docker login docker.pkg.github.com -u owner --password-stdin

      - name: Pull image from GitHub Registry
        run: docker pull docker.pkg.github.com/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG}

      - name: Install trivy
        run: |
          sudo apt-get install --no-install-recommends apt-transport-https gnupg
          wget -qO - https://aquasecurity.github.io/trivy-repo/deb/public.key | sudo apt-key add -
          echo deb https://aquasecurity.github.io/trivy-repo/deb $(lsb_release -cs) main | sudo tee -a /etc/apt/sources.list.d/trivy.list
          sudo apt-get update
          sudo apt-get install --no-install-recommends trivy

      - name: Vulnerability Scan with Trivy
        run: |
          trivy -q --severity HIGH,CRITICAL \
            --exit-code 1 docker.pkg.github.com/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG}

      - name: Notify Result to Slack
        uses: homoluctus/slatify@master
        if: always()
        with:
          type: ${{ job.status }}
          job_name: ':trivy: *Trivy*'
          channel: '#general'
          url: ${{ secrets.SLACK_WEBHOOK }}

  dockle:
    name: Dockle
    runs-on: ubuntu-18.04
    needs: build
    steps:
      - uses: actions/checkout@master

      - name: Login GitHub Registry
        run: echo ${{ secrets.GITHUB_TOKEN }} | docker login docker.pkg.github.com -u owner --password-stdin
      - name: Pull image from GitHub Registry
        run: docker pull docker.pkg.github.com/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG}

      - name: Install dockle
        run: |
          VERSION=$(curl --silent "https://api.github.com/repos/goodwithtech/dockle/releases/latest" | \
          grep '"tag_name":' | \
          sed -E 's/.*"v([^"]+)".*/\1/' \
          )
          curl -L -o dockle.deb https://github.com/goodwithtech/dockle/releases/download/v${VERSION}/dockle_${VERSION}_Linux-64bit.deb
          sudo dpkg -i dockle.deb
          rm dockle.deb

      - name: Check image with dockle
        run: dockle docker.pkg.github.com/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG}

      - name: Notify Result to Slack
        uses: homoluctus/slatify@master
        if: always()
        with:
          type: ${{ job.status }}
          job_name: ':docker: *Dockle*'
          channel: '#general'
          url: ${{ secrets.SLACK_WEBHOOK }}

  push:
    name: Push Docker Image to ECR
    runs-on: ubuntu-18.04
    needs: [trivy, dockle]
    steps:
      - uses: actions/checkout@master

      - uses: actions/setup-go@master
        with:
          go-version: '1.13'

      - name: Install ecs-cli
        run: go get github.com/aws/amazon-ecs-cli/ecs-cli

      - name: Login GitHub Registry
        run: echo ${{ secrets.GITHUB_TOKEN }} | docker login docker.pkg.github.com -u owner --password-stdin

      - name: Pull image from GitHub Registry
        run: |
          docker pull docker.pkg.github.com/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG}
         # Change docker image name
          docker tag docker.pkg.github.com/${{ github.repository }}/${IMAGE_NAME}:${IMAGE_TAG} ${IMAGE_NAME}:${IMAGE_TAG}

      - name: Push image to ECR
        env:
          AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
          AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
          AWS_DEFAULT_REGION: ap-northeast-1
        # GOPATH bug [reference](https://github.com/actions/setup-go/issues/14)
        run: $(go env GOPATH)/bin/ecs-cli push ${IMAGE_NAME}:${IMAGE_TAG}

      - name: Notify Result to Slack
        uses: homoluctus/slatify@master
        if: always()
        with:
          type: ${{ job.status }}
          job_name: ':rocket: *Push to ECR*'
          channel: '#general'
          url: ${{ secrets.SLACK_WEBHOOK }}

これで一回のDockerイメージビルドで後続のJobでもそのイメージを使いまわせるようになりました:clap:

Reference

20
14
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
20
14

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?