「Dockerfile → Docker Compose → Kubernetes」を、単独イメージを作る → ローカルで組み合わせてデバッグする → 外部で継続運用する流れと理解するのは、とてもよい入口です。
ただし、3つが順番に変換されるわけではありません。Docker ComposeをKubernetesへそのまま変換するのではなく、Dockerfileで作った同じイメージを、ComposeとKubernetesがそれぞれ別の実行定義で利用します。

3つの役割
| 要素 | 主な役割 | 成果物 |
|---|---|---|
| Dockerfile | 1つのコンテナイメージを再現可能に作る | イメージ |
| Docker Compose | 複数コンテナを主にローカルでまとめて起動する | compose.yaml |
| Kubernetes | クラスタ上で配置、再起動、更新、公開を継続管理する | マニフェスト |
このシリーズでは、イメージの保管先にGitLab Container Registryを使い、すべて手作業でbuild、push、deployします。CI/CDは前提にしません。
1. Dockerfileでイメージを作る
次は、静的ファイルをNginxで配信する最小例です。
FROM nginx:alpine
COPY ./public /usr/share/nginx/html
EXPOSE 80
docker build -t example-app:local .
docker run --rm -p 8080:80 example-app:local
DockerfileにはOSパッケージ、アプリケーション、起動コマンドなど、コンテナ内に必要なものを書きます。DBパスワードやアクセストークンのような環境ごとの秘密値は焼き込みません。
2. Docker Composeでローカル結合を確認する
アプリケーションとDBなど、複数サービスの接続確認にはComposeが便利です。
services:
app:
build: .
ports:
- "8080:80"
environment:
DATABASE_HOST: db
depends_on:
- db
db:
image: postgres:alpine
environment:
POSTGRES_DB: example
POSTGRES_USER: example
POSTGRES_PASSWORD: LOCAL_DEVELOPMENT_ONLY
docker compose up --build
docker compose ps
docker compose logs -f app
docker compose down
depends_on は起動順を補助しますが、DBが問い合わせを受け付けられる状態まで保証するものではありません。アプリ側の再試行やhealthcheckも設計します。また、この例の値はローカル学習専用です。本物のパスワードをComposeファイルへコミットしません。
3. 同じイメージをレジストリへ置く
外部クラスタは開発PC内の example-app:local を取得できません。イメージにレジストリ名と固定タグを付け、手動でpushします。
docker tag example-app:local \
registry.gitlab.com/GROUP/PROJECT/IMAGE:TAG
docker push registry.gitlab.com/GROUP/PROJECT/IMAGE:TAG
GitLabへの安全なログインと、GKEからのpull設定は第12回で扱います。latest のように実体が変わるタグより、リリース番号やコミット識別子など、どのイメージか追跡できるタグを使います。
4. Kubernetesで外部運用を宣言する
KubernetesではComposeの services をコピーするのではなく、目的ごとにオブジェクトを分けます。
apiVersion: apps/v1
kind: Deployment
metadata:
name: example-app
spec:
replicas: 2
selector:
matchLabels:
app: example-app
template:
metadata:
labels:
app: example-app
spec:
containers:
- name: app
image: registry.gitlab.com/GROUP/PROJECT/IMAGE:TAG
ports:
- containerPort: 80
---
apiVersion: v1
kind: Service
metadata:
name: example-app
spec:
selector:
app: example-app
ports:
- port: 80
targetPort: 80
- Deploymentがコンテナの個数と更新を管理する
- Serviceが作り直されるPodへ安定した宛先を与える
- ConfigMapやSecretが環境差分を渡す
- PersistentVolumeClaimが必要な永続データを扱う
Composeの1ファイルに近い情報を、Kubernetesでは責務別のAPIオブジェクトとして宣言します。
本番DBをPodに同居させるべきか
ローカルではComposeでDBを立てると便利ですが、GKE本番で同じ構成を無条件に再現する必要はありません。バックアップ、フェイルオーバー、ストレージ運用が必要なDBは、Cloud SQLなどのマネージドサービスを選ぶ方が運用しやすい場合があります。
「ComposeにあるからKubernetesにも全部載せる」ではなく、外部運用で誰が可用性を担うかをサービスごとに決めます。
よくある誤解
- Dockerfileだけで複数サービスの運用構成まで定義できるわけではない
- Docker ComposeはKubernetesの必須前工程ではない
- KubernetesがDockerfileやイメージを置き換えるわけではない
- コンテナ化しただけでデータが永続化されるわけではない
- イメージ内へ秘密値を入れてはいけない
次回
外部運用を支えるクラスタ内部を、Control plane・data plane・etcdに分けて見ていきます。