Docker Hubを見ていると,「Source Repository」にGithubリポジトリのリンクがあるものが多いです.
ということで,githubにあるDockerfileを自動ビルドしてDocker Hubに登録してくれる機能とかあるんだろうなと思って「github dockerhub 連携」とかでググると,みんなDocker Hubの「Automated Build」なるものを使っていることがわかります.
各記事見てると,まず「Docker Hubのアカウント設定からLinked Accountsを選んでGithubを連携させましょう」とか書いてるのですが,僕のDocker HubにはLinked Accountsなんてありません......🤔
よくよく公式ドキュメントを読むと,Automated BuildはDocker Hub課金勢(Pro, Teams, Business)のみの機能と書かれているではないですか...!😩😩
Docker Hubに課金してもよいのですが,一番安いProプランでも月5ドルという...
高くはないですが,エンジョイ趣味勢で月額課金はツラいです.ここは無課金で乗り切りたいところ.
前置きが長くなりましたが,こういうことで,Docker Hub無課金勢(Personal Plan)でもgithubからDockerイメージを自動でBuild & Pushする方法についてまとめます.
方針としては,Github Actionsを使ってCI/CD的に実施します.が,筆者はGithub Actionsを使うのは今回が初めて(お仕事はGitLab...)なので,問題あるかもですが責任は取りません.あくまでご参考にどうぞ(免責)
ほぼここに書かれてる内容になるので,分かる人はこちらを見てください.
もしくは,今回使用するyamlファイルをご覧ください.
- 前提
- Docker Hubのアカウント情報をGithubに設定する
- Github Actionsのワークフローの設定
- GithubへPush(から,自動でDockerイメージのBuild & Push)
- その他
- まとめ
前提
以下はすでにあるものとします
今回の記事では,以下のリポジトリを使ってます
ちなみに,Docker Hub側にリポジトリを用意する必要は必ずしもありません.
Docker Hubのアカウント情報をGithubに設定する
Github ActionsでDocker Hubへログインする都合上,GithubのリポジトリにDocker Hubのユーザ名とパスワードを登録します.ここでは,GithubのEncrypted secrets機能を使います.
Githubのレポジトリの「Settings > Secrets」から設定できます.
ここに,「DOCKERHUB_USERNAME」というNameでDocker Hubのユーザ名を,「DOCKERHUB_PASSWORD」というNameでDocker Hubのパスワードを登録します.
Github Actionsのワークフローの設定
githubのリポジトリのルートから.github/workflows
というディレクトリを切って,build-and-push-image.yml
というファイルを作り(ファイル名は任意です),以下を記述します.
name: Build and Push image to Docker Hub on: push: branches: - master jobs: build_and_push: runs-on: ubuntu-latest steps: - name: Check out the repo uses: actions/checkout@v2 - name: Log in to Docker Hub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Extract metadata for Docker id: meta uses: docker/metadata-action@v3 with: images: mu777/odrive-cli - name: Build and push Docker image uses: docker/build-push-action@v2 with: context: . push: true tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }}
これはこちらのドキュメントから持ってきたものです.
ここでは,masterブランチでpushされた場合にこれが発火するように設定しています.適宜on
の項目を変更してください.
使用しているアクションは以下です
- Checkout · Actions · GitHub Marketplace · GitHub
- Docker Login · Actions · GitHub Marketplace · GitHub
- Docker Metadata action · Actions · GitHub Marketplace · GitHub
- Build and push Docker images · Actions · GitHub Marketplace · GitHub
「Extract metadata for Docker」ステップのwith: images
のところは適宜ご自身のDocker Hubの「namespace/repository」に変更してください.
GithubへPush(から,自動でDockerイメージのBuild & Push)
追加したワークフローをコミットして,GithubへPushしましょう.
$ git add .github $ git commit -m "Add github actions" $ git push origin master
Githubのリポジトリの「Action」から実行の結果を確認できます.
Docker Hubを見ると,イメージがpushされていることがわかります.事前にDocker Hub側にリポジトリを作っていなかった場合は自動でリポジトリも作成されます.
ローカルでdocker pull
すると,ちゃんとDocker Hubから持ってくることができました!🎉🎉
その他
上記手順が目的への最小ステップと思われますが,更に追加でやりたいことを以下に挙げます.
Dockerイメージにlatestタグをつけたい!
上記手順だと,ブランチ名がタグになってしまいます.
手順
「Docker Metadata action」にflavor
パラメータを追加します.
- name: Extract metadata (tags, labels) for Docker
id: meta
uses: docker/metadata-action@v3
with:
images: mu777/odrive-cli
+ flavor: latest=true
「Docker Metadata action」ではもっと様々な条件でtag名を変更させることができるようですが,ここでは深入りしません.
詳細はドキュメントをご覧ください.
GithubのReadmeをDocker Hub側にも表示させたい!
上記手順だけだと,Docker HubのReadmeはDocker Hub側で作成する必要があります.
さすがにGithubとDocker Hubのダブルメンテは面倒なので,共有できるようにしましょう.
(これも,Automated Buildだと自動でできるみたいです... 金が欲しい......)
手順
Docker Hub Description アクションを使います.
以下のStepをgithub/workflows/build-and-push-image.yml
の一番最後に追加します.
- name: Docker Hub Description uses: peter-evans/dockerhub-description@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} repository: mu777/odrive-cli readme-filepath: ./README.md short-description: ${{ github.event.repository.description }}
このアクションは個人の方が作られているものなので,気になる方はご注意ください.
ソースを見る感じパスワードを抜いたりしているわけではないと思われますが,改悪が起こる可能性も無きにしもあらず......
(まぁ他で使っているDocker公式のアクションも「not certified by GitHub」ではあるのですが......)
複数CPUアーキテクチャ対応のイメージを自動ビルドしたい!
上記手順のruns-on: ubuntu-latest
環境だと,AMD64(x86-64)でDockerビルドが実行されます.
実際に確認したわけではないですが,これだとARMなど他の環境だと動かないはずです.
これを他のCPUアーキテクチャでも動くイメージもbuild & pushしておくようにしましょう.
手順
Docker Setup Buildx アクションで,複数CPUアーキテクチャでDockerビルドするための機能であるDocker Buildxを使います.
以下の3つのStepを,github/workflows/build-and-push-image.yml
の「Build and push Docker image」の前のどこかに追加します.
- name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v1 - name: Available platforms run: echo ${{ steps.buildx.outputs.platforms }}
さらに,「Build and push Docker image」ステップのwith
項にplatforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7,linux/arm/v6
を追加し,対応させるアーキテクチャを指定します.
- name: Build and push Docker image
uses: docker/build-push-action@v2
with:
context: .
push: true
+ platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7,linux/arm/v6
tags: ${{ steps.meta.outputs.tags }}
labels: ${{ steps.meta.outputs.labels }}
これらのStepを加えたアクションを実行後,Docker Hubで複数アーキテクチャが登録されていることを確認できます.
注意: ベースイメージの対応アーキテクチャ
ベースイメージが対応していないアーキテクチャではビルドできないのでご注意ください.
今回の例で言うと,ベースイメージのpythonイメージが対応しているアーキテクチャは以下です.
もちろんこれ以外のアーキテクチャではベースイメージが使えないので,以下のようなエラーでGithub Actionsがコケます.
Error: buildx failed with: error: failed to solve: python:3.7: no match for platform in manifest sha256:d9abbc0737ff8d23a546859c85903f1b8235a1495a405d5a47cbc55747f27b20: not found
まとめ
結局一番言いたかったのは,最初のAutomated BuildはDocker Hub課金勢(Pro, Teams, Business)のみということだけでした(地味にその情報にたどり着けずにハマってしまった).
とりあえず,「その他」の項を含めて全ての内容をまとめたbuild-and-push-image.yml
の中身を最後に載せておきます.
name: Build and Push image to Docker Hub on: push: branches: - master jobs: build_and_push: runs-on: ubuntu-latest steps: - name: Check out the repo uses: actions/checkout@v2 - name: Log in to Docker Hub uses: docker/login-action@v1 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} - name: Set up QEMU uses: docker/setup-qemu-action@v1 - name: Set up Docker Buildx id: buildx uses: docker/setup-buildx-action@v1 - name: Available platforms run: echo ${{ steps.buildx.outputs.platforms }} - name: Extract metadata (tags, labels) for Docker id: meta uses: docker/metadata-action@v3 with: images: mu777/odrive-cli flavor: latest=true - name: Build and push Docker image uses: docker/build-push-action@v2 with: context: . push: true platforms: linux/amd64,linux/arm64,linux/386,linux/arm/v7,linux/arm/v6 tags: ${{ steps.meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} - name: Docker Hub Description uses: peter-evans/dockerhub-description@v2 with: username: ${{ secrets.DOCKERHUB_USERNAME }} password: ${{ secrets.DOCKERHUB_PASSWORD }} repository: mu777/odrive-cli readme-filepath: ./README.md short-description: ${{ github.event.repository.description }}