Help us understand the problem. What is going on with this article?

Docker + VSCodeでGoの環境構築(ホットリロード対応)

はじめに

個人開発で最近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 を使用します。

手順

  1. Dockerfile(開発用&本番用) + docker-compose.yml の作成
  2. Remote Containers の設定
  3. ホットリロードの設定
  4. 開発環境の起動
  5. 開発環境の動作確認
  6. 本番環境の起動

開発環境

はじめに作業ディレクトリを作ります。

/
# 作業ディレクトリ作成
$ mkdir go-work
# 作業ディレクトリへ移動
$ cd go-work

1. Dockerfile(開発用&本番用) + docker-compose.yml の作成

続いてDockerfiledocker-compose.yml を書いていきます。
下記コマンドからファイルを作成してください。

/go-work
$ touch docker-compose.yml
$ mkdir -p docker/golang
$ touch docker/golang/Dockerfile.dev
$ touch docker/golang/Dockerfile.dep

※ Dockerfileの言語サポート

Dockerfile.dev(.dep) はVSCodeの標準では言語サポートされていないので設定を追加します。
設定されている方は次へ飛ばしてください。

  1. [Code] -> [基本設定] -> [設定]
  2. Files: Associations で検索
  3. settings.json で編集
settings.json
{
  "files.associations": { 
    "Dockerfile.dev": "dockerfile",
    "Dockerfile.dep": "dockerfile"
  }
}

Docker + docker-composeの設定

  • 開発用Dockerfile
/go-work/docker/golang/Dockerfile.dev
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
/go-work/docker/golang/Dockerfile.dep
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
/go-work/docker-compose.yml
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 の左下のアイコンをクリックしてください。
01-icon.png
すると、コマンドパレッドが開きますので、
Remote-Containers: Add Development Container Configuration Files...
と検索して選択してください。

02-remote-containers.png

選択したら、
From 'docker-compose.yml'
を選択してください。

03-remote-containers.png

選択後.devcontainer ディレクトリが作成され、設定ファイルが格納されています。

設定

.devcontainer
    ├── devcontainer.json
    └── docker-compose.yml

まずはじめに、docker-compose.yml はもう作成してあるので、
.devcontainer 内のdocker-compose.yml は削除してください。

下記のコマンドを実行してファイルを削除してください。

/go-work
$ rm .devcontainer/docker-compose.yml

次にdevcontainer.json を編集します。

/go-work/.devcontainer/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 の設定ファイルを作成します。

ちなみに設定ファイルを作成しなくても大丈夫ですのでこちらは任意で!

下記のコマンドを実行してください。

/go-work
$ mkdir app
$ cd app
# /go-work/app
$ touch .fresh.conf

設定

/go-work/app/.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 から左下のアイコンをクリックしてください。

01-icon.png

すると、コマンドパレッドが開きますので、
Remote-Containers: Reopen in Container
を検索して選択してください。

04-remote-containers.png

すると、画面が切り替わります。
この時点でDockerイメージが作成され、コンテナが自動で起動します。
起動するまでしばらく時間がかかりますので待機...

しばらくするとコンテナとリモートで繋がり作業ディレクトリに移ります。

05-remote-containers.png

VSCode の左下のアイコンも変わっているはずです。
VSCode 上でターミナルを開くと、コンテナ内のターミナルに切り替わっています。

コンテナ内
/go/src/app #

5. 開発環境の動作確認

ここからはコンテナ内で作業していきます。
ホットリロードの動作を確認するためにGo のプログラムを開発していきます。

main.go の作成

開発するためのファイルを作成します。

/go/src/app
touch main.go
go mod init main

つづいてmain.go に簡単なWebサーバを作成します。

/go/src/app/main.go
// ...省略
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 を変更し、保存してください。

/go/src/app/main.go
func index(w http.ResponseWriter, r *http.Request) {
  - fmt.Fprint(w, "Hello World")
  + fmt.Fprint(w, "Hello Golang")
}

保存したら再度、確認作業を行ってください。
Hello Golang が返ってくればホットリロードは正常に起動しています。

6. 本番環境の起動

本番環境はDockerをビルドして実行すれば良いだけです。

イメージのビルド

/go-work
$ docker build -t go-app -f ./docker/golang/Dockerfile.dep .

コンテナの実行

/go-work
$ docker run --name go-app go-app -p 8080:8080 -d . /bin/ash
S-Masakatsu
現在は、情報系専門学生として活動しています。 今春からWEB系エンジニアとして勤務します。 普段はサーバサイドメインでやっていますが、学生最後の制作でフロントを担当しました。
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away