GitHub ActionsワークフローからDockerHubにイメージをプッシュする
概要
- GitHub ActionsのワークフローからDockerHubにイメージをプッシュする基本的な方法(≒ 最小限の構成)の解説
やってないこと
- コンテナイメージのセキュリティ観点などでの最適化
- コンテナイメージのビルド速度の最適化
ワークフローの流れ
- Checkout
- GitHubのリポジトリをチェックアウトする
- actions/checkoutを利用
-
git clone & git checkoutする
- Login to DockerHub
- DockerHubにログインする
- docker/login-actionを利用
docker login
- Get image tag
- コンテナイメージに付与するタグを指定する
- Set up Docker Buildx
- DockerでコンテナイメージをビルドするためにBuildxをセットアップする
- docker/setup-buildx-action
- Build and Push
- コンテナイメージをビルドしてDockerHub上のイメージリポジトリにプッシュする
- docker/build-push-action
-
docker buildまたはdocker buildx buildに等しい
最終的なワークフローはFufuhu/bash_web_serverの.github/workflows/main.ymlに記載しています。
全体像を示すと次のようになっています。
name: Build and Push Docker Image
on:
push:
branches: [ main ]
workflow_dispatch:
jobs:
build-and-push:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: fufuhu
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Get image tag
id: get-image-tag
run: |
IMAGE_TAG=$(git rev-parse --short HEAD)
echo "tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and Push
uses: docker/build-push-action@v6
with:
push: true
context: .
file: Dockerfile
tags: |
fufuhu/bash_webserver:${{ steps.get-image-tag.outputs.tag }}
fufuhu/bash_webserver:latest
name: Build and Push Docker Imageから分かる通り、Build and Push Docker Imageワークフローとして定義しています。
個別ステップの詳細
Checkout
actions/checkoutを利用して、ソースコードをGitHubのリポジトリから取得している。
steps:
- name: Checkout
uses: actions/checkout@v4
actions/checkoutのオプションで任意のブランチやタグ、コミットを指定することもできるがここでは実施しておらず、デフォルトブランチをチェックアウトするようにしている。
Login to DockerHub
docker/login-actionを利用して、DockerHubにログイン(docker login)している。
- name: Login to Docker Hub
uses: docker/login-action@v3
with:
username: fufuhu
password: ${{ secrets.DOCKERHUB_TOKEN }}
ログイン時のパスワードについてはDockerHubのパーソナルアクセストークンを利用している(password: ${{ secrets.DOCKERHUB_TOKEN }}部分)。
セキュリティの担保のため、GitHubのシークレットを利用している(GitHub Actions でのシークレットの使用を参照)。
DockerHubのパーソナルアクセストークンの取得方法については後述。
Get image tag
ビルドしたコンテナイメージに付与するタグを生成している。
ここでは、git rev-parse --short HEADでgitのショートコミットIDを取得してイメージタグとして利用するようにしている。
- name: Get image tag
id: get-image-tag
run: |
IMAGE_TAG=$(git rev-parse --short HEAD)
echo "tag=$IMAGE_TAG" >> $GITHUB_OUTPUT
echo "tag=$IMAGE_TAG" >> $GITHUB_OUTPUTで、ステップのoutputsとして後段のステップで参照できるようにしている。
Set up Docker Buildx
docker/setup-buildx-actionを用いてBuildxを使ってコンテナイメージをビルドするためのセットアップをしている。
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
Build and Push
docker/build-push-actionによって、Buildxを使ったコンテナイメージのビルドをしている。
tagsの配下にfufuhu/bash_webserver:${{ steps.get-image-tag.outputs.tag }}
とfufuhu/bash_webserver:latestがあるように、同一イメージにsteps.get-image-tag.outputs.tagとlatestの2つのタグを付与してDockerHubにpushしている。
- name: Build and Push
uses: docker/build-push-action@v6
with:
push: true
context: .
file: Dockerfile
tags: |
fufuhu/bash_webserver:${{ steps.get-image-tag.outputs.tag }}
fufuhu/bash_webserver:latest
Login to DockerHubの準備事項
Login to DockerHubでは、docker loginの実行の際に、ユーザー名とパスワードが必要。
パスワードについては、DockerHubのパーソナルアクセストークンを利用している。
このパーソナルアクセストークンは認証情報であるため、公開するのは不適切なため、GitHubのシークレットを用いて安全に利用できるようにしている。
DockerHubのパーソナルアクセストークンの取得手順
DockerHubのパーソナルアクセストークンは、Docke Hubにログインしてから取得する必要があります。
Docker Hubにログインしたら、右上のメニューを開いてMy profileを選択します。

左側メニューからPersonal Access Tokenを選択します。

Generate new access tokenボタンをクリックします。

名前とAccess Permissionを設定します。
Access PermissionにはRead & Writeを指定します。

画面下部のGenerateボタンをクリックすると、パーソナルアクセストークンが生成されます。

dckr_pat_で始まるトークンを保存しておきます。
パーソナルアクセストークンのGitHub Secretへの保存
次に、Login to DockerHubステップでDocker Hubのパーソナルアクセストークンを安全に参照できるように、GitHubのシークレットにパーソナルアクセストークンを保存します。
GitHubリポジトリのSettingsタブを選択します。

Secrets and VariablesのActionsを選択します。

New Repository Secretボタンをクリックします。

シークレットの名前にDOCKERHUB_TOKENを指定し、シークレットにパーソナルアクセストークンの値を指定します。

Add secretボタンをクリックすれば、シークレットの作成は完了です。
あとは、GitHub ActionワークフローとしてBuild and Push Docker Imageを実行すれば良いです。
on:
push:
branches: [ main ]
workflow_dispatch:
ワークフローのトリガーとしてはmainブランチへのコミットのプッシュ(push.branches)、またはGitHub ActionのUIから明示的に呼び出せるようになっています(workflow_dispatch)。
Discussion