GitHub Container Registryを使ってDockerイメージを管理する
はじめに
GitHub Container Registry(ghcr.io)使用したDockerイメージ管理とActionsの組み込みについて触れている記事です。
本記事では、手動でのイメージ管理から GitHub Actions での自動化まで段階的に進めていきます。
GitHub Container Registry
GitHubの公式ドキュメントによると、GitHub Container Registry(以下GHCR)は以下のように定義されています
The Container registry stores container images within your organization or personal account, and allows you to associate an image with a repository.
つまり、GHCRは個人アカウントまたは組織内でコンテナイメージを保存・管理できるサービスです。
主な特徴:
- URL: ghcr.io
- 認証: Personal Access Token (PAT) または GitHub Actions の GITHUB_TOKEN
- 権限管理: リポジトリと連携、または独立した権限設定が可能
- 料金: パブリックイメージは無料、プライベートは GitHub Packages の料金体系に従う
手動で push してみる
まずは手動でイメージをpushして、基本的な流れを掴みます。
Personal Access Token (PAT) の作成
- Personal Access Token (PAT) の作成
- 必要な権限を選択:
write:packages(自動的に read:packages も選択される)
レジストリへのログインとpush
公式の手順より参照
# トークンを環境変数に設定
export CR_PAT=ghp_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
# GitHub Container Registry にログイン
echo $CR_PAT | docker login ghcr.io -u YOUR_GITHUB_USERNAME --password-stdin
# イメージをビルド
docker build -t my-app:latest .
# GHCRの命名規則に従ってタグ付け
docker tag my-app:latest ghcr.io/YOUR_USERNAME/my-app:latest
# イメージをpush
docker push ghcr.io/YOUR_USERNAME/my-app:latest
pushしたイメージの確認
今回は組織で実施しているためhttps://github.com/orgs/your-org/packages
で確認できます。
GitHub Actions で push してみる
ローカルで実施した手順を Actions 上で実施できるようにします。
最初の自動化ワークフロー
dockerが提供しているcomposite action
があるのでそちらを利用していきます。
name: Docker Build and Push
on:
push:
branches: [main]
tags: ['v*']
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push Docker image
uses: docker/build-push-action@v5
with:
context: .
push: true # 重要:これがないとpushされません!
tags: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest
より実践的なタグ管理
latest
タグだけでなく、バージョン管理もしたい場合はdocker/metadata-action
を使うと、Gitの情報から自動的に適切なタグを生成できます。
name: Docker Build and Push with Tags
on:
push:
branches: [main]
tags: ['v*']
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
build-and-push:
runs-on: ubuntu-latest
permissions:
contents: read
packages: write
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Extract metadata
id: meta
uses: docker/metadata-action@v5
with:
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
tags: |
type=ref,event=branch
type=semver,pattern={{version}}
type=semver,pattern={{major}}.{{minor}}
type=sha,prefix={{date 'YYYYMMDD'}}-
- name: Build and push
uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
cache-from: type=gha
cache-to: type=gha,mode=max
別のワークフローから実行
ビルドしたイメージを定期的に実行します
name: Run Container
on:
workflow_dispatch:
env:
REGISTRY: ghcr.io
IMAGE_NAME: ${{ github.repository }}
jobs:
run:
runs-on: ubuntu-latest
permissions:
packages: read # 読み取り権限のみ
steps:
- name: Log in to Container Registry
uses: docker/login-action@v3
with:
registry: ${{ env.REGISTRY }}
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Run container
run: |
docker run --rm \
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
npm start
トラブル
進める中でいくつか困りポイントあったので備忘録的に記載しています。
手動でpushしたいケース
docker loginができていれば自前でpushすることも可能です。
- name: Build and push Docker image
run: |
docker buildx build . \
--push \
--platform linux/amd64 \
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:latest \
-t ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ github.ref_name }}
docker image 名は lower のみ
docker image は 基本的にlowerケースのみを期待しているのでリポジトリ名など式
で利用する場合は気をつける
${{ github.repository }} CamelCaseなど入ってくる可能性がある
platform問題
ローカル環境では、それぞれのOSでbuildされるが、github actions上ではubuntu
上で実行されるため、プラットフォームlinux/amd64
の指定を忘れない
もしくはマルチプラットフォームに対応する
Actions上の名前解決
actions上ではlocalhost
と接続ができないので--add-host=host.docker.internal:host-gateway
による接続できるようオプションを追加する
こちら参考にさせていただきました。
jarファイルの取り扱い
dockerfile内でgraldew
のtaskなどでjar
ファイルを生成しCOPY
しても期待通り動かない場合は
dockerfile外で生成したjar
ファイルをARG
で渡すと期待通り読み込まれます。
こちら参考にさせていただきました。
Discussion