LoginSignup
6
5

More than 3 years have passed since last update.

[Docker]クソ重いHello, World!イメージを劇的に軽くする

Last updated at Posted at 2020-02-07

Docker v17くらいからMultiStageBuildという機能が実装されています。
今まで、「Hello,Worldを出力するだけのImageなのに、ベースImageサイズが大きくて、結局出来上がるImageも数百MBになるんだけど、、、」と、なっていたものが、BuildはGoのImage,実行はalpineのImageとできるようになりました。(v17以前でもできなくはなかったけど、めんどくさかった)
これが一体どういうことなのかをみていきたいと思います。

今回は、Hello, World!を出力するコンテナを作成していきます。

main.go
package main

import "fmt"

func main() {
        fmt.Println("Hello, World!")
}

MultiStageBuildを使わない場合

Dockerfileは以下のようになります。

FROM golang:1.13.7-alpine3.11

COPY ./main.go ./

RUN go build -o ./hello ./main.go

ENTRYPOINT ["./hello"]

それぞれ同じディレクトリに存在する状態で、以下のコマンドを打ってみましょう。

$ docker build -t hello:0.1 .

ビルド出来たらRunしてみます。

$ docker run hello:0.1
Hello World!

ちゃんとmain.goがbuildされて、実行されました。では、この時のImageサイズをみてみます。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello               0.1                 ea6e8238c063        49 seconds ago      361MB
golang              1.13.7-alpine3.11   87eefb76f0a8        9 days ago          359MB

このように、golangのcontainer Imageがベースになっているため、サイズが大きくなっています。
Hello, World!を出力するだけのコンテナなのに、これじゃあ重すぎですね。。。

MultiStageBuildを使う場合

Dockerfileは以下のようになります。

#Stage 1
FROM golang:1.13.7-alpine3.11 as builder
COPY ./main.go ./
RUN go build -o /hello ./main.go

#Stage 2
FROM alpine:3.11
COPY --from=builder /hello .
ENTRYPOINT ["./hello"]

Stage1はgolangのImageを使っていて、ここでmain.goをbuildしています。そしてその実行ファイルをStage2に持ってきて、こっちで実行すると言う形です。

$ docker run hello:0.1
Hello World!

こちらもちゃんと実行されました。同様に、Imageのサイズをみてみます。

$ docker images
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
hello               0.1                 15f814bf3a87        12 seconds ago      7.6MB
<none>              <none>              6f908ead16f8        13 seconds ago      361MB
golang              1.13.7-alpine3.11   87eefb76f0a8        9 days ago          359MB
alpine              3.11                e7d92cdc71fe        2 weeks ago         5.59MB

ここで<none>はStage1のImageで、<hello>がStage2のImageになっています。Hello, Worldを出力するImageは<hello>なので、そのサイズなんと7.6MBです!MultiStageBuildを使わない場合と比べて約350MBもImageサイズを削減することを実現できました!!

まとめ

ということで、今回はDockerのMultiStageBuildの機能について、触れてみました。サイズの重たいBuild環境を分離することで、Imageサイズの削減を可能にすることを挙げましたが、他にもStageで分けることで、Dockerfileの保守のしやすさが上がる、セキュリティに強くなるなど、良い事が沢山あります!みなさまも使った事がない方は一度チャレンジしてみてください!

6
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
5