はじめに
この記事ではコンテナイメージをビルドし、GitHub Container Registry(以下、ghcr)にpushする手順を整理します。 コマンドラインを使う方法とGitHub Actionsを使う方法の2つを紹介します。
ghcrとは
GitHubが提供しているコンテナレジストリです。
他のコンテナレジストリの選択肢としてはAmazon ECR・Google Container Registry、Azure Container Registry等が挙げられます。 これらと比較してghcrは「GitHub Actionsとの連携が容易」「クラウドベンダーのリソースやトークンを管理する手間が不要」という優位点があります。
GitHubを使っているプロジェクトではコンテナレジストリとしてgchrが有力な候補になるでしょう。
① コマンドラインでコンテナイメージをpushする
- Personal Access Token(PAT)を発行する
- ghcrにログインする
- コンテナイメージをビルドする
- コンテナイメージをpushする
1. Personal Access Token(PAT)を発行する
ghcrはPersonal Access Token(以下PAT)による認証のみがサポートされています。
personal access token (classic) の作成手順
に沿ってトークンを発行します。
作成後にトークンの値を確認することはできないため、必ずトークンの値を控えてください
ghcrにコンテナイメージをpushするには「write:packages」権限を適用する必要があります。
2. ghcrにログインする
コンテナイメージをghcrにpushするためには事前にghcrにログインする必要があります。
ログインには先ほど作成したPATを使います。
今回は~/.ghcr_token.txt
にトークン文字列が書き込まれているという体で手順を実行します。
$ cat ~/.ghcr_token.txt | docker login ghcr.io -u USERNAME --password-stdin
Login Succeeded
Login Succeed
と表示されれば成功です。
3. コンテナイメージをビルドする
今回はコンテナイメージをpushすることが目的なので、どんなイメージでも問題ありません。
ここでは適当にPythonのイメージを用意します。
.
|- app.py
|- Dockerfile
print("Hello, World!")
FROM python:3.12-slim
COPY app.py .
CMD ["python", "./app.py"]
$ docker build -t python-test .
[+] Building 0.1s (7/7) FINISHED docker:default
=> [internal] load build definition from Dockerfile 0.0s
=> => transferring dockerfile: 102B 0.0s
=> [internal] load .dockerignore 0.0s
=> => transferring context: 48B 0.0s
=> [internal] load metadata for docker.io/library/python:3.12-slim 0.0s
=> [internal] load build context 0.0s
=> => transferring context: 27B 0.0s
=> [1/2] FROM docker.io/library/python:3.12-slim 0.0s
=> CACHED [2/2] COPY app.py . 0.0s
=> exporting to image 0.0s
=> => exporting layers 0.0s
=> => writing image sha256:7e21e1f0d2428688c81735807b66e5db23b2dc8121a3bebe48533078aee7b517 0.0s
=> => naming to docker.io/library/python-test 0.0s
4. コンテナイメージをpushする
それでは先ほどビルドしたイメージをpushします。
ghcrにコンテナイメージをpushするためにはghcr.io/<USERNAME>/<IMAGENAME>:TAG
の形式でタグ付けする必要があります。GitHubのユーザ名がjunpei-azumaでイメージ名がpython-test, タグ名を1.0としたい場合、以下のようになります。
また、CLIからイメージをpushする場合、リポジトリと紐づけることができないことに注意が必要です。1
$ docker tag python-test:latest ghcr.io/junpei-azuma/python-test:1.0.0
それではコンテナイメージをpushします。
$ docker push ghcr.io/junpei-azuma/python-test:1.0.0
The push refers to repository [ghcr.io/junpei-azuma/python-test]
2b6d15ba5b96: Pushed
6258d28909ff: Layer already exists
cfaf35e1cecf: Layer already exists
c6bc67c64ae2: Layer already exists
bfc9081d1eb2: Layer already exists
1f00ff201478: Layer already exists
1.0.0: digest: sha256:7ad574ae5599e33b8c100ebf5376ced4eae97b1bafe1e549751ea8168cec5651 size: 1577
pushしたバージョンのイメージが作成されていれば成功です。
② GitHub Actionsでコンテナイメージをpushする
- ghcrにログインする
- コンテナイメージをビルド・pushする
①と比較してこの方法には以下のメリットがあります。そのため、実運用ではGitHub Actionsを使う方法が一般的です。
- 毎回コマンドを手打ちする必要がない
- イメージをリポジトリと紐づけることができる
- データ転送に課金されない2
今回は「GitHubでタグを新しく作成するとコンテナイメージをビルド→pushする」という処理を行うワークフローを実装します。
name: Build And Push Container Image
on:
push:
tags:
- "*"
env:
REGISTRY: ghcr.io
IMAGE_NAME: python-test
jobs:
build-and-push:
runs-on: ubuntu-latest
# イメージをプッシュする権限をGITHUB_TOKENに付与する
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
# 1. ghcrにログインする
- name: Login to GitHub Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
# 2. コンテナイメージをビルド・pushする
- name: Build and Push Container
uses: docker/build-push-action@v5
with:
push: true
tags: ${{ env.REGISTRY }}/${{ github.repository }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
1. ghcrにログインする
CLを使う場合と同じく最初にghcrにログインします。
自前でスクリプトを書いても良いのですが、今回はGitHub Market Placeで提供されているdocker-login
アクションを使います。
こちらのアクションはthird party製ではありますが、dockerが開発しているため公式製と同程度に信頼できると見てよいでしょう。
パラメータ
このアクションは下記のパラメータを受け取ります。
名前 | 型 | デフォルト値 | 概要 |
---|---|---|---|
registry | String | docker.io | コンテナレジストリのアドレス。 |
username | String | コンテナレジストリのユーザ名 (今回の場合、GitHubのユーザ名) |
|
password | String | コンテナレジストリの認証用パスワード・トークン | |
ecr | String | auto | コンテナレジストリがECRかどうか |
logout | Bool | true | ジョブの終了後にコンテナレジストリからログアウトするかどうか |
今回はregistry
,username
,password
の3つを指定します。
- registry:
ghcr.io
- username: ${{ github.actor }} (ワークフローの実行ユーザ) 3
- password: ${{ secrets.GITHUB_TOKEN }}(ワークフローの起動時に生成される一意なトークン)
公式マニュアルの実装例はこちら
2. コンテナイメージをビルド・pushする
続いてコンテナイメージをビルド・pushします。ここでもGitHub Market Placeのbuild-push-action
アクションを使います。
パラメータ
数が多く、全部は書いていられないのでよく使われるものだけ記載します。
名前 | 型 | 概要 |
---|---|---|
context | String | ビルドを実行するカレントディレクトリ. デフォルト値はリポジトリのルートパス |
file | String | Dockerfileのパス. デフォルト値は{context}/Dockerfile |
push | Bool | コンテナレジストリにpushするかどうか(デフォルト値はfalse) |
tags | List/CSV | タグの値のリスト |
今回はpush
とtags
を指定します。
- push: コンテナレジストリにイメージをpushするのでtrue
- tags:
ghcr.io/<REPOSITRYNAME>/<USERNAME>/<IMAGENAME>:<TAGNAME>
となるように指定
3. ワークフローを実行する
それではワークフローを実行します。
mainブランチにpushして適当にタグを打ちます。
コンテナイメージが追加されました。
おわりに
今回はGitHub Container Registryにコンテナイメージをpushする方法をまとめました。
GitHub内でビルド~push~保存が完結するので運用しやすいと思いました。
参考資料