一生懸命まとめましたが、公式ドキュメントに丁寧で正確な説明があることに最近気づきました。
概要
Docker Hubの無料枠に制限がかかるという話もあり、GitHub Container Registryの使い方を調べたのでメモする。具体的には以下を実現したい。
- GitHubへpushする度、GitHub Actionsでdockerイメージをbuildし、GitHub Container Registryにpush
- その際、GitHubへpushしたタグに応じて、dockerイメージのタグも変更する
環境
- wsl2のDebian
- Docker version 19.03.12, build 48a66213fe
事前準備
GitHub Container Registryに自動でdockerイメージをpushするには、Personal Access Tokenが必要1。GitHub右上の自分のアイコンからSettings
> Developer settings
> Personal access tokens
> Generate new token
の手順で作成する。スコープは以下の画像のもので大丈夫そう。
得られたトークンはDockerfileなどを管理しているGitHubリポジトリでSetting
> Secrets
> New secret
の手順で登録しておく(ここではCR_PAT
という名前で保存したことにする)。
YAMLファイル作成①
GitHub Actionsを制御するためのYAMLファイルを作成する。以下のようなディレクトリ構成を想定2。
.
├── .git
├── .github
│ └── workflows
│ └── build_on_push.yaml
└── Dockerfile
name: Publish Docker image
on: push
jobs:
main:
name: Push Docker image to Github Container Registry
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }}
- name: Push to GitHub Container Registry
uses: docker/build-push-action@v2
with:
push: true
tags: ghcr.io/dr666m1/qiita_starwars:latest
name:
はworkflowやjobを命名しているだけなので任意の値。on:
ではトリガーとなるイベントを指定(ここではpush)。3行目のjobs:
で5つのstepからなるjobを定義しているので、以降で各stepについて簡単に解説する(ちなみにruns-on:
はjobを実行する仮想マシンの指定で、ここではGitHubホストランナーを選択している)。
Checkout
actions/checkout@v2
というactionで、GitHubリポジトリにアクセスできる状態にする。逆に言えば、このstepがないと「Dockerfileが見つかりません」といったエラーに陥るはず。ドキュメントはこちら。
Set up QEMU, Set up Docker Buildx
docker/setup-qemu-action@v1
docker/setup-buildx-action@v1
はいずれも必要な機能を利用可能にするためのactionという程度の認識でよいと思う。
Login to GitHub Container Registry
docker/login-action@v1
というactionでログイン処理を行う。${{ secrets.CR_PAT }}
は先ほど作成したPersonal Access Tokenを参照している。Docker Hub やGitLabにも対応していて、ドキュメントにはそれぞれの対応方法が記載されている。
Push to GitHub Container Registry
docker/build-push-action@v2
というactionでdockerイメージのbuildとpushを行う。tags:
でタグも指定できるが、この段階ではlatest
としておく。
動作確認
ファイルの準備ができたらgit push
するだけで、YAMLで定義したワークフローが実行される。以下の画面のようにログも確認できる。
問題なければGitHub右上の自分のアイコンからYour profile
> Packages
でbuildされたdockerイメージを確認できる。デフォルトでprivateになるようなので、publicにしたければ変更してしまう。あとはdocker run
して問題なければOK3。
docker run -it --rm ghcr.io/dr666m1/qiita_starwars:latest
YAMLファイル作成②
次にタグを指定できるよう、YAMLファイルを以下の通り変更する。
name: Publish Docker image
on: push
jobs:
main:
name: Push Docker image to Github Container Registry
runs-on: ubuntu-latest
steps:
- name: Prepare # 追加
id: prep
run: |
if [[ $GITHUB_REF == refs/tags/* ]]; then
TAG=${GITHUB_REF#refs/tags/}
else
TAG="latest"
fi
echo "::set-output name=tag::${TAG}"
- name: Checkout
uses: actions/checkout@v2
- name: Set up QEMU
uses: docker/setup-qemu-action@v1
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v1
- name: Login to GitHub Container Registry
uses: docker/login-action@v1
with:
registry: ghcr.io
username: ${{ github.repository_owner }}
password: ${{ secrets.CR_PAT }}
- name: Push to GitHub Container Registry
uses: docker/build-push-action@v2
with:
push: true
tags: ghcr.io/dr666m1/qiita_starwars:${{ steps.prep.outputs.tag }} # 変更
主な変更点はPrepareというstepの追加。run:
でshell(デフォルトはbash4)で実行されるコマンドを指定する。ここでは$GITHUB_REF
環境変数5によって処理を変えていて、タグの名前を含めばそれを、なければlatest
をTAG
に代入している。echo "::set-output name=tag::${TAG}"
はワークフローコマンドと呼ばれるもので、ここではTAG
の値を後続のstepで参照できるようにしている。${{ steps.prep.outputs.tag }}
が実際に参照している部分。
この変更によって、GitHubにpushしたタグに応じてdockerイメージのタグも変更されるようになる。例えば以下のように実行すれば、dockerイメージのタグも1.0
になる。
git tag 1.0
git push --tags
最後に
もしDocker HubからGitHub Container Registryに移行したくなっても、これで概ね困らなそう。GitHub Actionsは自動テストなど、もっといろいろなことに使えるはずなので、時間があるときに勉強したい。
-
Github Packagesでは、代わりにGITHUB_TOKENが使えたらしい ↩
-
Dockerfileを見ての通りだが、この例だとスターウォーズの上映が始まる(このサンプルdockerイメージは削除済み ↩telnet towel.blinkenlights.nl
)のでCtrl+]
>quit
で抜ける