DockerHub で GitHub や BitbucketGitHub と連携して Docker イメージを自動ビルドすること自体は、既に先人たちが道を切り開いてくださっているので、そちらを参照されたし。
- Docker HubでAutomated Buildを設定する
- 【Docker】GitHubと連携してDockerイメージを自動ビルドする手順
- Qiita 内を "dockerhub 自動ビルド" で検索
本稿では、ちょっと捻くれたことをしている自分が、作業を進める中で得た知見を Tips として共有する。
Dockerfile がソースリポジトリのトップではなく、サブディレクトリの下にある場合
一つのソースリポジトリにディレクトリを掘って、複数の Dockerfile を管理している構成で、例えば directory1 の下にある Dockerfile を自動ビルドしたい場合、
├─ LICENSE
├─ README.md
├─ directory1
│ └─ Dockerfile ← これを自動ビルドしたい
└─ directory2
└─ Dockerfile
BUILD RULE の Build Context の欄に /directory1
と入力すれば良い。以下に例を示す。
Source Type | Source | Docker Tag | Dockerfile location | Build Context |
---|---|---|---|---|
Branch | dir1_dev | latest | Dockerfile | /directory1 |
ただし、directory2 など他のディレクトリの Dockerfile を編集した場合に自動ビルドが暴発しないよう、Source Type 欄や Source 欄の設定内容は注意すること。この例だと、ソースリポジトリの dir1_dev
ブランチに push した時だけ自動ビルドが発動する。
ちなみに、自動ビルドすると DockerHub におけるイメージの紹介ページの Overview の内容が、ソースリポジトリにある README.md の内容で強制的に上書きされる。もし、ソースリポジトリのトップに README.md ファイルが一つだけある構成だったりすると、そのファイルが参照されてしまう。
それだと困る場合の対応策としては、各ディレクトリそれぞれに README.md を保存しておけば良い。Dockerfile と同じディレクトリ内に README.md があれば、そちらが優先して参照される。
├─ LICENSE
├─ README.md ← 同じディレクトリ内になければ、これが参照される
├─ directory1
│ ├─ Dockerfile
│ └─ README.md ← これが優先的に参照される
└─ directory2
├─ Dockerfile
└─ README.md
一度の自動ビルドで複数のタグをつける
例えば、毎回の自動ビルド結果に対して個別のタグを付けると同時に、最新のものは常に latest タグを付けたい…ということを実現したい場合は、BUILD RULE の Docker Tag 欄にカンマ区切りで複数設定すると良い。以下に例を示す。
Source Type | Source | Docker Tag | Dockerfile location | Build Context |
---|---|---|---|---|
Tag | /^[0-9.]+$/ | latest,{sourceref} | Dockerfile | /directory1 |
この例だと、1.0
というタグを打ってソースリポジトリに push した場合、ビルド結果に対して 1.0
と latest
のタグが付けられる。
参考: https://github.com/docker/hub-feedback/issues/341#issuecomment-263705074
hooks/build を上書きした上で、一度の自動ビルドで複数のタグをつける
Dockerfile 内の ARG
に動的に変化する値を渡せるように、自動ビルドのスクリプトを上書きできる仕組みがあるのだが、上述の「一度の自動ビルドで複数のタグをつける」と組み合わせる場合、以下のようなスクリプトではうまくいかない。1
#!/bin/bash
docker build --build-arg CUSTOM=$VAR -f $DOCKERFILE_PATH -t $IMAGE_NAME .
エラーの内容から考察すると、恐らく、環境変数 DOCKER_TAG
には latest,1.0
という文字列が設定されていると考えられるので、for 文を利用して複数のイメージ名を指定するように細工する。加えて、ネットで調べたところ、どうも環境変数 DOCKERFILE_PATH
が空になるケースがあるようなので、念のためその対策もしておく。
以下にスクリプトの例を示す。
#!/bin/bash
set -eu
if [ -z "$DOCKERFILE_PATH" ]
then
file_path_arg=""
else
file_path_arg="-f $DOCKERFILE_PATH"
fi
image_name_arg=""
tags=`echo "$DOCKER_TAG" | sed -e 's/,/ /g'`
for tag in $tags
do
image_name_arg="$image_name_arg -t $DOCKER_REPO:$tag"
done
docker build --build-arg CUSTOM=$VAR $file_path_arg $image_name_arg .
MicroBadger と連携
MicroBadger を利用することで、以下のようなバッジを README.md などに貼り付けることができる。2
イメージのタグ名は、URL 内に埋め込まれているのでそれはそれとして、そのタグを付けたイメージをビルドした際の、ソースリポジトリにおける commit ID を取得するためには、Dockerfile に適切にラベルを設定しておく必要がある。
また、イメージのサイズについては、対象の Docker イメージが更新されたタイミングで webhook を呼び出すように設定しておき、メタ情報の更新の契機を与える必要がある。
…のだが、ちゃんと webhook の設定をしたつもりなのに、イメージのサイズがいつまで経っても "0B" の表示のまま変化しない。MicroBadger のイメージ詳細情報ページを見ても、レイヤ情報の欄が "No matching base image" と表示されてしまう。何故だ!?
公式サイトの "Support" のリンク先となっている GitHub ページの Issues を覗いたら、昨年(2019年)からレイヤ情報やサイズ情報の更新がうまくできていないっぽい。なんてこった。
どうにかならないかと調べた結果、shields.io を利用することで、レイヤ情報だけのバッジを作れるようなので、仕方がないのでそれで代用する。
URL の例: https://img.shields.io/microbadger/layers/obono/arduboy-env:latest.svg →