この記事では、Golang を用いた開発環境を Docker 上に構築する手順を紹介します。これまでの実践やトラブルシュート(たとえば、go.mod が見つからないエラー、Air のインストールパスの変更、ポートマッピングの不一致など)を踏まえ、初心者でもわかりやすく手順を整理しました。
目次
- プロジェクトのディレクトリ構成の準備
- Go モジュールの初期化
- Dockerfile の作成と Air のインストール
- Air の設定ファイル(.air.toml)の詳細解説
- サンプル Go コードの作成(HTTP サーバーの実装)
- docker-compose.yml の作成とボリューム/ポートマッピング設定
- ローカル環境の起動と動作確認
- まとめ
1. プロジェクトのディレクトリ構成の準備
まず、プロジェクト全体の親ディレクトリ(例:CPI-Explorer
)を作成し、その中に Golang のサービス用ディレクトリ(ここでは cpi-fetcher)を用意します。以下のような構成を目標とします。
CPI-Explorer/ ← プロジェクト全体のルート
├── docker-compose.yml ← 全体のコンテナオーケストレーション用
└── cpi-fetcher/ ← Golang サービス用ディレクトリ
├── Dockerfile ← Docker イメージのビルド手順
├── .air.toml ← Air の設定ファイル(ホットリロード用)
├── go.mod ← Go モジュールの初期化ファイル
├── go.sum ← 依存パッケージのチェックサム(自動生成)
├── src/ ← ソースコード用ディレクトリ
│ └── main.go ← アプリケーションのエントリーポイント
└── tmp/ ← ビルド成果物出力先(Air の設定で指定)
ターミナルで以下のコマンドを実行して準備してください。
mkdir -p ~/projects/CPI-Explorer/cpi-fetcher/src
cd ~/projects/CPI-Explorer/cpi-fetcher
2. Go モジュールの初期化
Golang では依存管理に「Go Modules」を利用します。
cpi-fetcher ディレクトリ内で以下のコマンドを実行してモジュール初期化を行います。
go mod init github.com/your-username/CPI-explorer/cpi-fetcher
※ 実際の GitHub リポジトリ URL に合わせて your-username
は適宜変更してください。
これにより、go.mod
が生成され、外部ライブラリの依存管理ができるようになります。
3. Dockerfile の作成と Air のインストール
Dockerfile を作成し、コンテナ内で Golang の環境と Air をセットアップします。
Air はホットリロードツールで、ソースコードの変更検知時に自動でビルド・再起動してくれます。
注意: 以前は github.com/cosmtrek/air
を使っていましたが、現在はモジュールパスが変更され、正しくは github.com/air-verse/air
です。
cpi-fetcher/Dockerfile
# ベースイメージ(Go 1.23)
FROM golang:1.23
# 作業ディレクトリを /app に設定
WORKDIR /app
# ホットリロードツール Air をインストール(正しいパスを使用)
RUN go install github.com/air-verse/air@latest
# ソースコードはホスト側からマウントするので、コピーは不要
# コンテナ起動時に Air を実行する(設定ファイル .air.toml を利用)
CMD ["air", "-c", ".air.toml"]
4. Air の設定ファイル(.air.toml)の詳細解説
Air の設定は .air.toml
で行います。以下はサンプルと各項目の詳細です。
cpi-fetcher/.air.toml
root = "."
tmp_dir = "tmp"
[build]
# ソースコードをビルドするコマンド。src ディレクトリ内のコードをコンパイルして tmp/main に出力
cmd = "go build -o tmp/main ./src"
# 出力されたバイナリのパス
bin = "tmp/main"
# 監視対象の拡張子。これらのファイルが変更されたら再ビルドをトリガー
include_ext = ["go", "tpl", "tmpl", "html"]
# 監視対象から除外するディレクトリ。特にビルド成果物の tmp は除外することで無限ループを防止
exclude_dir = ["assets", "tmp", "vendor"]
[log]
# ログにタイムスタンプを表示。デバッグに役立つため true を設定
time = true
[run]
# ビルド後に実行するコマンド。ここではビルド済みのバイナリ tmp/main を実行
cmd = "tmp/main"
各設定項目のポイント
-
root:
プロジェクトのルートディレクトリを指定。通常は"."
でOKです。 -
tmp_dir:
ビルド成果物(バイナリファイル)を出力する一時ディレクトリ。ここで指定したディレクトリ内に、go build
の出力結果が保存されます。 -
[build] セクション:
-
cmd: 実際のビルドコマンド。
go build -o tmp/main ./src
は、src
内のコードをコンパイルし、tmp/main
にバイナリを作成します。 - bin: ビルド後の実行ファイルのパス。Air が実行時にこの値を使用します。
- include_ext: 監視対象のファイル拡張子。これらのファイルが変更されると、Air が再ビルドを行います。
-
exclude_dir: 監視から除外するディレクトリ。特にビルド成果物が出力される
tmp
は除外するのがポイントです。
-
cmd: 実際のビルドコマンド。
-
[log] セクション:
ログの出力形式を設定します。タイムスタンプ付きにすると、ビルドや実行のタイミングがわかりやすくなります。 -
[run] セクション:
ビルドが成功した後に実行するコマンドを指定します。ここでは、先ほどビルドしたtmp/main
を実行しています。
5. サンプル Go コードの作成
ここでは、簡単な HTTP サーバーのサンプルコードを用意します。
cpi-fetcher/src/main.go
package main
import (
"fmt"
"log"
"net/http"
)
func helloHandler(w http.ResponseWriter, r *http.Request) {
// クライアントにレスポンスを返す
fmt.Fprintln(w, "Hello from CPI Explorer - cpi-fetcher!")
}
func main() {
// ルートパスに対してハンドラーを設定
http.HandleFunc("/", helloHandler)
port := "8080"
log.Printf("cpi-fetcher is running on port %s...\n", port)
// すべてのインターフェースからのアクセスを受け付けるため、0.0.0.0 を指定
log.Fatal(http.ListenAndServe("0.0.0.0:"+port, nil))
}
このコードは、コンテナ内で 8080 番ポートにて HTTP サーバーを起動し、アクセスがあれば「Hello from CPI Explorer - cpi-fetcher!」と返すシンプルなものです。
6. docker-compose.yml の作成とボリューム/ポートマッピング設定
親ディレクトリ CPI-Explorer に docker-compose.yml を作成し、サービス全体を管理します。
特に、ホスト側の cpi-fetcher ディレクトリ全体をコンテナ内の /app
にマウントすることで、go.mod
やその他のファイルが正しく利用されるようにします。
CPI-Explorer/docker-compose.yml
version: '3.8'
services:
cpi-fetcher:
build: ./cpi-fetcher
container_name: cpi-fetcher
volumes:
- ./cpi-fetcher:/app
ports:
- "8080:8080"
working_dir: /app
ポイント
-
Volumes:
./cpi-fetcher:/app
とすることで、ホストの cpi-fetcher ディレクトリ全体がコンテナ内の/app
にマッピングされ、go.mod
、src/
、.air.toml
などが正しく利用されます。
※ 個別にファイルをマウントする方法もありますが、全体マウントがシンプルです。 -
Ports:
コンテナ側の 8080 番ポートとホスト側の 8080 番ポートをマッピングします。
※ 初期のトラブルで、ホストとコンテナ間のポートマッピングが不一致だと「ERR_EMPTY_RESPONSE」などのエラーが発生するため注意してください。 -
working_dir:
コンテナ内での作業ディレクトリを/app
に設定しています。これにより、Air やgo build
が正しいパスで実行されます。
7. ローカル環境の起動と動作確認
すべての設定が完了したら、Docker Compose を使ってコンテナを起動します。
-
親ディレクトリ CPI-Explorer に移動し、以下のコマンドを実行します。
cd ~/projects/CPI-Explorer docker-compose up --build -d
-
コンテナのログを確認して、Air のビルドやアプリケーションの起動が正しく行われているか確認します。
docker-compose logs cpi-fetcher
ログには「cpi-fetcher is running on port 8080...」と表示されるはずです。
-
ブラウザや curl でアクセスし、レスポンスが返ってくるかテストします。
curl http://localhost:8080
正常であれば、「Hello from CPI Explorer - cpi-fetcher!」と表示されます。
8. まとめ
この記事では、Golang のローカル開発環境を Docker と Air を使って構築する手順を整理しました。
これまでのトラブル(go.mod ファイルが見つからない、Air のインストールパスの変更、ポートマッピングの不一致など)も解決しながら、以下の手順で環境を整えました。
-
プロジェクトのディレクトリ構成の準備:
必要なディレクトリとファイル(go.mod、src/、.air.toml など)を用意。 -
Go モジュールの初期化:
go mod init
コマンドで依存管理を開始。 -
Dockerfile の作成と Air のインストール:
正しいモジュールパス(github.com/air-verse/air)を使用し、Air をインストール。 -
.air.toml の詳細設定:
ビルドコマンド、監視対象、除外ディレクトリなど、ホットリロードに必要な設定を実施。 -
サンプルコードの実装:
簡単な HTTP サーバーを実装し、実際にレスポンスが返るか確認。 -
docker-compose.yml の設定:
ホスト側のディレクトリ全体をコンテナ内にマウントし、ポートマッピングを正しく設定。 -
起動と検証:
Docker Compose でコンテナをビルド・起動し、ログや curl で動作確認。
これらの手順を参考に、快適な Golang の開発環境を構築してください。
もし疑問や問題が発生した場合は、各設定ファイルやログを再確認し、適切な調整を行って頂ければ解決できるはずです。dockerでのローカル環境構築では、docker compose logs container_name
をデバッグで頻繁に利用します。覚えておくと便利です。
以上、Docker と Air を利用した Golang のローカル開発環境構築手順の解説でした。