🐳
軽量なDockerイメージを作るために意識すること
はじめに
今まで個人開発でなんとなくDockerを触るレベルでしたが、
転職を機に実務でDockerを触れる機会が増えてきました。
なんとなく使っていたDockerへの理解を深めるためにも、
より軽量なDockerイメージの作り方についてメモします。
なぜ軽量なイメージを作るのか
- ビルド時間の短縮
- トライアンドエラーがしやすくなる
- 生産性が高まる
- Dockerイメージをpush/pullする時間の短縮
- CI/CDにかかる時間の短縮
- オートスケール時にかかる時間の短縮
- ストレージの節約
軽量なDockerイメージを作るために
軽量なベースイメージを選ぶ
- Debian
- UbuntuなどのLinuxディストリベーションベース
- 広く普及して安定している
- バージョンごとに
-buster
(v10)や-bullseye
(v11) などのコードネームがつく
- Alpine
- 組み込み系で多く利用される
BusyBox
ベース - リソース効率を重視しており軽量
- 標準Cライブラリが
musl
のため、glibc
との互換性の問題が発生するケースがある
- 組み込み系で多く利用される
- -slim
- 上記のようなイメージから、使用頻度の低いライブラリを削ったもの
- distoless
- OSを含まずに、言語にフォーカスしたDockerイメージ
- Googleにより公開
- gcr.io/distroless/python3-debian11
- gcr.io/distroless/nodejs18-debian11 など
不要なファイルをコンテナに含めない
-
Dockerfile
を空のディレクトリに配置し、構築に必要なファイルだけ追加する - もしくは、
Dockerfile
と同じ階層に.dockerignore
を作成する-
.git
などの不要な隠しフォルダなどに注意する
-
.dockerignore
.git
*.log
レイヤー数を減らす
-
RUN
やCOPY
などの命令単位でレイヤーが作成される -
&&
や\
を使いコマンドを並列することで、レイヤー数を減らせる
# レイヤーが2つの場合
RUN apt update
RUN apt install -y bzr cvs git mercurial
# レイヤーが1つの場合
RUN apt update && \
apt install -y bzr \
cvs \
git \
mercurial \
頻繁に変更されるものは後に記述する
- 変更のないレイヤーは処理をスキップすることができる
- ソースコードの
COPY
など、頻繁に更新されるものはDockerfile
の後ろ側に記述することで、ビルド内容をキャッシュできる
# キャッシュを活かせない場合(/appにソースコードが含まれる例)
COPY . /app
RUN apt update && apt install git
# キャッシュを活かせる場合(変更がない場合RUNのレイヤーをスキップできる)
RUN apt update && apt install git
COPY . /app
マルチステージビルドを活用する
- コンテナをビルド用のコンテナと、実行用のコンテナに分ける
- ビルド済みの軽量なコンテナのみデプロイできる(ビルド用のコンテナは破棄される)
# ビルド用のコンテナ
FROM golang:1.16 as build
WORKDIR /go/src/github.com/alexellis/href-counter/
RUN go get -d -v golang.org/x/net/html
COPY app.go ./
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o app .
# 実行用のコンテナ
FROM alpine:latest as prod
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY /go/src/github.com/alexellis/href-counter/app ./
CMD ["./app"]
まとめ
軽量なDockerイメージを作るために、
- 軽量なベースイメージを選ぶ
- 不要なファイルをコンテナに含めない
- レイヤー数を減らす
- 頻繁に変更されるものは後に記述する
- マルチステージビルドを活用する
の5つをまとめてみました。
上記以外にも有効な手段や、意識するといいことが見つかり次第、
内容追加していきたいと思います。
参考
Discussion
良記事ありがとうございます!!
わわ、ありがとうございます!!