初期の 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
バージョン 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 .