Docker 23.0.0リリース! バージョン番号ポリシー変更、BuildKitをデフォルト有効化など #docker #コンテナ
この記事は1年以上前に投稿されました。情報が古い可能性がありますので、ご注意ください。
2023年2月2日、 Docker 23.0.0 がリリースされました。前回の20.10.0リリースから2年ぶりのメジャーバージョンアップで、大きな変更が行われました。速報レベルとなりますがいくつかピックアップしてみたいと思います。詳細はリリースノートをご覧ください。
バージョン番号ポリシーの変更
2017年3月1日、Dockerはそれまでの1.13.1のようなバージョン番号から、17.03という年月バージョン番号ポリシーを導入しました。同時に月例リリースサイクルを採用し、2017年4月には17.04を、2017年5月には17.05をリリース、というように毎月マイナーバージョンが上がっていく形式でした。
しかし、Dockerのバージョンアップを追ってきた方であればご存知かもしれませんが、必ずしもリリース年月とバージョン番号が一致していない事態が頻発しており、わかりにくい状況がありました。
2022年6月4日にベータ版としてリリースされた22.06.0-beta.0は6月内にリリースされなかったどころかその後半年以上音沙汰なく、20.10.xが最新のまま2年が過ぎようとしていました。
そして2022年12月7日、23.0.0-beta.1がベータ版としてリリースされました。このリリースより、年月バージョン番号ポリシーからセマンティックバージョニングに変更することが発表されました。同時に22.06はリリースされないこととなり、23.0.0としてリリースされることとなりました。
BuildKitをデフォルト有効化(Linuxのみ)
23.0.0ではLinuxでBuildKitがデフォルトで有効化されました。BuildKitとは、Dockerイメージの効率的なキャッシュ利用や並列ビルドなどの高速化や、Dockerfileの文法拡張などを行った、いまやLegacy Builderと呼ばれるようになった従来のイメージビルダーの改良版です。またBuildxとは、BuildKitの拡張版であり、23.0.0でこちらもデフォルトで有効となっています。本稿では簡単にするために、BuildKitとBuildxをまとめてBuildKitと呼称します。
BuildKit自体は18.06.0で実験的機能として採用され、18.9.0以降では環境変数DOCKER_BUILDKITを1に設定すれば利用可能でしたが、23.0.0では環境変数の設定なしでBuildKitを利用することができます。
Legacy BuilderとBuildKitの大きな違いはマルチステージビルドの扱いでしょう。Legacy BuilderではマルチステージビルドであってもDockerfileの記述順にビルド処理を行っていましたが、BuildKitは可能な部分を自動的に検出し、効率的なキャッシュ利用や並列でビルド処理を行うため高速な処理が期待できます。
次のDockerfileを見てください。マルチステージビルドを定義しています。
FROM alpine:3.16 AS hello RUN apk add --no-cache alpine-sdk COPY hello.c / RUN gcc -o /hello /hello.c FROM alpine:3.16 AS world RUN apk add --no-cache alpine-sdk COPY world.c / RUN gcc -o /world /world.c FROM alpine:3.16 COPY --from=hello /hello /hello COPY --from=world /world /world CMD /hello ; /world
これをLegacy Builder (22.10.x)でビルドしてみましょう。
% docker image build --no-cache -t multitest:legacy . Sending build context to Docker daemon 6.144kB Step 1/12 : FROM alpine:3.16 AS hello ---> 9c6f07244728 Step 2/12 : RUN apk add --no-cache alpine-sdk ---> Running in 9b199ad76d90 fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/community/x86_64/APKINDEX.tar.gz (1/38) Upgrading musl (1.2.3-r0 -> 1.2.3-r2) (2/38) Installing fakeroot (1.25.3-r3) (3/38) Installing openssl (1.1.1s-r0) (4/38) Installing libattr (2.5.1-r1) (5/38) Installing attr (2.5.1-r1) (6/38) Installing libacl (2.3.1-r0) (7/38) Installing tar (1.34-r0) (8/38) Installing pkgconf (1.8.1-r0) (9/38) Installing patch (2.7.6-r7) (10/38) Installing libgcc (11.2.1_git20220219-r2) (11/38) Installing libstdc++ (11.2.1_git20220219-r2) (12/38) Installing lzip (1.23-r0) (13/38) Installing ca-certificates (20220614-r0) (14/38) Installing brotli-libs (1.0.9-r6) (15/38) Installing nghttp2-libs (1.47.0-r0) (16/38) Installing libcurl (7.83.1-r5) (17/38) Installing curl (7.83.1-r5) (18/38) Installing abuild (3.9.0-r0) Executing abuild-3.9.0-r0.pre-install (19/38) Installing binutils (2.38-r3) (20/38) Installing libmagic (5.41-r0) (21/38) Installing file (5.41-r0) (22/38) Installing libgomp (11.2.1_git20220219-r2) (23/38) Installing libatomic (11.2.1_git20220219-r2) (24/38) Installing gmp (6.2.1-r2) (25/38) Installing isl22 (0.22-r0) (26/38) Installing mpfr4 (4.1.0-r0) (27/38) Installing mpc1 (1.2.1-r0) (28/38) Installing gcc (11.2.1_git20220219-r2) (29/38) Installing musl-dev (1.2.3-r2) (30/38) Installing libc-dev (0.7.2-r3) (31/38) Installing g++ (11.2.1_git20220219-r2) (32/38) Installing make (4.3-r0) (33/38) Installing fortify-headers (1.1-r1) (34/38) Installing build-base (0.5-r3) (35/38) Installing expat (2.5.0-r0) (36/38) Installing pcre2 (10.40-r0) (37/38) Installing git (2.36.4-r0) (38/38) Installing alpine-sdk (1.0-r1) Executing busybox-1.35.0-r17.trigger Executing ca-certificates-20220614-r0.trigger OK: 202 MiB in 51 packages Removing intermediate container 9b199ad76d90 ---> e8e6c5a1eb67 Step 3/12 : COPY hello.c / ---> 6a3055c4ec62 Step 4/12 : RUN gcc -o /hello /hello.c ---> Running in 04f684c60641 Removing intermediate container 04f684c60641 ---> 5e1c6e07db39 Step 5/12 : FROM alpine:3.16 AS world ---> 9c6f07244728 Step 6/12 : RUN apk add --no-cache alpine-sdk ---> Running in a6943e604a38 fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/main/x86_64/APKINDEX.tar.gz fetch https://dl-cdn.alpinelinux.org/alpine/v3.16/community/x86_64/APKINDEX.tar.gz (1/38) Upgrading musl (1.2.3-r0 -> 1.2.3-r2) (2/38) Installing fakeroot (1.25.3-r3) (3/38) Installing openssl (1.1.1s-r0) (4/38) Installing libattr (2.5.1-r1) (5/38) Installing attr (2.5.1-r1) (6/38) Installing libacl (2.3.1-r0) (7/38) Installing tar (1.34-r0) (8/38) Installing pkgconf (1.8.1-r0) (9/38) Installing patch (2.7.6-r7) (10/38) Installing libgcc (11.2.1_git20220219-r2) (11/38) Installing libstdc++ (11.2.1_git20220219-r2) (12/38) Installing lzip (1.23-r0) (13/38) Installing ca-certificates (20220614-r0) (14/38) Installing brotli-libs (1.0.9-r6) (15/38) Installing nghttp2-libs (1.47.0-r0) (16/38) Installing libcurl (7.83.1-r5) (17/38) Installing curl (7.83.1-r5) (18/38) Installing abuild (3.9.0-r0) Executing abuild-3.9.0-r0.pre-install (19/38) Installing binutils (2.38-r3) (20/38) Installing libmagic (5.41-r0) (21/38) Installing file (5.41-r0) (22/38) Installing libgomp (11.2.1_git20220219-r2) (23/38) Installing libatomic (11.2.1_git20220219-r2) (24/38) Installing gmp (6.2.1-r2) (25/38) Installing isl22 (0.22-r0) (26/38) Installing mpfr4 (4.1.0-r0) (27/38) Installing mpc1 (1.2.1-r0) (28/38) Installing gcc (11.2.1_git20220219-r2) (29/38) Installing musl-dev (1.2.3-r2) (30/38) Installing libc-dev (0.7.2-r3) (31/38) Installing g++ (11.2.1_git20220219-r2) (32/38) Installing make (4.3-r0) (33/38) Installing fortify-headers (1.1-r1) (34/38) Installing build-base (0.5-r3) (35/38) Installing expat (2.5.0-r0) (36/38) Installing pcre2 (10.40-r0) (37/38) Installing git (2.36.4-r0) (38/38) Installing alpine-sdk (1.0-r1) Executing busybox-1.35.0-r17.trigger Executing ca-certificates-20220614-r0.trigger OK: 202 MiB in 51 packages Removing intermediate container a6943e604a38 ---> 3e94656e91ec Step 7/12 : COPY world.c / ---> 3792ff12329a Step 8/12 : RUN gcc -o /world /world.c ---> Running in d2c365b38f2a Removing intermediate container d2c365b38f2a ---> f3be1989ca6f Step 9/12 : FROM alpine:3.16 ---> 9c6f07244728 Step 10/12 : COPY --from=hello /hello /hello ---> c0ac7f08eb1d Step 11/12 : COPY --from=world /world /world ---> 3cab1952a351 Step 12/12 : CMD /hello ; /world ---> Running in d67c3469766c Removing intermediate container d67c3469766c ---> 7458d6efce63 Successfully built 7458d6efce63 Successfully tagged multitest:legacy
「hello」ステージと「world」ステージはそれぞれ関係しない独立したステージなのですが、Legacy BuilderではDockerfileの記述通り、順番にビルドしており、時間がかかっています。具体的には両ステージそれぞれで apk add --no-cache alpine-sdk が実行されているので大変無駄です。
ではBuildKitを使ってみましょう。なお「BuildKitはデフォルトで有効」なのですが、別途 docker-buildx-plugin パッケージのインストールが必要になります。未インストールの場合は「BuildKit is enabled but the buildx component is missing or broken.」というエラーとなり、ビルドが実行できないためご注意ください。
% docker image build --no-cache -t multitest:buildkit . [+] Building 19.3s (13/13) FINISHED => [internal] load .dockerignore 0.2s => => transferring context: 2B 0.0s => [internal] load build definition from Dockerfile 0.2s => => transferring dockerfile: 349B 0.0s => [internal] load metadata for docker.io/library/alpine:3.16 0.0s => CACHED [world 1/4] FROM docker.io/library/alpine:3.16 0.0s => [internal] load build context 0.5s => => transferring context: 223B 0.0s => [world 2/4] RUN apk add --no-cache alpine-sdk 11.9s => [world 3/4] COPY world.c / 1.6s => [hello 3/4] COPY hello.c / 1.7s => [world 4/4] RUN gcc -o /world /world.c 2.2s => [hello 4/4] RUN gcc -o /hello /hello.c 2.0s => [stage-2 2/3] COPY --from=hello /hello /hello 0.6s => [stage-2 3/3] COPY --from=world /world /world 1.0s => exporting to image 0.7s => => exporting layers 0.6s => => writing image sha256:02a20ffe7ea100333ad111a61f0eac14e35e547af2360 0.0s => => naming to docker.io/library/multitest:buildkit 0.0s
apk add --no-cache alpine-sdk が1回しか実行されていないこと、「hello」ステージと「world」ステージのCOPYとRUNがDockerfileの順序と異なっていることがわかります。キャッシュを効果的に利用したこととDockerfileの記述順序にとらわれない実行が行われており、Legacy Builderよりビルド時間が大幅に短縮されました。
その他
詳細はリリースノートを参照していただきたいのですが、次のエントリが目につきました。
- Add support for alternate OCI runtimes on Linux, compatible with the containerd runtime v2 API.
- Add experimental support for SwarmKit cluster volumes (CSI).
- Remove LCOW (Linux Containers on Windows).
より詳細な解説はMirantis社ブログやDocker社ブログに掲載されると思いますので、クリエーションラインでは継続的に動向をチェックし、CL LABにて発信していこうと思います。