Dockerfileを書かずにBuildpacksで圧倒的に軽量なDockerイメージを作成する(539MB->245MB)
はじめに
2018 年 10 月に Cloud Native Buildpacks は Cloud Native Computing Foundation (CNCF)に Sandbox として受け入れられました。 CNCF には Kubernetes, Prometheus, Envoy, Fluentd など有名プロジェクトも多く受け入れられています。 Buildpacks を使うことで、Dockerfile を書かなくても Docker イメージを作成できます。 また、作成されるイメージはかなり軽量でした。
試してみた
今回は、以下のリポジトリの Java アプリケーションの Docker イメージを作成します。 github.com
インストール
# Mac $ brew install buildpacks/tap/pack # Linux $ wget https://github.com/buildpacks/pack/releases/download/v0.12.0/pack-v0.12.0-linux.tgz $ tar xvf pack-v0.12.0-linux.tgz $ rm pack-v0.12.0-linux.tgz $ ./pack --help # Windows $ choco install pack --version=0.12.0
チュートリアルにある例 (301MB)
pack build <image-name>
でイメージを作成します。
301MB のイメージが作成されました。
docker run
でアプリケーションを起動できました。
$ pack build myapp --builder cnbs/sample-builder:bionic $ docker run -it -p 8080:8080 myapp:latest
ビルダーを--builder
で指定します。
他にもさまざまなビルダーを選択できます。
Suggested builders: Google: gcr.io/buildpacks/builder:v1 Ubuntu 18 base image with buildpacks for .NET, Go, Java, Node.js, and Python Heroku: heroku/buildpacks:18 heroku-18 base image with buildpacks for Ruby, Java, Node.js, Python, Golang, & PHP Paketo Buildpacks: gcr.io/paketo-buildpacks/builder:base Ubuntu bionic base image with buildpacks for Java, NodeJS and Golang Paketo Buildpacks: gcr.io/paketo-buildpacks/builder:full-cf cflinuxfs3 base image with buildpacks for Java, .NET, NodeJS, Golang, PHP, HTTPD and NGINX Paketo Buildpacks: gcr.io/paketo-buildpacks/builder:tiny Tiny base image (bionic build image, distroless run image) with buildpacks for Golang
spring-boot(2.3.0) からの新機能 (245MB)
Java 限定の話になりますが、Spring Boot 2.3.0 から Buildpacks を内部的に使っている機能が組み込まれました。
mvn spring-boot:build-image
で Docker イメージを作成できます。
pom.xml
を編集してビルドするプロジェクトの Spring Bootのバージョンを 2.3.0 以上へアップデートします。
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent>
mvn spring-boot:build-image
でビルドできます。
245MBと最も軽量なイメージが作成されました。
docker run
でアプリケーションを起動できました。
$ mvn spring-boot:build-image $ docker run -it -p 8080:8080 sample:0.0.1-SNAPSHOT
自分で Doker Build (539MB)
自分で Dockerfile を書く方法です。 マルチステージビルドを利用してビルドしても、他より重い539MB でした。
FROM maven:3.6.3-jdk-8 as builder WORKDIR /apps/java-maven COPY pom.xml pom.xml RUN mvn dependency:resolve COPY src src RUN mvn package -DskipTests=true FROM openjdk:8 WORKDIR /apps/java-maven COPY --from=builder /apps/java-maven/target/sample-0.0.1-SNAPSHOT.jar /apps/java-maven/target/sample-0.0.1-SNAPSHOT.jar ENTRYPOINT ["java", "-jar", "/apps/java-maven/target/sample-0.0.1-SNAPSHOT.jar"] EXPOSE 8080
通常通り、以下のコマンドでビルドしてアプリケーションを起動します。
$ docker build -t self-build . $ docker run -it -p 8080:8080 self-build:latest
おわりに
本記事では Java での例でしたが、Go,Node,Ruby,PHP,Python などであればビルドできます。
pack build <image-name> --builder gcr.io/paketo-buildpacks/builder:tiny
などのコマンドで言語にあったビルダーを指定すればビルドできます。
自分で Docker ビルドをする場合はイメージは 539MB でしたが、Buildpacks を利用すれば Dockerfile を書かなくてもすむ上にイメージは 245MB になりました。
なんで小さくなるかはdiveで深掘りしたり、ドキュメント読んだりしてまた記事にしますか
— kotaroooo0 (@kotaroooo0) 2020年8月16日