go-containers について
go-containersは、Go開発者向けのコンテナ最適化スキルです。静的コンパイル、軽量なベースイメージ、Goのビルドフラグを扱い、Dockerfileの作成や監査に役立ちます。
主な機能
- 01Goバイナリの静的ビルド設定
- 02scratch、distroless、Alpineの選択
- 03リンカーフラグによるバイナリ縮小
- 04CA証明書とCGO依存関係の処理
- 05マルチステージビルドによる環境分離
活用シーン
- 01Goサービスの本番イメージ縮小
- 02GoアプリケーションのDockerfile監査
- 03Cライブラリ利用時のイメージ選定
- 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=0 | CGO を無効にし、静的バイナリを作成 | 動的ライブラリへの依存を削除 |
-a | すべてのパッケージを強制的に再ビルド | クリーンなビルドを保証 |
-installsuffix cgo | 出力ディレクトリを分離 | キャッシュの競合を防止 |
-ldflags="-w -s" | デバッグ情報とシンボルテーブルをストリップ | バイナリサイズを大幅に削減 |
-w | DWARF デバッグ情報を省略 | サイズを約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) | 改善 |
|---|---|---|---|---|
| イメージサイズ | 846MB | 15MB | 2.5MB | 99.7%削減 |
| プル時間 | 52s | 4s | 1s | 98%高速化 |
| ビルド時間 | 3m 20s | 2m 15s | 1m 45s | 47%高速化 |
| 起動時間 | 2.1s | 1.2s | 0.8s | 62%高速化 |
| メモリ使用量 | 480MB | 180MB | 128MB | 73%削減 |
| ストレージコスト | $0.48/mo | $0.01/mo | $0.001/mo | 99.8%削減 |
セキュリティへの影響
| イメージタイプ | 脆弱性 | 攻撃対象領域 |
|---|---|---|
| Debianベース | 63 CVE | OS全体、シェル、パッケージマネージャー、ユーティリティ |
| Alpineベース | 12 CVE | 最小限のOS、シェル、パッケージマネージャー |
| Scratch | 0 CVE | バイナリのみ、OSなし |
| Distroless | 0~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固有のコンテナー最適化
コメント
Markdown 対応