「手動でDockerfileを書くたびに、ベストプラクティスを守れているか不安になる」「マルチステージビルドの最適化がよくわからない」——Dockerコンテナ化には意外と多くのノウハウが求められます。
Google Gemini CLI(旧Project Antigravity)は、アプリケーションのソースコードを分析して最適なDockerfile・docker-compose.yaml・.dockerignoreを自動生成できるAIコーディングツールです。本記事では、Gemini CLIを使ったDockerコンテナ化の実践テクニックを解説します。
この記事を3秒でまとめると
- Gemini CLIがプロジェクト構造を分析し、最適なDockerfileを自動生成する
- マルチステージビルドでイメージサイズを最大90%削減できる
- docker-compose.yamlの生成からセキュリティ対策まで一気通貫で対応
Dockerコンテナ化でよくある課題
ベースイメージの選定ミス
node:latestやpython:latestのような非固定タグを使ったり、不必要に大きなイメージを使ったりする問題は頻繁に見られます。
# ❌ よくある問題のあるDockerfile
FROM node:latest
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["node", "server.js"]
このDockerfileには以下の問題があります:
latestタグで再現性がない- フルイメージで約1GB(不要なツールが多数含まれる)
- ビルドキャッシュが効かない(
COPY . .が先) - rootユーザーで実行されるセキュリティリスク
.dockerignoreが考慮されていない
マルチステージビルドの未活用
ビルドツールやdevDependenciesが本番イメージに含まれてしまい、イメージサイズが肥大化する問題です。
Gemini CLIで最適なDockerfileを自動生成
プロジェクト分析からDockerfile生成
Gemini CLIにプロジェクトのDockerコンテナ化を指示するだけで、ベストプラクティスに沿ったDockerfileが生成されます。
gemini "このNode.jsプロジェクトを本番向けにDockerコンテナ化して。
以下の要件を満たすこと:
- マルチステージビルド
- 非rootユーザー
- ヘルスチェック
- .dockerignoreも生成"
Gemini CLIが生成する最適化されたDockerfile:
# ============================================
# Stage 1: 依存関係のインストール
# ============================================
FROM node:22-alpine AS deps
WORKDIR /app
# パッケージファイルのみ先にコピー(キャッシュ効率化)
COPY package.json package-lock.json ./
RUN npm ci --only=production && \
cp -r node_modules /prod_modules && \
npm ci
# ============================================
# Stage 2: ビルド
# ============================================
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
RUN npm run build
# ============================================
# Stage 3: 本番イメージ
# ============================================
FROM node:22-alpine AS runner
WORKDIR /app
# セキュリティ: 非rootユーザーを作成
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 appuser
# 本番依存のみコピー
COPY --from=deps /prod_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package.json ./
# 非rootユーザーに切り替え
USER appuser
# ヘルスチェック
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1
EXPOSE 3000
CMD ["node", "dist/server.js"]
同時に.dockerignoreも生成されます:
node_modules
.git
.github
.env*
*.md
!README.md
dist
coverage
.nyc_output
.vscode
.idea
Dockerfile
docker-compose*.yaml

言語別のDockerfile生成テクニック
Python(FastAPI)のコンテナ化
gemini "このFastAPIプロジェクトのDockerfileを生成して。
uvicornでマルチワーカー起動、依存はpoetry管理"
FROM python:3.12-slim AS builder
WORKDIR /app
RUN pip install poetry==1.8.3 && \
poetry config virtualenvs.create false
COPY pyproject.toml poetry.lock ./
RUN poetry install --no-dev --no-interaction --no-ansi
COPY . .
FROM python:3.12-slim AS runner
WORKDIR /app
RUN groupadd -r appgroup && useradd -r -g appgroup appuser
COPY --from=builder /usr/local/lib/python3.12/site-packages /usr/local/lib/python3.12/site-packages
COPY --from=builder /usr/local/bin/uvicorn /usr/local/bin/uvicorn
COPY --from=builder /app .
USER appuser
HEALTHCHECK --interval=30s --timeout=10s \
CMD python -c "import urllib.request; urllib.request.urlopen('http://localhost:8000/health')" || exit 1
EXPOSE 8000
CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8000", "--workers", "4"]
Go(バイナリ)のコンテナ化
Goはスタティックバイナリを生成できるため、最小限のイメージ(distroless/scratch)が使えます。
gemini "このGoプロジェクトをDockerコンテナ化して。
scratchベースで最小イメージにして"
FROM golang:1.22-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \
go build -ldflags="-w -s" -o /app/server ./cmd/server
FROM scratch
COPY --from=builder /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/
COPY --from=builder /app/server /server
EXPOSE 8080
ENTRYPOINT ["/server"]
TypeScript(Next.js)のコンテナ化
gemini "Next.js 15プロジェクトのDockerfileを生成して。
standalone出力モードを使って最小化して"
FROM node:22-alpine AS deps
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
FROM node:22-alpine AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
ENV NEXT_TELEMETRY_DISABLED=1
RUN npm run build
FROM node:22-alpine AS runner
WORKDIR /app
ENV NODE_ENV=production
ENV NEXT_TELEMETRY_DISABLED=1
RUN addgroup --system --gid 1001 nodejs && \
adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT=3000
CMD ["node", "server.js"]
docker-compose.yamlの自動生成
開発環境構成
gemini "以下のマイクロサービス構成のdocker-compose.yamlを生成して:
- frontend: Next.js (port 3000)
- api: FastAPI (port 8000)
- worker: Go (バッチ処理)
- db: PostgreSQL 16
- redis: Redis 7 (キャッシュ・キュー)
- 開発用ホットリロード対応"
version: "3.9"
services:
frontend:
build:
context: ./frontend
target: deps
volumes:
- ./frontend:/app
- /app/node_modules
ports:
- "3000:3000"
environment:
- NEXT_PUBLIC_API_URL=http://localhost:8000
command: npm run dev
depends_on:
- api
api:
build:
context: ./backend
target: builder
volumes:
- ./backend:/app
ports:
- "8000:8000"
environment:
- DATABASE_URL=postgresql://app:secret@db:5432/appdb
- REDIS_URL=redis://redis:6379
command: uvicorn app.main:app --host 0.0.0.0 --reload
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
worker:
build:
context: ./tools
volumes:
- ./tools:/app
environment:
- DATABASE_URL=postgresql://app:secret@db:5432/appdb
- REDIS_URL=redis://redis:6379
depends_on:
db:
condition: service_healthy
redis:
condition: service_started
db:
image: postgres:16-alpine
volumes:
- postgres_data:/var/lib/postgresql/data
- ./db/init.sql:/docker-entrypoint-initdb.d/init.sql
environment:
POSTGRES_USER: app
POSTGRES_PASSWORD: secret
POSTGRES_DB: appdb
ports:
- "5432:5432"
healthcheck:
test: ["CMD-SHELL", "pg_isready -U app -d appdb"]
interval: 10s
timeout: 5s
retries: 5
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
- redis_data:/data
volumes:
postgres_data:
redis_data:
Dockerセキュリティ対策
脆弱性スキャンの自動化
gemini "Docker imageのセキュリティチェックを行うCIワークフローを生成して:
- Trivy/Grypeによる脆弱性スキャン
- Hadolintによるベストプラクティスチェック
- Dockleによるセキュリティ監査"
セキュリティベストプラクティスの自動適用
Gemini CLIは以下のセキュリティ対策を自動的に組み込みます:
| 対策 | 内容 |
|---|---|
| 非rootユーザー | 専用ユーザーを作成して実行 |
| バージョン固定 | タグではなくSHA256ダイジェストでイメージ指定 |
| シークレット管理 | Docker BuildKitのsecretマウントを使用 |
| レイヤー最小化 | マルチステージビルドで不要ファイルを除外 |
| ヘルスチェック | コンテナの正常性を監視 |
詳しくはGemini CLIセキュリティガイドも参照してください。
イメージサイズの最適化比較
Gemini CLIで最適化した場合のイメージサイズ比較:
| アプリケーション | 最適化前 | 最適化後 | 削減率 |
|---|---|---|---|
| Node.js API | 1.2 GB | 180 MB | 85% |
| Python FastAPI | 950 MB | 150 MB | 84% |
| Go バイナリ | 850 MB | 12 MB | 99% |
| Next.js フロント | 1.5 GB | 200 MB | 87% |
CI/CDでのDockerビルド最適化
GitHub Actionsとの連携
gemini "GitHub Actionsでマルチプラットフォーム(amd64/arm64)の
Dockerイメージをビルドしてプッシュするワークフローを生成して。
レイヤーキャッシュも活用して"
name: Docker Build & Push
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: docker/setup-qemu-action@v3
- uses: docker/setup-buildx-action@v3
- uses: docker/login-action@v3
with:
registry: ghcr.io
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- uses: docker/build-push-action@v5
with:
context: .
platforms: linux/amd64,linux/arm64
push: true
tags: ghcr.io/${{ github.repository }}:latest
cache-from: type=gha
cache-to: type=gha,mode=max
CI/CDの詳細はGemini CLI CI/CD自動化ガイドも参照してください。
SES案件でのDockerスキルの重要性
コンテナ技術はSES案件のほぼすべての分野で求められるスキルとなっています。
- 開発環境構築: docker-composeによるローカル環境の統一
- CI/CDパイプライン: コンテナベースのビルド・テスト・デプロイ
- マイクロサービス: Kubernetes上でのコンテナオーケストレーション
- クラウド移行: オンプレからECS/GKE/AKSへの移行
Gemini CLIを使えば、これらのDockerスキルをより正確に、より早く身につけることができます。
まとめ — Gemini CLIでDockerの「正しい書き方」を実践
Dockerのベストプラクティスは年々更新され、把握し続けるのは大変です。Gemini CLIを活用することで、常に最新のベストプラクティスに沿ったDockerfileが生成できます。
- 自動分析: プロジェクト構造に応じた最適なDockerfile生成
- マルチステージ: ビルドと本番を分離してイメージサイズ最小化
- セキュリティ: 非rootユーザー・脆弱性スキャン・シークレット管理
- CI/CD統合: GitHub Actionsとの連携ワークフロー
SES案件で「Docker経験あり」と自信を持って言えるスキルを、Gemini CLIと一緒に身につけましょう。
SES BASEでは、Docker・Kubernetes関連のSES案件を多数掲載しています。
関連記事: