Tech Knowledge

IT技術者の知識共有を目的とした記事を書いています

Dockerfileのベストプラクティス: コンテナイメージの最適化

Dockerfileのベストプラクティスについて

Dockerfileは、Dockerイメージを作成するための命令セットです。Dockerfileを書くときには、いくつかのベストプラクティスに従うことが推奨されます。これらのベストプラクティスは、イメージのサイズ、ビルド時間、セキュリティ、メンテナンス性などを改善するのに役立ちます。ここでは、Dockerfileのベストプラクティスの一部を紹介します。

ベースイメージを適切に選択する

ベースイメージは、Dockerfileの最初の命令で指定されるイメージです。ベースイメージは、アプリケーションに必要な最小限の依存関係やランタイムを含むものを選ぶべきです。例えば、Pythonアプリケーションを作る場合は、python:3.9-alpineという軽量なベースイメージを使うことができます。不要なパッケージやファイルを含むベースイメージを使うと、イメージのサイズが大きくなり、ビルド時間が長くなり、セキュリティリスクが高まります。

マルチステージビルドを利用する

マルチステージビルドとは、一つのDockerfileで複数のイメージを作成し、最終的なイメージに必要なファイルだけをコピーする方法です。マルチステージビルドを使うと、ビルド時に必要なツールやライブラリを含む中間イメージを作成し、最終的なイメージにはアプリケーションの実行に必要なファイルだけを残すことができます。これにより、イメージのサイズを小さくし、セキュリティを向上させることができます。例えば、Goアプリケーションを作る場合は、以下のようなマルチステージビルドを使うことができます。

# ビルドステージ
FROM golang:1.18 as builder

# 作業ディレクトリの設定
WORKDIR /app

# 依存関係の管理ファイルをコピー
COPY go.mod ./
COPY go.sum ./

# 依存関係のダウンロード
RUN go mod download

# ソースコードをコピー
COPY *.go ./

# バイナリのビルド
RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o myapp .

# 実行ステージ
FROM alpine:latest

# ビルドステージからバイナリをコピー
COPY --from=builder /app/myapp .

# アプリケーションの実行
CMD ["./myapp"]

キャッシュを効率的に利用する

Dockerは、ビルド時に各命令ごとにレイヤーと呼ばれるキャッシュを作成します。同じ命令が再度実行される場合は、キャッシュされたレイヤーを再利用します。これにより、ビルド時間を短縮することができます。しかし、キャッシュは無効化される可能性もあります。例えば、COPY命令でファイルやディレクトリをコピーする場合は、コピー元の内容が変更されているかどうかによってキャッシュが無効化されます。そのため、頻繁に変更されるファイルやディレクトリは後ろの方でコピーすることが望ましいです。

レイヤーをまとめる

RUN命令で複数のコマンドを実行する場合は、&&や\でつなげることで一つのレイヤーにまとめることができます。これにより、レイヤーの数を減らし、イメージのサイズを小さくすることができます。例えば、以下のように書くことができます。

RUN apt-get update && \
    apt-get install -y curl && \
    rm -rf /var/lib/apt/lists/*

ビルド時と実行時の引数を使う

Dockerfileでは、ビルド時にARG命令で引数を定義し、ビルド時に--build-argオプションで値を渡すことができます。これにより、ビルド時に動的に値を変更することができます。例えば、以下のように書くことができます。

ARG VERSION
FROM node:${VERSION}-alpine
docker build --build-arg VERSION=16 .

実行時には、ENV命令で環境変数を定義し、実行時に-eオプションで値を渡すことができます。これにより、実行時に動的に値を変更することができます。例えば、以下のように書くことができます。

ENV PORT=3000
EXPOSE ${PORT}
CMD ["node", "server.js"]
docker run -e PORT=8000 -p 8000:8000 image_name

メタデータを付与する

Dockerfileでは、LABEL命令でイメージにメタデータを付与することができます。メタデータは、イメージの作成者や説明などを記述するのに役立ちます。また、Docker HubやGitHub Container Registryなどのレジストリにイメージを公開する場合は、メタデータを使ってイメージの品質や信頼性を向上させることができます。例えば、以下のように書くことができます。

LABEL maintainer="example@example.com"
LABEL description="This is a sample image"
LABEL org.opencontainers.image.source="https://github.com/example/repo"

まとめ

以上は、Dockerfileのベストプラクティスの一部です。他にも多くのベストプラクティスがありますので、詳しくは公式ドキュメントや参考文献をご覧ください。

docs.docker.com General best practices for writing Dockerfiles | Docker Docs Best practices for Dockerfile instructions | Docker Docs

Written with Copilot