Contents
前提条件とインストール手順
本章では、ローカル環境で Go アプリを Docker コンテナ上で開発 するために最低限必要なツールの導入方法を解説します。Docker Desktop と Go のバージョンは「最新安定版」を対象とし、VSCode の拡張機能は CLI が PATH に通っている前提でインストールコマンドを示しています。各ツールが正しくインストールできれば、以降の手順はすべてコンテナ内で完結します。
Docker Desktop の導入
- 公式サイト(https://www.docker.com/products/docker-desktop)から OS に合わせた Docker Desktop(最新安定版) をダウンロード。
- インストーラを実行し、指示に従ってインストール。インストール完了後は
docker versionでバージョンが表示されることを確認してください。
補足:Docker Desktop のバージョン番号は頻繁に更新されます。記事執筆時点の「最新安定版」を使用する方針とし、具体的な数字は記載していません。
Go の導入
- https://go.dev/dl/ から Go 1.22 以降 のバイナリ(Linux/macOS/Windows)を取得。
- ダウンロードしたアーカイブを解凍し、
go実行ファイルが PATH に含まれるように環境変数PATH=$PATH:/usr/local/go/bin(例)を設定。 go versionで正しくインストールされていることを確認。
VSCode と拡張機能の導入
VSCode 本体は公式サイトからインストールしてください。その後、ターミナルで次のコマンドを実行します(VSCode の CLI (code) が PATH に通っていることが前提です。PATH へ登録されていない場合は、VSCode の「Shell Command: Install 'code' command in PATH」メニューから設定できます)。
|
1 2 3 4 5 6 |
# Remote‑Containers 拡張 code --install-extension ms-vscode-remote.remote-containers # Go 拡張(公式) code --install-extension golang.go |
注意:上記コマンドが失敗した場合は、VSCode の GUI から「拡張機能」パネルを開き、名前で検索して手動インストールしてください。
まとめ
- Docker Desktop・Go・VSCode(+拡張)の「最新安定版」を導入すれば、ローカルでも本番に近いコンテナ環境が構築できます。
codeコマンドは PATH に追加しておくとスクリプト化しやすく、手順の自動化が可能です。
プロジェクト構成と go.mod 初期化
このセクションでは、Go の標準的なディレクトリレイアウトとモジュール管理の基本を紹介します。適切に構造化されたプロジェクトは Docker のキャッシュ利用や CI/CD パイプラインでのビルド効率向上につながります。
推奨ディレクトリツリー
以下は「業務アプリケーション」想定の典型的な構成です。myapp はリポジトリ名に置き換えてください。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
myapp/ ├── cmd/ # アプリケーションのエントリポイント │ └── server/ │ └── main.go ├── internal/ # プロジェクト内部だけで利用するパッケージ │ └── handler/ │ └── handler.go ├── pkg/ # 外部公開可能なユーティリティライブラリ │ └── utils/ │ └── util.go ├── go.mod # モジュール定義ファイル └── go.sum # 依存関係のハッシュ |
- cmd/:
mainパッケージを配置し、ビルド対象のバイナリを生成します。 - internal/: 他モジュールからインポートできないように Go が自動的に制限する領域です。
- pkg/: ライブラリとして外部に提供したいコードを置きます(公開 API の設計が容易になります)。
go.mod の初期化手順
|
1 2 3 4 5 6 7 8 9 10 11 12 |
# プロジェクトのルートへ移動 cd myapp # モジュール名は GitHub リポジトリパスなど、ユニークな名前を指定 go mod init github.com/yourname/myapp # 例として Gin フレームワークを取得(バージョンは最新安定版で OK) go get github.com/gin-gonic/gin@latest # 依存関係が正しく解決できるかローカルビルド go build ./cmd/server |
go.mod が生成されると、go.mod と go.sum の内容は Docker ビルド時のキャッシュレイヤーとして再利用できます。
まとめ
- 標準的なディレクトリ構成を採用すると、コードの可読性・保守性が向上し、Docker キャッシュ戦略と相性が良くなります。
go.modの初期化は最初の一手です。以降の依存追加はgo getで行い、必ずgo mod tidyで整合性を保ちましょう。
マルチステージ Dockerfile の作成
ここでは ビルダーイメージ と 実行イメージ を分離したマルチステージ構成のポイントを解説します。レイヤーキャッシュと最小化されたランタイムを両立させることで、開発・本番どちらでも高速なコンテナが得られます。
キャッシュ活用の基本戦略
ビルドステージで go.mod と go.sum を先にコピーし、依存関係だけをダウンロードするレイヤーを作ります。ソースコードが変更されてもこのレイヤーは再利用されるため、go mod download の実行回数が減少します。
推奨 Dockerfile(Dockerfile.dev)
|
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 30 31 32 33 34 35 36 37 38 39 |
# ---------- Builder Stage ---------- FROM golang:1.22-buster AS builder # Air と ca-certificates をインストール(Air は Go でビルドできるので go install を使用) RUN apt-get update && apt-get install -y --no-install-recommends ca-certificates \ && rm -rf /var/lib/apt/lists/* \ && go install github.com/cosmtrek/air@latest # PATH に Air のバイナリを追加 ENV PATH="/go/bin:${PATH}" WORKDIR /app # 1️⃣ 依存関係だけをコピーしてキャッシュを作成 COPY go.mod go.sum ./ RUN go mod download # 2️⃣ ソースコード全体をコピー COPY . . # 本番イメージ用にバイナリをビルド(開発時は Air が実行されるので必須ではない) RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 \ go build -ldflags="-s -w" -o /app/bin/server ./cmd/server # ---------- Runtime Stage ---------- FROM alpine:latest AS runtime # 「最新安定版」 Alpine を使用 WORKDIR /app COPY --from=builder /app/go.mod . COPY --from=builder /app/go.sum . COPY --from=builder /app/bin/server ./server COPY --from=builder /go/bin/air /usr/local/bin/air # Air バイナリをコピー # 必要な CA 証明書だけを残す(TLS 通信がある場合に備える) RUN apk add --no-cache ca-certificates && update-ca-certificates EXPOSE 8080 CMD ["./server"] |
テーブルでポイントを整理
| 項目 | 内容・効果 |
|---|---|
| ベースイメージ | golang:1.22-buster(公式、長期サポート)と alpine:latest(軽量) |
| キャッシュ戦略 | go.mod/go.sum を先にコピー → RUN go mod download で依存レイヤーを固定 |
| バイナリ配置 | ビルダーから実行ステージへ /app/bin/server のみ持ち込む |
| Air のインストール | go install により最新版を取得し、PATH へ追加 |
| CA 証明書 | 本番で外部 API を呼び出す際に必要な最小限の証明書だけを残す |
まとめ
- マルチステージ構成は「ビルド高速化 + イメージ軽量化」の両立が可能です。
go.modの先行コピーとgo mod downloadがキャッシュ利用の鍵となります。
docker‑compose.yml におけるサービス定義とボリューム設定
この章では、開発用コンテナ(Air 監視) と 本番用コンテナ を同一 Compose ファイルで管理する方法を示します。ボリュームマウントと working_dir の正しい指定が、ホスト側エディタとコンテナ内部のファイル同期を円滑にします。
開発サービス(Air)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
version: "3.9" services: app: build: context: . dockerfile: Dockerfile.dev container_name: go_app_dev working_dir: /app # コンテナ内部の作業ディレクトリを明示 command: ["air", "-c", ".air.toml"] # Air が変更を監視 ports: - "8080:8080" volumes: - ./:/app:cached # ソースコードをマウント(macOS/Windows 推奨) environment: - GOENV=development |
:cachedオプションは macOS/Windows のファイル共有における I/O パフォーマンス向上効果があります。working_dirが設定されていないと、Air が期待するプロジェクトルートを認識できずエラーになるケースが多く報告されています。
本番サービス(最小イメージ)
|
1 2 3 4 5 6 |
prod: image: yourrepo/go-app:latest # ビルド済みマルチステージイメージをタグ付けしたもの container_name: go_app_prod ports: - "80:8080" |
- 本番サービスは ビルダーイメージから生成された最小ランタイム を直接使用するだけなので、
buildセクションは不要です。
まとめ
- 開発用と本番用を同一
docker-compose.ymlに記述すれば、環境切替がdocker compose up app/docker compose up prodのみで完了します。 - 正しい
working_dirとボリューム設定により、Air のライブリロードがエディタの保存と同時に反映されます。
Air を使ったライブリロード環境と VSCode Remote‑Containers 設定
このセクションでは、Air の詳細設定 と VSCode Remote‑Containers の構成 を組み合わせた開発フローを解説します。.air.toml の各項目の意味を丁寧に説明し、初心者でもすぐに使えるテンプレートを提供します。
Air のインストールと .air.toml の解説
Dockerfile で go install github.com/cosmtrek/air@latest を実行すると、/go/bin/air にバイナリが配置されます。次にプロジェクトルートに以下の設定ファイルを作成してください。
|
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 |
# .air.toml – Live Reload 設定ファイル # 1️⃣ プロジェクトのルートディレクトリ(Docker コンテナ内の作業ディレクトリと同一) root = "." # デフォルトはカレントディレクトリ # 2️⃣ ビルド成果物を格納する一時領域。コンテナ内部にだけ存在し、ホストへはマウントされません。 tmp_dir = "tmp" [build] # Air が変更検知したときに実行するコマンド cmd = "go build -o ./tmp/server ./cmd/server" # 上記コマンドで生成されたバイナリのパス(Air が自動起動する対象) bin = "./tmp/server" # 監視対象となるファイル拡張子。ここに列挙したものが変更されるとビルドが走ります。 include_ext = ["go", "tmpl", "html"] # ビルドから除外するディレクトリ(依存関係のキャッシュ等は不要なので除外) exclude_dir = ["vendor", "tmp", ".git"] [log] # ログにタイムスタンプを付与。デバッグ時に変更時間が分かりやすくなります。 time = true [color] # コンソール出力の色設定(任意)。"yellow" はビルド成功時のハイライトです。 main = "yellow" |
主な項目のポイント
| セクション | キー | 説明 |
|---|---|---|
root |
"." |
プロジェクトルート。Docker の working_dir と合わせることでパスずれを防止 |
tmp_dir |
"tmp" |
ビルド成果物の一時保存先。コンテナ再起動時に自動削除されるのでクリーンな状態が保たれる |
[build] |
cmd |
変更検知時に実行するビルドコマンド(go build -o ./tmp/server …) |
bin |
ビルド後に Air が起動させるバイナリのパス | |
include_ext |
監視対象拡張子。Go ソースだけでなくテンプレート等も含められる | |
exclude_dir |
キャッシュや VCS ディレクトリを除外し、無駄なビルドを防止 | |
[log] |
time |
ログに時刻を出力。デバッグが容易になる |
[color] |
main |
コンソールの文字色(任意) |
VSCode Remote‑Containers の構成
devcontainer.json の設定例
プロジェクト直下に .devcontainer/devcontainer.json を作成します。Docker Compose ファイルを参照し、app サービスを開発コンテナとして利用します。
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
{ "name": "Go Development Container", "dockerComposeFile": ["../docker-compose.yml"], "service": "app", // docker‑compose の app サービスを使用 "workspaceFolder": "/app", "remoteUser": "root", "extensions": [ "golang.go", "ms-vscode-remote.remote-containers" ], "postCreateCommand": "go mod tidy && air -c .air.toml", // コンテナ起動後に Air を自動起動 "settings": { "go.useLanguageServer": true, "go.formatTool": "gofmt", "editor.formatOnSave": true } } |
postCreateCommandはコンテナ作成直後に実行され、依存解決と Air の起動を自動化します。extensionsに Remote‑Containers と Go 拡張を列挙しておくことで、VSCode が自動的にインストールします。
デバッグ構成(launch.json)
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
{ "version": "0.2.0", "configurations": [ { "name": "Launch Go Server (Remote)", "type": "go", "request": "launch", "mode": "auto", "program": "${workspaceFolder}/cmd/server", "env": { "GOENV": "development" }, "remotePath": "/app" } ] } |
remotePathはコンテナ内部の作業ディレクトリを指すため、ブレークポイントが正しくマッピングされます。
まとめ
.air.tomlの各項目を把握すれば、ファイル変更 → ビルド → 再起動までが数秒で完了する開発フローが構築できます。- VSCode Remote‑Containers と組み合わせることで、エディタ自体がコンテナ内に入り込む形になり、環境差異によるトラブルを大幅に削減できます。
ビルド・テスト・CI/CD の実践例とトラブルシューティング
本章では、日常的に使うビルド/テストコマンドと、GitHub Actions / GitLab CI での Docker イメージ自動化手順を示します。また、よくあるエラーとその対処法もまとめました。
よくあるエラー一覧(導入文)
以下は開発中に頻出するエラーメッセージと、その原因・解決策です。表の左側が実際にコンテナ上で表示されるメッセージ、右側が対処法になります。
| エラー | 原因 | 解決策 |
|---|---|---|
go.mod not found |
作業ディレクトリが /app ではない、またはボリュームマウント失敗 |
docker-compose.yml の working_dir: /app と volumes: - ./:/app を再確認し、docker compose up --build でキャッシュクリア |
listen tcp :8080: bind: address already in use |
ホスト側でポート 8080 が既に占有されている | docker compose ps で使用中コンテナを特定し、docker compose down 後に空きポート(例: 8081)へ変更 |
air: command not found |
Dockerfile の PATH に /go/bin が追加されていない |
Dockerfile に ENV PATH="/go/bin:${PATH}" を追記、または RUN cp /go/bin/air /usr/local/bin/ |
cannot find module for package … |
go.mod キャッシュが古くなっている |
コンテナ内で go clean -modcache 実行、あるいは docker compose build --no-cache でイメージ再構築 |
Q&A サンプル
-
Q:
docker compose exec app go test ./...が失敗し、no such file or directory: .air.tomlと出ます。
A: テスト実行時に Air の設定は不要です。コマンドをdocker compose exec app sh -c "go test ./..."に変更すれば問題なく走ります。 -
Q: Windows 環境でボリュームマウントが遅いと感じる。
A: Docker Desktop の「Settings → Resources → File Sharing」でパフォーマンスオプションをcachedに設定し、Compose ファイルでも:cachedを付与すると I/O が改善します。
GitHub Actions でのビルド・プッシュ例
|
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 30 31 32 |
name: Docker Build & Push on: push: branches: [ main ] jobs: build-and-push: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v3 - name: Set up Buildx uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v3 with: username: ${{ secrets.DOCKER_USER }} password: ${{ secrets.DOCKER_PASS }} - name: Build and push image uses: docker/build-push-action@v5 with: context: . file: Dockerfile.dev push: true tags: yourrepo/go-app:${{ github.sha }},yourrepo/go-app:latest |
docker/build-push-actionがマルチステージイメージ全体をビルドし、タグ付けして Docker Hub にプッシュします。- ビルドキャッシュは GitHub のレイヤーキャッシュ機能が自動で利用されるため、2 回目以降は高速化されます。
GitLab CI での go mod キャッシュ例
|
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 30 31 32 |
stages: - build - test variables: GO_VERSION: "1.22" before_script: - apt-get update && apt-get install -y wget ca-certificates - wget https://dl.google.com/go/go${GO_VERSION}.linux-amd64.tar.gz - tar -C /usr/local -xzf go${GO_VERSION}.linux-amd64.tar.gz - export PATH=$PATH:/usr/local/go/bin build: stage: build script: - go mod download # 依存取得をキャッシュ対象にする - docker build -t $CI_REGISTRY_IMAGE:$CI_COMMIT_SHORT_SHA . cache: key: "${CI_PROJECT_ID}-go-mod" paths: - .modcache/ tags: - docker test: stage: test script: - go test ./... dependencies: - build |
cacheセクションで$GOPATH/pkg/mod(デフォルトは.modcache/)を保存し、次回ジョブの実行時間を短縮します。- Docker ビルドは
buildジョブで完了させ、testは Go のユニットテストのみを走らせます。
まとめ
- エラーメッセージと原因を把握すれば、トラブルの切り分けが格段に楽になります。
- CI/CD パイプラインは Docker のマルチステージビルドと
go.modキャッシュを活用するだけで高速化でき、GitHub Actions と GitLab CI どちらでも同様の構成が可能です。
全体まとめ
- 前提ツール:Docker Desktop(最新安定版)・Go 1.22+・VSCode + Remote‑Containers/Go 拡張をインストールすれば、ローカルでも本番に近い環境が手に入ります。
- プロジェクト構成:標準的な
cmd / internal / pkgレイアウトとgo.modの初期化で依存管理と Docker キャッシュを最適化します。 - マルチステージ Dockerfile:
go.mod先行コピー+go mod downloadによるレイヤーキャッシュ、Alpine ベースの実行イメージでサイズとセキュリティを両立。 - docker‑compose.yml:開発用(Air)と本番用サービスを同一ファイルで管理し、ボリュームマウントと
working_dirの設定がライブリロードの鍵になります。 - Air と VSCode Remote‑Containers:
.air.tomlの各項目を理解すれば「保存 → ビルド → 再起動」まで数秒で完了し、VSCode からシームレスにデバッグ可能です。 - CI/CD とトラブルシューティング:GitHub Actions / GitLab CI にマルチステージビルドと
go.modキャッシュを組み込むことで、継続的デリバリーが高速かつ安定します。
以上のベストプラクティスに沿って環境構築すれば、Go + Docker 開発 の生産性と信頼性が大幅に向上し、チーム全体で統一された開発フローを実現できます。