mcpField
G
go-containers

go-containers

github.com/laurigatesクラウド・DevOps5962 回インストール1 日前に更新
リポジトリ

go-containers について

go-containersは、Go開発者向けのコンテナ最適化スキルです。静的コンパイル、軽量なベースイメージ、Goのビルドフラグを扱い、Dockerfileの作成や監査に役立ちます。

主な機能

  1. 01Goバイナリの静的ビルド設定
  2. 02scratch、distroless、Alpineの選択
  3. 03リンカーフラグによるバイナリ縮小
  4. 04CA証明書とCGO依存関係の処理
  5. 05マルチステージビルドによる環境分離

活用シーン

  1. 01Goサービスの本番イメージ縮小
  2. 02GoアプリケーションのDockerfile監査
  3. 03Cライブラリ利用時のイメージ選定
  4. 04バイナリサイズと動的依存関係の確認

インストール

コマンドをコピーしてターミナルで実行します。

$npx skills add https://github.com/laurigates/claude-plugins --skill go-containers

インストール後、Claude Code で/go-containersを入力して読み込まれたか確認します。

詳細

Go コンテナーの最適化

静的コンパイル、scratch/distroless ベースイメージ、Go 固有のビルド最適化を活用して、最小かつ安全な Go コンテナーイメージを構築するための専門知識です。

このスキルを使用する場面

次の場合はこのスキルを使用します…次の場合は container-development を使用します…
Go アプリケーションの Dockerfile を作成または監査する場合言語に依存しないマルチステージビルドのパターンを記述する場合
Go バイナリに scratch、distroless、Alpine のどれを使うか選ぶ場合非 root/最小権限の基準に従って、あらゆるコンテナーを強化する場合
数百 MB の Go イメージを一桁 MB まで小さくする場合Docker Compose でサービスを構成する場合
Go 固有の CGO/静的リンクの問題を解決する場合Node.js(nodejs-containers)または Python(python-containers)のイメージを最適化する場合

主な専門知識

Go 固有の利点:

  • 単一の静的バイナリにコンパイルされます(ランタイム依存関係なし)
  • scratch ベースで実行できます(文字どおり空のイメージです)
  • 実行時にインタープリター、VM、システムライブラリは不要です
  • 可能な限り小さなコンテナーイメージを実現できます(2~5MB)

主な機能:

  • CGO_ENABLED=0 による静的バイナリのコンパイル
  • ldflags(-w、-s)によるバイナリのストリップ
  • scratch および distroless ベースイメージ
  • HTTPS 用 CA 証明書の処理
  • C ライブラリが必要な場合の CGO の考慮事項

最適化の過程:846MB → 2.5MB

これは、体系的な最適化によってサイズを 99.7% 削減する方法を示しています。

ステップ 1:問題 — Debian のフルベース(846MB)
# ❌ BAD: Includes full Go toolchain, Debian system, unnecessary tools
FROM golang:1.23
WORKDIR /app
COPY . .
RUN go build -o main .
EXPOSE 8080
CMD ["./main"]

問題点:

  • Debian のフルベース(約116MB)
  • Go コンパイラーとツールチェーン一式(約730MB)
  • システムライブラリ、パッケージマネージャー、シェル
  • これらは実行時には必要ありません

イメージサイズ:846MB

ステップ 2:Alpine に切り替え(312MB)
# ✅ BETTER: Alpine reduces OS overhead
FROM golang:1.23-alpine
WORKDIR /app
COPY . .
RUN go build -o main .
EXPOSE 8080
CMD ["./main"]

改善点:

  • Alpine Linux(ベースは約5MB、Debian は約116MB)
  • それでも Go ツールチェーン一式が含まれています(実行時には不要です)

イメージサイズ:312MB(63% 削減)

ステップ 3:マルチステージビルド(15MB)
# ✅ GOOD: Separate build from runtime
# Build stage
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN go build -o main .

# Runtime stage
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]

改善点:

  • ビルド成果物を最終イメージから除外
  • 最終イメージには Alpine とバイナリのみ
  • デプロイとプルが高速化

イメージサイズ:15MB(312MB から95%削減)

ステップ 4:バイナリのストリップとビルドフラグの最適化(8MB)
# ✅ BETTER: Optimized build flags
# Build stage
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .

# Optimized build with stripping
RUN CGO_ENABLED=0 GOOS=linux go build \
    -a \
    -installsuffix cgo \
    -ldflags="-w -s" \
    -trimpath \
    -o main .

# Runtime stage with CA certificates
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /app
COPY --from=builder /app/main .
EXPOSE 8080
CMD ["./main"]

ビルドフラグの説明:

フラグ目的効果
CGO_ENABLED=0CGO を無効にし、静的バイナリを作成動的ライブラリへの依存を削除
-aすべてのパッケージを強制的に再ビルドクリーンなビルドを保証
-installsuffix cgo出力ディレクトリを分離キャッシュの競合を防止
-ldflags="-w -s"デバッグ情報とシンボルテーブルをストリップバイナリサイズを大幅に削減
-wDWARF デバッグ情報を省略サイズを約30%削減
-sシンボルテーブルとデバッグ情報を省略さらに約10%削減
-trimpathファイルシステムのパスを削除セキュリティ:ローカルパスの漏えいを防止

追加項目:

  • HTTPS リクエスト用の CA 証明書
  • 完全な静的バイナリ(動的依存関係なし)

イメージサイズ:8MB(15MB から47%削減)

ステップ 5:Scratch または Distroless(2.5MB)

オプション A:Scratch(最小構成)

# Build stage
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .

# Optimized static build
RUN CGO_ENABLED=0 GOOS=linux go build \
    -a \
    -installsuffix cgo \
    -ldflags="-w -s" \
    -trimpath \
    -o main .

# Runtime stage - scratch (empty image)
FROM scratch

# Copy CA certificates from builder
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/

# Copy binary
COPY --from=builder /app/main /main

EXPOSE 8080
CMD ["/main"]

イメージサイズ:2.5MB(8MB から68%削減)

オプション B:Distroless(やや大きいが、デバッグが容易)

# Build stage (same as above)
FROM golang:1.23-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build \
    -a \
    -ldflags="-w -s" \
    -trimpath \
    -o main .

# Runtime stage - distroless
FROM gcr.io/distroless/static-debian12

COPY --from=builder /app/main /main
EXPOSE 8080
CMD ["/main"]

Distroless の利点:

  • CA 証明書が自動的に含まれます
  • 最小限の OS ファイル(passwd、nsswitch.conf)
  • シェルなし(セキュリティ上の利点)
  • やや大きくなります(約2~3MB増)が、便利なメタデータが含まれます

イメージサイズ:約4~5MB

パフォーマンスへの影響

指標Debian(846MB)Alpine(15MB)Scratch(2.5MB)改善
イメージサイズ846MB15MB2.5MB99.7%削減
プル時間52s4s1s98%高速化
ビルド時間3m 20s2m 15s1m 45s47%高速化
起動時間2.1s1.2s0.8s62%高速化
メモリ使用量480MB180MB128MB73%削減
ストレージコスト$0.48/mo$0.01/mo$0.001/mo99.8%削減

セキュリティへの影響

イメージタイプ脆弱性攻撃対象領域
Debianベース63 CVEOS全体、シェル、パッケージマネージャー、ユーティリティ
Alpineベース12 CVE最小限のOS、シェル、パッケージマネージャー
Scratch0 CVEバイナリのみ、OSなし
Distroless0~2 CVEバイナリ+最小限のランタイム、シェルなし

scratch/distrolessのセキュリティ上の利点:

  • シェルなし → シェルインジェクション攻撃なし
  • パッケージマネージャーなし → サプライチェーン攻撃なし
  • OSユーティリティなし → 攻撃対象領域を最小限に抑制
  • 不要なライブラリなし → 脆弱性を削減

各アプローチを使用する場面

用途推奨ベース理由
本番サービスScratchまたはDistroless最小サイズ、最大限のセキュリティ
C依存関係のあるサービスAlpine(CGOを使用)システムライブラリが必要
開発/デバッグAlpineトラブルシューティングにシェルアクセスが必要
レガシーアプリDebian slim互換性要件

Go向け .dockerignore

# Version control
.git
.gitignore
.gitattributes

# Go artifacts
vendor/
*.exe
*.exe~
*.dll
*.so
*.dylib
*.test
*.out
go.work
go.work.sum

# Development files
.vscode/
.idea/
*.swp
*.swo
*~
.DS_Store

# Documentation
README.md
*.md
docs/
LICENSE

# CI/CD
.github/
.gitlab-ci.yml
.travis.yml
Jenkinsfile

# Environment files
.env
.env.*
*.env

# Build artifacts
dist/
build/
bin/
tmp/
temp/

# Logs
*.log
logs/

# Test files (if not needed in image)
*_test.go
testdata/

# Docker files
Dockerfile*
docker-compose*.yml
.dockerignore

バイナリサイズの分析

# Build with different optimization levels
go build -o main-default .
go build -ldflags="-w" -o main-w .
go build -ldflags="-s" -o main-s .
go build -ldflags="-w -s" -o main-ws .

# Compare sizes
ls -lh main-*

# Typical results for a medium Go app:
# main-default: 12.5MB (with debug info + symbols)
# main-w:        8.7MB (no debug info)
# main-s:       10.2MB (no symbol table)
# main-ws:       7.8MB (both stripped)

# Further analyze binary
go tool nm main-default | wc -l  # Count symbols
file main-ws                      # Verify static linking
ldd main-ws                       # Should show "not a dynamic executable"

上級者向け:CGOに関する考慮事項

GoアプリケーションでCGO(Cライブラリ、SQLiteなどのデータベースドライバーなど)を使用する場合、ベースイメージに scratch は使用できません。

# When CGO is required (database drivers, C libraries)
FROM golang:1.23-alpine AS builder

# Install C dependencies
RUN apk add --no-cache gcc musl-dev

WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .

# Build with CGO enabled
RUN CGO_ENABLED=1 GOOS=linux go build \
    -ldflags="-w -s -linkmode external -extldflags '-static'" \
    -o main .

# Runtime needs musl
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /app/main .
CMD ["./main"]

注:CGOを使用する場合、Alpineが最小の選択肢です(最終イメージは約7~10MB)。

一般的なGoデータベースドライバー

ドライバーCGOが必要最小ベース
github.com/lib/pq(PostgreSQL)いいえScratch
github.com/go-sql-driver/mysqlいいえScratch
github.com/mattn/go-sqlite3はいAlpine
modernc.org/sqlite(純Go)いいえScratch

エージェント型開発の最適化

開発を高速化するGo専用のコンテナーコマンド:

コンテキストコマンド目的
クイックビルドgo build -ldflags="-w -s" -o app .シンボルを除去したバイナリをビルド
サイズの確認ls -lh appバイナリサイズを確認
静的リンクの確認ldd app動的依存関係がないことを確認
コンテナービルドDOCKER_BUILDKIT=1 docker build -t app .キャッシュを使った高速ビルド
サイズの確認docker images app --format "{{.Size}}"最終イメージのサイズを確認
レイヤー分析docker history app:latest --humanレイヤーサイズを確認

ベストプラクティス

必ず行うこと:

  • Cライブラリが必要な場合を除き、CGO_ENABLED=0 を使用する
  • -ldflags="-w -s" でバイナリからシンボルを除去する
  • -trimpath を使用してファイルシステムのパスを削除する
  • 本番環境では scratch または distroless を優先する
  • Goとベースイメージのバージョンを固定する(latest は使用しない)

決して行わないこと:

  • 本番イメージにGoコンパイラーを含める
  • GoアプリでDebian/Ubuntuのフルベースイメージを使用する
  • 本番用バイナリにデバッグシンボルを含める
  • rootユーザーで実行する(scratch でも USER 65534 を使用する)

関連スキル

  • container-development - 一般的なコンテナーパターン、マルチステージビルド、セキュリティ
  • nodejs-containers - Node.js固有のコンテナー最適化
  • python-containers - Python固有のコンテナー最適化

コメント