Golang開発環境構築
コンセプト
- ローカル環境に処理系をインストールしない(全てコンテナに集約)
- 開発時はVS Codeのリモートコンテナでコンテナ内で開発
- ホットリロードツールで自動的にビルド
前提条件
- OSSとして公開しないプロジェクト(自社サービスとか)
環境
- Ubuntu 20.04
- Docker
- VS Code
- Remote Containers
ディレクトリ構成
$tree -a -I .git
.
├── .air.toml
├── .devcontainer.json
├── .env.example
├── .gitignore
├── Dockerfile
├── Makefile
├── README.md
├── docker-compose.yaml
├── go.mod
├── go.sum
└── main.go
- ルートディレクトリに
main.go
を配置するスタイル
Dockerfile
- 開発時に使用するコンテナとリリース用のコンテナをマルチステージビルドで分けている
FROM golang:1.20 AS dev
WORKDIR /app
# -- Set ENV
ENV CGO_ENABLED=1 \
GOOS=linux \
GOARCH=amd64
# -- Install Dev Tool
RUN go install github.com/cosmtrek/air@latest && \
go install golang.org/x/tools/gopls@latest && \
go install github.com/ramya-rao-a/go-outline@latest && \
go install golang.org/x/tools/cmd/goimports@latest && \
go install github.com/josharian/impl@latest && \
go install github.com/go-delve/delve/cmd/dlv@latest && \
go install github.com/cweill/gotests/...@latest && \
go install github.com/haya14busa/goplay/cmd/goplay@latest && \
go install github.com/fatih/gomodifytags@latest && \
go install go.uber.org/mock/mockgen@latest && \
go install github.com/onsi/ginkgo/v2/ginkgo@latest && \
go install github.com/onsi/gomega/...@latest && \
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.55.2
# -- COPY Source
COPY . /app
# -- Build
RUN go mod download && go build -o ${GOPATH}/bin/myapp main.go
# -- Hot reload
CMD ["air", "-c", ".air.toml"]
FROM ubuntu:22.04 as prod
WORKDIR /app
# -- Set Envs
ENV DEBIAN_FRONTEND=noninteractive \
TZ=Asia/Tokyo \
LC_ALL=C.UTF-8 \
LANG=C.UTF-8
#
RUN apt update && apt install -y tzdata
COPY --from=dev /go/bin/myapp /app
CMD ["/app/myapp"]
- 処理系のバージョンは明示的に決めたいのでバージョンタグが付いたものを使用(
latest
は使わない)
- 開発用のコンテナにはユーティリティツールもインストールしている(VS Codeのリモートコンテナ起動時に毎回サジェストされるのが鬱陶しいので)
- 開発時はホットリロードツールとして
air
を利用している
docker-compose.yaml
version: '3.8'
services:
app:
environment:
PORT: ${PORT}
build: .
volumes:
- type: bind
source: "."
target: "/app"
ports:
- ${PORT}:8080
.devcontainer.json
{
"name": "MyDevContainer",
"dockerComposeFile": [
"docker-compose.yaml"
],
"service": "app",
"remoteUser": "root",
"workspaceFolder": "/app",
"customizations": {
"vscode": {
"extensions": [
"golang.go",
"ms-azuretools.vscode-docker"
]
}
}
}
Makefile
build:
go build -o myapp main.go
test:
go test ./...
lint:
golangci-lint run --fix ./...
- ターゲットのコマンド行がスペースになっている事に注意
- 本稿ではHTML生成時にツールによってスペースに置換されてしまっているが、実際のMakefileではタブである必要がある
モジュールの追加
- ソースコードにimportを追加 && コンテナ内で
go mod tidy
- VS Codeのリモートコンテナで開発している場合、コンテナのターミナルが使えるようになるのでそこで実行する
参考資料