開発環境の準備
本セクションでは、Docker と Go の動作要件を確認し、インストールから動作確認までの流れを示します。開発マシンが正しくセットアップされていることは、後続のビルドやデプロイで生じる環境依存エラーを防ぐ鍵となります。
Docker Desktop のインストール
Docker Desktop は Windows、macOS、および一部 Linux ディストリビューション向けに公式サポートが提供されています。最新のサポート対象は次の通りです。
| OS | バージョン | 備考 |
|---|---|---|
| Windows 10/11 (Home, Pro, Enterprise) | WSL 2 有効化必須 | Windows Store 版または公式サイトからインストーラを取得 |
| macOS | Ventura(13)以降 | Apple Silicon(M1/M2)および Intel 両方に対応 |
| Ubuntu | 22.04 LTS、23.10 以降 | apt パッケージで Docker Engine を利用する場合は Desktop は不要 |
| Debian / Fedora / RHEL | 最新の LTS リリース | Docker Engine (docker.io) のみ公式サポート。Desktop が必要な場合は Community Edition を参照 |
インストール手順(共通)
1. 公式ダウンロードページ https://www.docker.com/products/docker-desktop/ にアクセスし、OS 別の「Download for …」ボタンをクリック。
2. ダウンロードしたインストーラを実行し、画面指示に従ってインストール。
3. インストール完了後、ターミナル(PowerShell / iTerm2 等)でdocker versionを実行し、Client と Server のバージョンが表示されれば成功です。
Linux 環境で Desktop が不要な場合は、公式リポジトリから Docker Engine をインストールしてください。
|
1 2 3 4 5 6 7 8 9 10 11 |
# Ubuntu 22.04 の例 sudo apt-get update sudo apt-get install -y ca-certificates curl gnupg lsb-release curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg echo \ "deb [arch=$(dpkg --print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] \ https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | \ sudo tee /etc/apt/sources.list.d/docker.list > /dev/null sudo apt-get update sudo apt-get install -y docker-ce docker-ce-cli containerd.io |
前提条件の確認
以下のツールがインストール済みかどうかを、コマンドラインで簡単にチェックできます。全てが揃っていることを ローカルビルド と CI 環境 の両方で前提とします。
| ツール | 推奨バージョン | チェックコマンド |
|---|---|---|
| Go | 1.22.x 以上 | go version |
| Git | 任意の最新版 | git --version |
| VS Code (または好みのエディタ) | - | code --version(VS Code がインストールされている場合) |
| Docker CLI | Desktop/Engine に同梱 | docker version --format '{{.Server.Version}}' |
Tip: VS Code の「Docker」拡張機能と「Go」拡張機能を併用すると、イメージビルドやデバッグが GUI から直感的に実行できます。
プロジェクト構成とコード実装
この章では、典型的な Go プロジェクトのディレクトリレイアウトと、Docker ビルドに必要な設定ファイル(go.mod、.dockerignore、Dockerfile)を具体例とともに解説します。
ディレクトリ構成
以下は、シングルバイナリ アプリケーション向けの推奨レイアウトです。ソースコードは src/ に集約し、ビルド成果物やテストは同層に配置します。
|
1 2 3 4 5 6 7 8 |
my-go-app/ ├─ src/ │ ├─ main.go │ ├─ main_test.go │ └─ go.mod ├─ .dockerignore # ビルドコンテキスト除外設定 └─ Dockerfile # マルチステージビルド定義 |
Go モジュールの初期化
src/ ディレクトリへ移動し、モジュールを作成・依存解決します。CI 環境でも同様に実行できるよう、go.mod と go.sum を必ずコミットしてください。
|
1 2 3 4 |
cd src go mod init github.com/yourname/my-go-app # 自身のリポジトリ URL に置き換える go mod tidy # 依存パッケージを自動取得 |
Hello World アプリ(main.go)
最小構成で HTTP サーバを立ち上げるコード例です。実際のビジネスロジックはこのファイルに追加していきます。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
package main import ( "fmt" "net/http" ) func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintln(w, "Hello, Dockerized Go!") } func main() { http.HandleFunc("/", handler) if err := http.ListenAndServe(":8080", nil); err != nil { panic(err) } } |
.dockerignore のベストプラクティス
Docker ビルド時に不要なファイルがコンテキストに含まれると、イメージサイズが肥大化しビルド速度も低下します。Go プロジェクト専用の除外設定は次の通りです(node_modules は削除しました)。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
# バージョン管理系ファイル .git .gitignore # ログ・一時ファイル *.log tmp/ **/tmp/ # Go ビルドキャッシュとテスト成果物 /go/pkg/mod src/bin/ src/**/*.test # エディタ/IDE の設定 .vscode/ .idea/ |
効果: 上記パターンを除外することで、ビルドコンテキストが数十 MB から数 MB に縮小し、ネットワーク転送やレイヤー作成のコストが大幅に削減されます。
マルチステージ Dockerfile とイメージ最適化
本節では、ビルダー ステージで Go バイナリを生成し、ランタイム ステージで Alpine Linux(数 MB 程度)または scratch ベースの超小型イメージへ移行する手順を解説します。
Builder ステージの構成
まずは依存取得とバイナリビルドだけを行うステージです。キャッシュ活用により、ソースコードが変更されても go.mod が固定されていれば再ダウンロードは発生しません。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
# syntax=docker/dockerfile:1.4 # BuildKit 機能有効化宣言 FROM golang:1.22-alpine AS builder # ビルドに必要なツールだけをインストール(git はモジュール取得のため必須) RUN apk add --no-cache git WORKDIR /app/src COPY src/go.mod src/go.sum ./ RUN go mod download # 依存解決はキャッシュ対象 COPY src/ . # -ldflags="-s -w" はデバッグ情報とシンボルテーブルを除去し、バイナリサイズを約30%削減 RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ go build -ldflags="-s -w" -o /app/bin/app . |
重要ポイント解説
CGO_ENABLED=0:純粋なスタティックバイナリを生成し、Alpine のmuslと互換性を保ちます。GOARCH=amd64(またはarm64):マルチアーキテクチャ対応はdocker buildxで実現可能です。- キャッシュ層の順序:
go.modのコピーとgo mod downloadを最初に配置することで、コード変更時でも依存解決は再利用されます。
Runtime ステージ(Alpine)
ビルダーで生成したバイナリだけを持ち込み、軽量なランタイム環境を構築します。ベースサイズは 数 MB 程度 になる点に留意してください(実際の最終イメージは追加レイヤーや ca-certificates の有無で変動します)。
|
1 2 3 4 5 6 7 8 9 10 11 12 |
FROM alpine:3.19 AS runtime # 非 root ユーザー作成(セキュリティベストプラクティス) RUN addgroup -S app && adduser -S -G app app WORKDIR /app COPY --from=builder /app/bin/app ./app USER app EXPOSE 8080 CMD ["./app"] |
Alpine のサイズに関する注意
- ベースイメージは約5 MBですが、
ca-certificates(HTTPS 通信が必要な場合)やtzdataを追加すると総容量は 10–15 MB 程度になることがあります。 - 必要最小限のパッケージのみをインストールし、
--no-cacheオプションで一時的なキャッシュを残さないようにします。
Scratch ベースの超軽量イメージ(任意)
さらにサイズ削減が求められる場合は scratch を使用できます。scratch は空のベースイメージなので、バイナリだけが格納されます。
|
1 2 3 4 5 6 7 |
FROM scratch AS prod COPY --from=builder /app/bin/app /app USER 1000:1000 # 任意の非 root UID/GID EXPOSE 8080 ENTRYPOINT ["/app"] |
- サイズ比較:Alpine が数 MB、
scratchは 2 MB 未満(バイナリ自体のサイズのみ)。 - 制約:TLS 証明書やロケールが必要な場合は別途コピーする必要があります。
BuildKit とマルチプラットフォームビルド
Docker Desktop の設定画面で BuildKit を有効化するか、環境変数 DOCKER_BUILDKIT=1 をエクスポートしてください。マルチアーキテクチャ対応は docker buildx が提供します。
|
1 2 3 4 5 6 7 |
# BuildKit 有効化(一時的) export DOCKER_BUILDKI T=1 # マルチプラットフォームビルド例(amd64 と arm64 両方生成) docker buildx create --use # 初回だけ実行すれば OK docker buildx bake -f docker-bake.hcl |
docker-bake.hcl のサンプルは以下です。
|
1 2 3 4 5 6 7 |
target "default" { context = "." dockerfile = "Dockerfile" platforms = ["linux/amd64", "linux/arm64"] tags = ["yourrepo/my-go-app:latest"] } |
開発時のコンテナ活用とデバッグ
ローカル開発では、コード変更を即座に反映させる ホットリロード と、Go の公式デバッガ dlv を利用したコンテナ内デバッグが有効です。ここでは具体的な設定例と実行コマンドを示します。
ボリュームマウントによるホットリロード
ソースコードはローカルに保持しつつ、開発用イメージでリアルタイムにビルド・再起動させます。以下の docker run コマンドは 開発ステージ(builder の成果物)を利用します。
|
1 2 3 4 5 |
docker run --rm -it \ -v "$(pwd)/src:/app/src" \ -p 8080:8080 \ my-go-app:dev |
-vオプションでローカルのsrc/ディレクトリをコンテナ内/app/srcにマウント。- ポートはホストとコンテナ双方で同一(8080)に設定し、ブラウザから
http://localhost:8080へアクセスできます。
Air を用いた自動ビルド・再起動
Air は Go 向けのライブリローダです。開発イメージに組み込む手順は以下の通りです。
|
1 2 3 4 5 6 |
# builder ステージの末尾に追記 RUN go install github.com/cosmtrek/air@latest # 開発用エントリポイントを上書き CMD ["air", "-c", ".air.toml"] |
.air.toml のシンプル設定例(30 行未満):
|
1 2 3 4 5 6 7 8 9 |
[build] cmd = "go build -o /app/bin/app ./src" bin = "/app/bin/app" include_ext = ["go"] exclude_dir = ["vendor", ".git"] [log] time = true |
この構成で docker run(上記と同様)を実行すると、src/ 配下の .go ファイルが変更されるたびに自動ビルド・再起動が走ります。
Delve(dlv)によるコンテナ内デバッグ
本番イメージに dlv を含めず、デバッグ専用イメージを作成する方法をご紹介します。builder ステージへインストールし、ポート公開とヘッドレスモードで起動します。
|
1 2 3 4 5 6 |
# builder の続き RUN go install github.com/go-delve/delve/cmd/dlv@latest # デバッグ用エントリポイント(オプション) CMD ["dlv", "debug", "./src/main.go", "--headless", "--listen=:40000", "--api-version=2", "--log"] |
コンテナ起動例:
|
1 2 3 4 5 |
docker run --rm -it \ -v "$(pwd)/src:/app/src" \ -p 8080:8080 -p 40000:40000 \ my-go-app:debug |
VS Code の Go 拡張機能で「Attach to Remote」設定を作成し、localhost:40000 に接続すればブレークポイントが有効になります。
コンテナ内での go test 実行
CI と同一環境で単体テストを走らせることで、ローカルと CI の結果差異を排除できます。以下は開発イメージ上でテストを実行する例です。
|
1 2 |
docker run --rm -v "$(pwd)/src:/app/src" my-go-app:dev go test ./... |
go.modがマウントされた状態なので、依存解決も自動的に行われます。- テストが失敗した場合はコンテナの終了コードが 1 になるため、シェルスクリプトや CI の判定ロジックと自然に連携できます。
CI/CD と本番デプロイ
GitHub Actions を活用し、マルチアーキテクチャ対応イメージの自動ビルド・Docker Hub へのプッシュを実現します。エラーが発生した際の対処法も併せて掲載しています。
GitHub Actions ワークフロー例
.github/workflows/docker.yml に配置する YAML は、20 行以内に収まるシンプルかつ拡張性の高い構成です。コメントは省略し、必要最小限のステップだけを書きました。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
name: Docker Build & Push on: push: branches: [ main ] jobs: build-and-push: runs-on: ubuntu-latest steps: - uses: actions/checkout@v3 - name: Set up QEMU uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Login to Docker Hub uses: docker/login-action@v2 with: username: ${{ secrets.DH_USERNAME }} password: ${{ secrets.DH_TOKEN }} - name: Build and push multi‑arch image uses: docker/build-push-action@v5 with: context: . file: Dockerfile platforms: linux/amd64,linux/arm64 push: true tags: ${{ secrets.DH_USERNAME }}/my-go-app:latest |
ワークフローのポイント
- QEMU と Buildx の組み合わせで、
amd64とarm64両方のイメージを同時にビルド。 docker/build-push-action@v5が内部的に BuildKit を有効化するため、手動で環境変数を設定する必要はありません。- シークレットとして保存した Docker Hub の認証情報は、GitHub リポジトリの Settings > Secrets and variables > Actions から登録してください。
本番向け最小イメージ戦略
Alpine ベース(汎用的)
|
1 2 3 4 5 6 7 8 9 10 11 |
FROM alpine:3.19 AS runtime # 必要に応じて ca-certificates をインストール RUN apk add --no-cache ca-certificates RUN addgroup -S app && adduser -S -G app app WORKDIR /app COPY --from=builder /app/bin/app ./app USER app EXPOSE 8080 CMD ["./app"] |
- サイズは
ca-certificatesを含めても 10–12 MB 程度に抑えられます。 - TLS が必須な外部 API 呼び出しや HTTPS サーバの場合は、上記行を有効にしてください。
Scratch ベース(超小型)
|
1 2 3 4 5 6 |
FROM scratch AS prod COPY --from=builder /app/bin/app /app USER 1000:1000 EXPOSE 8080 ENTRYPOINT ["/app"] |
- 利用シーン:社内マイクロサービスやリソース制約が厳しいエッジデバイス向け。
- 注意点:
/etc/passwdや証明書が無いため、ログ出力は標準出力に限定し、TLS が不要な場合のみ推奨。
よくあるエラーと対処法
| エラー | 原因 | 解決策 |
|---|---|---|
go.mod not found |
Dockerfile の WORKDIR が期待通りでない |
WORKDIR /app/src を明示し、COPY src/go.mod . のパスを確認 |
| ポートがマッピングされていない | docker run -p オプションの記述ミス |
-p 8080:8080 の形でホストポートとコンテナポートを同一に指定 |
| ビルドが遅くなる(キャッシュ未使用) | BuildKit が無効、もしくは go.mod が変更されている |
環境変数 DOCKER_BUILDKIT=1 を設定し、docker build --no-cache で再確認 |
| デバッグ時に dlv が接続できない | ポート公開忘れ、またはファイアウォール制限 | -p 40000:40000 を必ず付与し、ローカルのセキュリティポリシーを緩和 |
| GitHub Actions のプッシュ失敗 | Docker Hub の認証情報が未設定または期限切れ | リポジトリシークレット DH_USERNAME と DH_TOKEN を再生成し、正しく登録 |
ベストプラクティス:CI でのビルドエラーは、ローカル環境と同一の Dockerfile/docker-compose 設定で再現できるかをまず確認してください。
まとめ
- 開発環境: 最新版 Docker Desktop(Windows/macOS)または Docker Engine(Linux)に加え、Go 1.22、Git、VS Code をインストールし、
docker versionで動作確認を行います。 - プロジェクト構成:
src/にコード・テスト・モジュール情報を配置し、.dockerignoreで不要ファイル(Go キャッシュや IDE 設定)を除外します。 - マルチステージ Dockerfile: Builder → Runtime(Alpine)または Scratch の二段階構成により、イメージサイズは数 MB に抑えつつビルド速度と再現性を確保します。BuildKit と
--targetオプションでビルドプロセスを柔軟に制御できます。 - 開発時の利便性: ボリュームマウント+Air によるホットリロード、dlv によるコンテナ内デバッグ、
go testのコンテナ実行でローカルと CI が同一環境になるよう統一します。 - CI/CD と本番デプロイ: GitHub Actions でマルチアーキテクチャビルド・自動プッシュを設定し、Alpine または Scratch の最小イメージへデプロイすることで、セキュリティと運用コストの両面を最適化します。
本ガイドに沿って手順を実践すれば、ローカル開発 → 継続的インテグレーション → 本番環境への安全なデプロイ がシームレスに行えるようになります。ぜひご自身のリポジトリで試し、チーム全体の DevOps 効率化に役立ててください。