はじめに
個人開発で最近Go言語を使う機会が増えてきました。
Go言語で開発するにあたり私が感じたことは、
- Dockerで動かしたい
- ホットリロード機能が欲しい
- 開発用・本番用でコンテナを分けたい
- 開発時は、VSCode上でコンテナ内とリモート接続して作業したい
色々な方々のDocker環境を参考にDockerでGo環境を作りました。
よろしければ参考にしてください。
ホスト環境
- Docker: ver.19.03.8
- docker-compose: ver.1.25.4
- VSCode: ver.1.43.0
ホットリロード
Go言語でホットリロードをする際、調べていたら、
- fresh
- realize
があるのを知りました。
しかし、筆者はrealize の方はエラー(error: returned a non-zero code: 1
)が発生してgo get
ができませんでした。
一度コンテナを立ち上げて、コンテナ内でgo get
したらうまく行くのですが解決出来ませんでした...
ですので今回はfresh を使用します。
手順
- Dockerfile(開発用&本番用) + docker-compose.yml の作成
- Remote Containers の設定
- ホットリロードの設定
- 開発環境の起動
- 開発環境の動作確認
- 本番環境の起動
開発環境
はじめに作業ディレクトリを作ります。
# 作業ディレクトリ作成
$ mkdir go-work
# 作業ディレクトリへ移動
$ cd go-work
1. Dockerfile(開発用&本番用) + docker-compose.yml の作成
続いてDockerfile とdocker-compose.yml を書いていきます。
下記コマンドからファイルを作成してください。
$ touch docker-compose.yml
$ mkdir -p docker/golang
$ touch docker/golang/Dockerfile.dev
$ touch docker/golang/Dockerfile.dep
※ Dockerfileの言語サポート
Dockerfile.dev(.dep) はVSCodeの標準では言語サポートされていないので設定を追加します。
設定されている方は次へ飛ばしてください。
- [Code] -> [基本設定] -> [設定]
-
Files: Associations
で検索 -
settings.json
で編集
{
"files.associations": {
"Dockerfile.dev": "dockerfile",
"Dockerfile.dep": "dockerfile"
}
}
Docker + docker-composeの設定
- 開発用Dockerfile
FROM golang:1.14.0-alpine3.11
SHELL ["/bin/ash", "-c"]
WORKDIR /go/src/app
COPY ./app ./
EXPOSE 8080
ENV GO111MODULE=on
RUN apk add --no-cache alpine-sdk
# Golang ホットリロード(freshのインストール)
RUN go get github.com/pilu/fresh
# Golang 環境構築(任意)
RUN go get github.com/go-delve/delve/cmd/dlv \
github.com/rogpeppe/godef \
golang.org/x/tools/cmd/goimports \
golang.org/x/tools/cmd/gorename \
sourcegraph.com/sqs/goreturns \
github.com/ramya-rao-a/go-outline \
golang.org/x/tools/gopls@latest
- 本番用Dockerfile
FROM golang:1.14.0-alpine3.11 as builder
WORKDIR /go/src/app
COPY ./app ./
ENV GO111MODULE=on
RUN go mod download
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o /go/bin/app
FROM alpine:latest
RUN apk --no-cache add ca-certificates
COPY --from=builder /go/bin/app /go/bin/app
ENTRYPOINT [ "/go/bin/app" ]
EXPOSE 8080
- docker-compose
version: '3.7'
services:
app:
container_name: go-app
build:
context: .
# Remote Containerが立ち上がるまで待機
dockerfile: docker/golang/Dockerfile.dev
ports:
- 8080:8080
volumes:
- ./app:/go/src/app:cached
command: /bin/ash -c "while sleep 1000; do :; done"
2. Remote Containers の設定
インストール
インストールしていない方は、 Remote-Containers からインストールしてください。
準備
まずはじめにVSCode の左下のアイコンをクリックしてください。
すると、コマンドパレッドが開きますので、
Remote-Containers: Add Development Container Configuration Files...
と検索して選択してください。
選択したら、
From 'docker-compose.yml'
を選択してください。
選択後.devcontainer
ディレクトリが作成され、設定ファイルが格納されています。
設定
.devcontainer
├── devcontainer.json
└── docker-compose.yml
まずはじめに、docker-compose.yml はもう作成してあるので、
.devcontainer 内のdocker-compose.yml は削除してください。
下記のコマンドを実行してファイルを削除してください。
$ rm .devcontainer/docker-compose.yml
次にdevcontainer.json を編集します。
{
"name": "go",
"dockerComposeFile": [
"../docker-compose.yml"
],
"service": "app",
"workspaceFolder": "/go/src/app",
"settings": {
"terminal.integrated.shell.linux": "/bin/ash",
"go.gopath": "/go"
},
"extensions": [
"ms-vscode.go",
],
"shutdownAction": "stopCompose"
}
3. ホットリロードの設定
準備
まずはGoアプリを開発する作業ディレクトリを作成します。
その後ホットリロードを行うためのfresh の設定ファイルを作成します。
ちなみに設定ファイルを作成しなくても大丈夫ですのでこちらは任意で!
下記のコマンドを実行してください。
$ mkdir app
$ cd app
# /go-work/app
$ touch .fresh.conf
設定
root: .
tmp_path: ./tmp
build_name: runner-build
build_log: runner-build-errors.log
valid_ext: .go, .tpl, .tmpl, .html
no_rebuild_ext: .tpl, .tmpl, .html
ignored: assets, tmp
build_delay: 600
colors: 1
log_color_main: cyan
log_color_build: yellow
log_color_runner: green
log_color_watcher: magenta
log_color_app:
上記の設定はテンプレートから持ってきています。
細かい設定は任意で!
4. 開発環境の起動
さて、いよいよコンテナを起動します。
VSCode から左下のアイコンをクリックしてください。
すると、コマンドパレッドが開きますので、
Remote-Containers: Reopen in Container
を検索して選択してください。
すると、画面が切り替わります。
この時点でDockerイメージが作成され、コンテナが自動で起動します。
起動するまでしばらく時間がかかりますので待機...
しばらくするとコンテナとリモートで繋がり作業ディレクトリに移ります。
VSCode の左下のアイコンも変わっているはずです。
VSCode 上でターミナルを開くと、コンテナ内のターミナルに切り替わっています。
/go/src/app #
5. 開発環境の動作確認
ここからはコンテナ内で作業していきます。
ホットリロードの動作を確認するためにGo のプログラムを開発していきます。
main.go の作成
開発するためのファイルを作成します。
touch main.go
go mod init main
つづいてmain.go に簡単なWebサーバを作成します。
// ...省略
func init() {
http.HandleFunc("/", index)
}
func index(w http.ResponseWriter, r *http.Request) {
fmt.Fprint(w, "Hello World")
}
func main() {
fmt.Print("Server Start")
if err := http.ListenAndServe(":8080", nil); err != nil {
panic(err)
}
}
実行
main.go を実行するのですが今回はfresh を使って実行します。
VSCode 内のコンテナで実行しても良いのですが、こちらは開発時で利用したいので今回は別ターミナルで実行します。
別ターミナルでコンテナ内に入り、ホットリロードを起動させます。
$ docker exec -it go-app /bin/ash
# コンテナ内: /go/src/app
fresh -c .fresh.conf
main.go が実行されますので確認作業に移ります。
確認
確認は、ブラウザ または、ターミナル で確認します。
- ブラウザの場合は、http://localhost:8080 にアクセス
- ターミナルの場合は、
curl http://localhost:8080
を実行
Hello World
が返ってくれば起動しています。
変更
つづいてホットリロードが正常に起動しているかを確認したいので、
fresh を起動したままVSCode に戻ってください。
VSCode上でmain.go を変更し、保存してください。
func index(w http.ResponseWriter, r *http.Request) {
- fmt.Fprint(w, "Hello World")
+ fmt.Fprint(w, "Hello Golang")
}
保存したら再度、確認作業を行ってください。
Hello Golang
が返ってくればホットリロードは正常に起動しています。
6. 本番環境の起動
本番環境はDockerをビルドして実行すれば良いだけです。
イメージのビルド
$ docker build -t go-app -f ./docker/golang/Dockerfile.dep .
コンテナの実行
$ docker run --name go-app go-app -p 8080:8080 -d . /bin/ash