Docker マルチステージビルド、buildkit
[History] [Last Modified] (2019/11/05 14:46:25)
ここは
趣味のプログラミングを楽しむための情報共有サービス。記事の一部は有料設定にして公開できます。 詳しくはこちらをクリック📝
Recent posts
Popular pages

概要

初期の Docker には存在しなかった、マルチステージビルドおよび buildkit を利用すると、イメージのビルドを効率化できます。

マルチステージビルド

バージョン 17.05 以降で利用できます。Docker イメージのサイズを小さくするためには、イメージのレイヤを少なくすることが有効です。過去のバージョンの Docker では、まず最初にアプリケーションビルド用の Dockerfile でイメージをビルドして、ビルドしたイメージから docker create してビルド成果物などを取り出し、別の Dockerfile で改めてイメージをビルドする、ということを外部のシェルスクリプトなどで行っていました。このような手順でレイヤを少なくする方法は builder pattern とよばれました。マルチステージビルドを用いると、同様のことが一つの Dockerfile だけで実現できます。以下はマルチステージビルドの例です。

CMakeLists.txt

cmake_minimum_required (VERSION 3.10)
add_executable(main main.cpp)

main.cpp

#include <iostream>

int main() {
    std::cout << "hi" << std::endl;
    return 0;
}

Dockerfile

FROM amd64/gcc:latest AS mybuilder

RUN apt update
RUN apt install -y cmake

RUN mkdir -p /work/build
COPY CMakeLists.txt /work/
COPY main.cpp /work/
WORKDIR /work/build
RUN cmake ..
RUN make

FROM debian:buster-slim
COPY --from=mybuilder /work/build/main /usr/local/bin/myapp
CMD ["myapp"]

ビルド例

docker build -t myapp:latest .
docker run --rm myapp:latest
hi

特定のステージまでをビルドすることもできます。

docker build --target mybuilder -t mybuilder:latest .
docker run --rm mybuilder:latest /work/build/main
hi

サイズおよびレイヤ数に大きな違いがあることが確認できます。

$ docker image ls myapp
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
myapp               latest              af9aea1fedf7        2 minutes ago       69.2MB

$ docker image ls mybuilder
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
mybuilder           latest              317ea3a9255c        2 minutes ago       1.18GB

$ docker history myapp | wc -l
5

$ docker history mybuilder | wc -l
23

DOCKER_BUILDKIT

バージョン 18.09 利用できる buildkit は既定では有効になっておらず、環境変数を設定すると有効になります。

DOCKER_BUILDKIT=1 docker build -t myapp:latest .

有効にした状態であれば、ssh などの認証情報を Dockerfile 内で syntax=docker/dockerfile:experimental の拡張記法で利用できます。

# syntax=docker/dockerfile:experimental
FROM alpine:latest
RUN apk add --no-cache openssh-client git
RUN mkdir -p -m 0600 ~/.ssh && ssh-keyscan github.com >> ~/.ssh/known_hosts
RUN --mount=type=ssh git clone git@github.com:xxx/xxx.git

ビルド例

DOCKER_BUILDKIT=1 docker build --ssh default .
Related pages