Help us understand the problem. What is going on with this article?

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

皆さんは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: docker login docker.pkg.github.com -u owner -p ${{ secrets.GITHUB_TOKEN }}

      - 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: docker login docker.pkg.github.com -u owner -p ${{ secrets.GITHUB_TOKEN }}

      - 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: docker login docker.pkg.github.com -u owner -p ${{ secrets.GITHUB_TOKEN }}

      - 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: docker login docker.pkg.github.com -u owner -p ${{ secrets.GITHUB_TOKEN }}

      - 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

homines22
Network programmingやインフラ(サーバー・ネットワーク)などに興味があります。 最近はAWSを使ってサービス開発しています。 よく使う言語はC / Python / TypeScriptです。
hands-lab
ハンズラボは小売業特化型ITソリューション企業です。数十万に及ぶ膨大な商品マスタを扱ってきた豊富なノウハウで、お客様の現場に最適なシステムを提案・開発します。 エンジニア募集中
https://www.hands-lab.com/
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした