クラウドネイティブな開発において、Dockerコンテナは本番デプロイのデファクトスタンダードとなっています。
しかし、セキュリティ対策を意識せずに構築されたコンテナイメージは、OSの脆弱性、不要なパッケージ、ルート権限でのプロセス実行など、重大なセキュリティリスクを抱えがちです。本記事では、Dockerイメージを堅牢化し、本番環境での脅威を最小化するためのベストプラクティスを解説します。
1. マルチステージビルド(Multi-stage Builds)の徹底
コンテナイメージの中に、ビルドに必要なコンパイラ、SDK、不要な開発用ツール(gitやnpmなど)をそのまま残しておくと、イメージサイズが肥大化するだけでなく、アタックサーフェス(攻撃対象領域)を広げてしまいます。
マルチステージビルドを利用し、最終的なイメージには「ビルド成果物」と「実行に必要な最小限のランタイム」だけを格納するようにします。
# ステージ1: ビルド環境
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp main.go
# ステージ2: 実行用最小イメージ
FROM alpine:3.19
WORKDIR /app
COPY --from=builder /app/myapp .
EXPOSE 8080
CMD ["./myapp"]
2. ルート(root)ユーザーでの実行を避ける
デフォルトでは、Dockerfile内の命令およびコンテナ内プロセスは root(特権ユーザー) として実行されます。万が一コンテナ内のアプリがハッキングされた場合、ホストマシン側のカーネルやファイルシステム全体にアクセスされる深刻なリスクが生じます。
これを防ぐため、必ず専用の一般ユーザーを作成して切り替える設定を追加します。
# ユーザーの作成と切り替えの例
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
CMD ["./myapp"]
3. セキュアなベースイメージの選定
ubuntu などの汎用的なOSイメージから開始するのではなく、不要なユーティリティ(curl, bash, package managerなど)が一切含まれていないベースイメージを使用します。
- Alpine Linux (
-alpine): 非常に軽量(約5MB)でパッケージ数が少なく、脆弱性リスクが非常に低い。 - Distrolessイメージ: Googleが提供する、アプリの実行ファイルと最小限の依存関係(Cライブラリなど)しか含まない、シェルすら入っていない究極にセキュアなイメージ。
4. 脆弱性スキャンツールの導入 (Trivyの活用)
作成したDockerイメージに脆弱性が含まれていないか、CI/CDパイプライン(GitHub Actionsなど)のビルドフェーズで自動スキャンを行うように設計します。
デファクトスタンダードとなっている Trivy などを使い、ビルド後のイメージをスキャンします。
# Trivyによるイメージスキャンの実行例
trivy image myapp:latest
これにより、ビルド時に自動で古いライブラリの脆弱性(CVE)を検知し、安全でないイメージの本番リリースを防ぐことができます。
5. まとめ
セキュアなコンテナ構築の鉄則は 「最小限であること」 です。不要なツールを持ち込まず、実行権限を最小限に絞り込むことで、本番環境の安全性を飛躍的に高めることができます。
