LoginSignup
2
0

More than 3 years have passed since last update.

DockerHub でイメージを自動ビルドする際の Tips

Posted at

DockerHub で GitHub や BitbucketGitHub と連携して Docker イメージを自動ビルドすること自体は、既に先人たちが道を切り開いてくださっているので、そちらを参照されたし。

本稿では、ちょっと捻くれたことをしている自分が、作業を進める中で得た知見を 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.0latest のタグが付けられる。

参考: https://github.com/docker/hub-feedback/issues/341#issuecomment-263705074

hooks/build を上書きした上で、一度の自動ビルドで複数のタグをつける

Dockerfile 内の ARG に動的に変化する値を渡せるように、自動ビルドのスクリプトを上書きできる仕組みがあるのだが、上述の「一度の自動ビルドで複数のタグをつける」と組み合わせる場合、以下のようなスクリプトではうまくいかない。1

.../hooks/build
#!/bin/bash
docker build --build-arg CUSTOM=$VAR -f $DOCKERFILE_PATH -t $IMAGE_NAME .

エラーの内容から考察すると、恐らく、環境変数 DOCKER_TAG には latest,1.0 という文字列が設定されていると考えられるので、for 文を利用して複数のイメージ名を指定するように細工する。加えて、ネットで調べたところ、どうも環境変数 DOCKERFILE_PATH が空になるケースがあるようなので、念のためその対策もしておく。

以下にスクリプトの例を示す。

.../hooks/build
#!/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" と表示されてしまう。何故だ!?
shot.jpg
公式サイトの "Support" のリンク先となっている GitHub ページの Issues を覗いたら、昨年(2019年)からレイヤ情報やサイズ情報の更新がうまくできていないっぽい。なんてこった。

どうにかならないかと調べた結果、shields.io を利用することで、レイヤ情報だけのバッジを作れるようなので、仕方がないのでそれで代用する。
URL の例: https://img.shields.io/microbadger/layers/obono/arduboy-env:latest.svgMicroBadger Layers


  1. そもそも、build スクリプトを上書きしなかった場合は、どんなスクリプトで処理してるのだろうか? どこかに情報は無いものか。 

  2. MicroBadger のイメージ詳細情報ページの右側にある "Get the badges" からマークダウン記述例を取得できる。 

2
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
0