🤖

🤖

:gijutsu_burogu:

Dockerfileを書かずにBuildpacksで圧倒的に軽量なDockerイメージを作成する(539MB->245MB)

はじめに

2018 年 10 月に Cloud Native Buildpacks は Cloud Native Computing Foundation (CNCF)に Sandbox として受け入れられました。 CNCF には Kubernetes, Prometheus, Envoy, Fluentd など有名プロジェクトも多く受け入れられています。 Buildpacks を使うことで、Dockerfile を書かなくても Docker イメージを作成できます。 また、作成されるイメージはかなり軽量でした。

buildpacks.io

試してみた

今回は、以下のリポジトリ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)

github.com

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 になりました。