BuildKit でイメージ構築¶
Docker Build は Docker Engine で最も使われる機能の1つです。利用者の幅は、利用者、開発チーム、リリースチーム、全てが Docker Build を使います。
18.09 のリリースで導入されたのは、構築アーキテクチャの見直しが非常に求められていた、 Docker Build の拡張です。BuildKit (ビルドキット)の統合により、性能、ストレージ管理、特徴的な機能性、セキュリティに関する改善が利用者に分かるでしょう。
- BuildKit が作成した Docker イメージは、以前のビルドが作成した Docker イメージ同様、 Docker Hub に送信可能です
- Dockerfile の形式は、以前の Build の動作と同様に、 BuitKit の構築でも動作します
- ユーザは Dockerfile で指定した新しいイメージの構築は、新しい
--secret
コマンドライン・オプションでシークレット(機微)情報をパスします(訳者注、イメージに記録しません)
build オプションに関する詳しい情報は、リファレンスガイド上の コマンドライン build オプション をご覧ください。
BuildKit での構築を有効化¶
Docker の新規インストールが最も簡単で、 docker build
コマンドの実行時に DOCKER_BUILDKIT`
環境変数を次のように指定します。
$ DOCKER_BUILDKIT=1 docker build .
デフォルトで docker BuildKit を有効化するには、 /etc/docker/daemon.json
のデーモン設定で機能を true にし、デーモンを再起動します。
{ "features": { "buildkit": true } }
新しい Docker Build コマンドラインによる構築の出力¶
新しい docker build BuildKit TTY 出力(デフォルト):
$ docker build .
[+] Building 70.9s (34/59)
=> [runc 1/4] COPY hack/dockerfile/install/install.sh ./install.sh 14.0s
=> [frozen-images 3/4] RUN /download-frozen-image-v2.sh /build buildpa 24.9s
=> [containerd 4/5] RUN PREFIX=/build/ ./install.sh containerd 37.1s
=> [tini 2/5] COPY hack/dockerfile/install/install.sh ./install.sh 4.9s
=> [vndr 2/4] COPY hack/dockerfile/install/vndr.installer ./ 1.6s
=> [dockercli 2/4] COPY hack/dockerfile/install/dockercli.installer ./ 5.9s
=> [proxy 2/4] COPY hack/dockerfile/install/proxy.installer ./ 15.7s
=> [tomlv 2/4] COPY hack/dockerfile/install/tomlv.installer ./ 12.4s
=> [gometalinter 2/4] COPY hack/dockerfile/install/gometalinter.install 25.5s
=> [vndr 3/4] RUN PREFIX=/build/ ./install.sh vndr 33.2s
=> [tini 3/5] COPY hack/dockerfile/install/tini.installer ./ 6.1s
=> [dockercli 3/4] RUN PREFIX=/build/ ./install.sh dockercli 18.0s
=> [runc 2/4] COPY hack/dockerfile/install/runc.installer ./ 2.4s
=> [tini 4/5] RUN PREFIX=/build/ ./install.sh tini 11.6s
=> [runc 3/4] RUN PREFIX=/build/ ./install.sh runc 23.4s
=> [tomlv 3/4] RUN PREFIX=/build/ ./install.sh tomlv 9.7s
=> [proxy 3/4] RUN PREFIX=/build/ ./install.sh proxy 14.6s
=> [dev 2/23] RUN useradd --create-home --gid docker unprivilegeduser 5.1s
=> [gometalinter 3/4] RUN PREFIX=/build/ ./install.sh gometalinter 9.4s
=> [dev 3/23] RUN ln -sfv /go/src/github.com/docker/docker/.bashrc ~/.ba 4.3s
=> [dev 4/23] RUN echo source /usr/share/bash-completion/bash_completion 2.5s
=> [dev 5/23] RUN ln -s /usr/local/completion/bash/docker /etc/bash_comp 2.1s
新しい docker build BuildKit の簡易出力:
$ docker build --progress=plain .
#1 [internal] load .dockerignore
#1 digest: sha256:d0b5f1b2d994bfdacee98198b07119b61cf2442e548a41cf4cd6d0471a627414
#1 name: "[internal] load .dockerignore"
#1 started: 2018-08-31 19:07:09.246319297 +0000 UTC
#1 completed: 2018-08-31 19:07:09.246386115 +0000 UTC
#1 duration: 66.818µs
#1 started: 2018-08-31 19:07:09.246547272 +0000 UTC
#1 completed: 2018-08-31 19:07:09.260979324 +0000 UTC
#1 duration: 14.432052ms
#1 transferring context: 142B done
#2 [internal] load Dockerfile
#2 digest: sha256:2f10ef7338b6eebaf1b072752d0d936c3d38c4383476a3985824ff70398569fa
#2 name: "[internal] load Dockerfile"
#2 started: 2018-08-31 19:07:09.246331352 +0000 UTC
#2 completed: 2018-08-31 19:07:09.246386021 +0000 UTC
#2 duration: 54.669µs
#2 started: 2018-08-31 19:07:09.246720773 +0000 UTC
#2 completed: 2018-08-31 19:07:09.270231987 +0000 UTC
#2 duration: 23.511214ms
#2 transferring dockerfile: 9.26kB done
デフォルトのフロントエンドを上書き¶
デフォルトのフロントエンドを上書きすると、 Dockerfile
で新しい構文機能が利用可能です。デフォルトのフロントエンドを上書きするには、 Dockerfile
の1行目に、特定のフロントエンド・イメージをコメントとして指定します。
# syntax = <frontend image>, e.g. # syntax = docker/dockerfile:1.0-experimental
新しい Docker Build シークレット情報¶
docker build の新しい --secret
フラグは、Dockerfile でシークレット情報(機微情報)をユーザが渡す必要があるときに、docker イメージを安全に構築するための方法であり、最終イメージにシークレットを保存しません。
id
は docker build --secret
を渡すための識別子です。この識別子は Dockerfile 中で使う RUN --mount
識別子と関連付けられます。この情報はセンシティブな情報となりうるため、Docker は secret がどこにあるかをファイル名を使わずに、Dockerfile の外で保持します。
dst
はシークレット用のファイルを、 Dockerfile の RUN
コマンドで使う特定のファイルに名称変更します。
たとえば、テキストファイル中に秘密情報の一部を保存します。
$ echo 'WARMACHINEROX' > mysecret.txt
そして、Dockerfile 側では、Buildkit フロントエンド docker/dockerfile:1.0-experimental
を使う指定をしたら、シークレット機能が利用できます。
例:
# syntax = docker/dockerfile:1.0-experimental
FROM alpine
# デフォルトのシークレットの場所から、シークレットを表示
RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
# 任意のシークレットの場所から、シークレットを表示
RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar
この Dockerfile はシークレットがアクセス可能であるというデモンストレーションです。ご覧の通り、シークレットは構築の出力で表示されます。最終イメージのビルドでは、このシークレット・ファイルを持ちません。
$ docker build --no-cache --progress=plain --secret id=mysecret,src=mysecret.txt .
...
#8 [2/3] RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret
#8 digest: sha256:5d8cbaeb66183993700828632bfbde246cae8feded11aad40e524f54ce7438d6
#8 name: "[2/3] RUN --mount=type=secret,id=mysecret cat /run/secrets/mysecret"
#8 started: 2018-08-31 21:03:30.703550864 +0000 UTC
#8 1.081 WARMACHINEROX
#8 completed: 2018-08-31 21:03:32.051053831 +0000 UTC
#8 duration: 1.347502967s
#9 [3/3] RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar
#9 digest: sha256:6c7ebda4599ec6acb40358017e51ccb4c5471dc434573b9b7188143757459efa
#9 name: "[3/3] RUN --mount=type=secret,id=mysecret,dst=/foobar cat /foobar"
#9 started: 2018-08-31 21:03:32.052880985 +0000 UTC
#9 1.216 WARMACHINEROX
#9 completed: 2018-08-31 21:03:33.523282118 +0000 UTC
#9 duration: 1.470401133s
...
構築時に SSH でプライベート・データにアクセス¶
参考
Build secrets and SSH forwarding in Docker 18.09 に詳しい情報と例がありますのでご覧ください。
docker build
で --ssh
オプションを付けると、 Docker Engine は SSH エージェント接続の転送が可能になります。SSH エージェントに関する情報は OpenSSH の man ページ をご覧ください。
Dockerfile
中の命令で、 type=ssh
マウントの定義で明確に SSH アクセスを要求すると、SSH エージェントとの接続が可能になります。その他の方法では、SSH エージェントと通信することはできません。
Dockerfile
中で RUN
コマンドで SSH アクセスの要求をするには、マウント時のタイプを ssh
と定義します。これは SSH_AUTH_SOCK
環境変数をセットアップし、プログラムが SSH でそのソケットを自動的に使うのに依存します。
こちらはコンテナ内で SSH を使う Dockerfile の例です:
# syntax=docker/dockerfile:experimental
FROM alpine
# ssh クライアントと git をインストール
RUN apk add --no-cache openssh-client git
# github.com のための公開鍵をダウンロード
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
# プライベート・リポジトリのクローン
RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git myproject
Dockerfile
が作成されれば、 --ssh
オプションを使ってで SSH エージェントと接続できます。
$ docker build --ssh default .
トラブルシューティング:プライベート・レジストリでの問題¶
x509:未知の認証局によって書名された証明書¶
安全ではない(自己書名した証明書の)レジストリ(insecure registry)からイメージを取得しようとすると、あるいはレジストリをミラーとして使おうとすると、Docker 18.09 では以下の問題に直面します。
[+] Building 0.4s (3/3) FINISHED
=> [internal] load build definition from Dockerfile
=> => transferring dockerfile: 169B
=> [internal] load .dockerignore
=> => transferring context: 2B
=> ERROR resolve image config for docker.io/docker/dockerfile:experimental
------
> resolve image config for docker.io/docker/dockerfile:experimental:
------
failed to do request: Head https://repo.mycompany.com/v2/docker/dockerfile/manifests/experimental: x509: certificate signed by unknown authority
解決策:適切にレジストリを安全にします。 Let's Encrypt の SSL 証明書は無料で取得できます。 レジストリ・サーバのデプロイ をご覧ください。
Sonatype Nexus バージョン 3.15 未満の上でプライベート・レジストリを実行中に、イメージが見つからない¶
Sonatype Nexus バージョン 3.15 未満を使い、プライベート・レジストリを事項中であれば、以下のようなエラーメッセージが表示されるでしょう。
------
> [internal] load metadata for docker.io/library/maven:3.5.3-alpine:
------
------
> [1/4] FROM docker.io/library/maven:3.5.3-alpine:
------
rpc error: code = Unknown desc = docker.io/library/maven:3.5.3-alpine not found
おそらくこのバグに直面しました: NEXUS-12684
解決策は、Nexus をバージョン 3.15 以上にアップグレードします。
参考
- Build images with BuildKit
- https://docs.docker.com/develop/develop-images/build_enhancements/