Go言語

Go アプリを最小サイズの Docker コンテナへ - 基礎とベストプラクティス

ⓘ本ページはプロモーションが含まれています

スポンサードリンク

1️⃣ Docker の基本概念と Go バイナリの相性

1-1 コンテナは「レイヤー」+「差分書き込み層」

Docker イメージは 読み取り専用レイヤー(ベース OS、ライブラリ、アプリ本体) と 書き込み可能な差分層 で構成されます。
コンテナ起動時に差分層だけが作られるため、同一イメージはどのホストでもほぼ同じ挙動を示します。
レイヤーは再利用できるので、ビルドキャッシュやプル時間が大幅に短縮されます。

1-2 Go バイナリは Docker 化に最適

  • go build -ldflags="-s -w"静的リンク かつシンボルテーブル削除したバイナリは、サイズが 10 ~ 15 MB 程度に収まります。
  • 静的バイナリはランタイムや共有ライブラリを必要としないため、最小のベースイメージ(Alpine など)だけで動作させられます。

※ 注意
記載しているサイズは執筆時点の概算です。公式イメージは随時更新されるので、実際に使用する前に docker pull 後の docker images で最新サイズを確認してください。


2️⃣ 公式 golang イメージとベース OS の選び方

イメージ 主な特徴 想定用途 参考サイズ*
golang:1.22-alpine Alpine + musl libc、パッケージは apk ビルドステージ(静的リンクが可能) 150 MB
golang:1.22-bullseye (Debian) glibc、パッケージは apt Cgo が必要なライブラリや外部バイナリを使う場合 350 MB
alpine:latest 5 ~ 6 MB 程度の最小実行環境 ランタイムステージ(static バイナリだけ) 6 MB

*サイズは執筆時点の公式レポジトリ情報です。バージョンやタグが変わると増減します。

2-1 「常に最新版」表現を修正

Docker Hub のタグは “latest” が指すイメージは頻繁に更新されます が、必ずしも同一の内容になる保証はありません。CI パイプラインで使用する場合は 固定バージョン(例: golang:1.22-alpine を指定し、必要に応じて手動で更新を検討してください。


3️⃣ マルチステージビルドで超軽量コンテナを作る

3-1 全体構成とポイント

ステージ 主な役割 重要な Dockerfile 命令
builder ソースコード取得、依存解決、静的バイナリ生成 COPY go.mod go.sum, RUN go mod download, RUN go build
runtime 実行環境だけを残す(Alpine + バイナリ) FROM alpine:latest, COPY --from=builder, USER 設定, HEALTHCHECK

3-2 完成形 Dockerfile (コメント付き)

補足ポイント

  • CGO_ENABLED=0 により glibc 依存が除去され、Alpine の musl でも動作します。
  • RUN addgroup ... && adduser ... は単一レイヤーにまとめて層数を削減しています。
  • HEALTHCHECK は本番環境の自動復旧やオートスケールで有効です。

3-3 キャッシュ活用のコツ(go.mod の順序)

この書き方で、ソースコードの変更があっても 依存取得層 はキャッシュされ続けます。


4️⃣ 本番環境向けベストプラクティス

4-1 非 root 実行と権限設計

  • USER 命令で作成した低権限ユーザーを必ず使用し、Kubernetes の runAsNonRoot ポリシーに適合させます。
  • 必要最小限のファイル・ディレクトリだけに書き込み権限を付与すると、コンテナ侵害時の被害範囲が限定されます。

4-2 .dockerignore の正しい記述例

  • Dockerfile を除外するとビルドコンテキストにイメージが送られず、ビルド自体が失敗します。必ずリストから外してください。

4-3 サイズ測定と継続的最適化

項目 確認コマンド例 推奨上限(参考)
イメージ総サイズ docker images --format "{{.Repository}}:{{.Tag}} {{.Size}}" 20 MB 以下(Alpine + 静的バイナリ)
レイヤー数 docker history <image> 5 層以内に抑えるとキャッシュ効率が向上
不要ファイルの除外 .dockerignore の網羅性をチェック ビルドコンテキストは < 10 MB が理想

Tip:CI パイプラインで docker image ls --format "{{.Repository}}:{{.Tag}} {{.Size}}" を走らせ、サイズが閾値を超えたら自動で警告する仕組みを入れると肥大化防止に役立ちます。

4-4 セキュリティスキャンの実装例

  • 定期的にスキャンし、CVE が報告されたベースイメージは パッチが当たった最新タグ に更新します。

5️⃣ 開発・デプロイフローの自動化

5-1 Docker Compose とローカル開発環境

  • volumes によりローカル変更が即座にコンテナへ反映され、air などのホットリロードツールと併用すれば開発速度が向上します。

5-2 VSCode DevContainer の設定

  • VSCode 起動時に自動でコンテナが立ち上がり、エディタ拡張やデバッグ設定が共有されます。
  • postCreateCommand で依存解決とビルドを走らせることで、チーム全員が同一の環境で作業できます。

5-3 GitHub Actions による CI/CD パイプライン

  • テスト → ビルド → プッシュ のシンプルなフローで、プルリクエストがマージされた瞬間に最新イメージがレジストリへデプロイされます。
  • cache-from / cache-to によりビルド時間を数分単位で短縮できます。

6️⃣ まとめと次のステップ

項目 キーポイント
Docker の基礎 レイヤー構造が再利用と高速起動を実現。Go の静的バイナリは最小イメージ化に最適。
ベースイメージ選択 golang:1.22-alpine(ビルド)+alpine:3.19(ランタイム)がサイズと速度のバランスが良い。glibc が必要なケースは Debian 系へ切り替える。
マルチステージビルド Builder と Runtime を分離し、go.mod の先行コピーでキャッシュを最大活用。最終イメージは約 12 ~ 15 MB に抑えられる(Alpine + static binary)。
本番ベストプラクティス 非 root ユーザー、正しい .dockerignore、HEALTHCHECK、定期的な脆弱性スキャンで安全性と可観測性を確保。
開発・CI/CD 自動化 Docker Compose + VSCode DevContainer でローカル環境統一、GitHub Actions がテスト・ビルド・デプロイの全工程を自動化。
運用上の留意点 イメージサイズやタグは随時変わるため、docker pull 後に docker images で実測値を確認し、バージョン固定と定期更新のポリシーを策定する。

これらの手順・設定をプロジェクトに組み込めば、「最小サイズかつ本番品質」 の Go アプリ Docker コンテナがすぐに構築でき、開発からデプロイまで一貫したフローを実現できます。


次のアクション例
1. 本リポジトリに上記 Dockerfile.dockerignore を追加し、git add . && git commit -m "Add production‑ready Docker setup"
2. CI 用シークレット(Docker Hub 認証情報)を GitHub リポジトリの Settings → Secrets に設定。
3. docker compose up --build でローカル環境を起動し、curl http://localhost:8080/health200 を返すことを確認。

これで本番に耐えうる軽量コンテナが完成です!

スポンサードリンク

-Go言語