LoginSignup
7
8

More than 3 years have passed since last update.

Docker, VSCode Remote Container, Air による Go 開発環境構築

Last updated at Posted at 2021-04-18

はじめに

概要

Docker と VSCode Remote Container による Go の Web サーバ開発環境を構築する記事です
ローカルに Go をインストールすることなく、

  • コード補完
  • コード変更があるたびに再ビルド(ライブリロード)

の Go 開発環境を構築します。

リポジトリ

この記事で作成する内容は GitHub に上げています。

背景

業務で Go を触ることとなり、勉強するにあたって手軽な Go の開発環境の構築方法を調べていました。
Docker を使った Go の開発環境を構築する方法はいくつか情報があったのですが、コード補完やフォーマッタを効かせるために結局ローカルに Go をインストールする必要があり、少し微妙でした。
また、簡単な Web サーバを書いていたのですが、ソースコードを修正するたびにいちいちビルドし直すのが面倒でした。

色々と試している中で、

で解決できることが分かり、本記事はその成果物です。

できるだけ手軽に、Go の Web サーバ開発環境を整えたい人向けの記事となっています。

開発環境の構築

動作環境

ディレクトリ構造

.
|
├── .devcontaier/
|      └── devcontainer.json
├── .air.toml
├── docker-compose.yml
└── Dockerfile

コンテナ設定

Dockerfile
FROM golang:1.16.3-alpine

ENV GO111MODULE on

WORKDIR /go/src/app

RUN apk update \
  && apk add git \
  && go install github.com/cosmtrek/air@latest \
  && go get -u golang.org/x/tools/gopls \
  github.com/ramya-rao-a/go-outline

ここでは、Go 拡張機能で使用する ranguage server に必要な gopls や、ライブリロードに必要な Air のバイナリインストール&ビルドを行っています。

docker-compose.yml
version: "3.8"

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile
    command: "air"
    tty: true
    stdin_open: true
    command: "air"
    volumes:
      - ./app:/go/src/app
    ports:
      - 8080:8080
    security_opt:
      - apparmor:unconfined
    cap_add:
      - SYS_PTRACE

ライブリロード設定

.air.toml で、ライブリロードの設定を行います。
今回は、公式のサンプルコードをそのまま拝借して使用します。

コンテナ接続設定

VSCode Remote Container 用の設定をします。

.devcontainer/.devcontainer.json
{
	"name": "Go-Practice",
	"dockerComposeFile": [
		"../docker-compose.yml",
	],
	"service": "web",
	"workspaceFolder": "/go/src/app",
	"settings": {
		"terminal.integrated.shell.linux": "/bin/ash",
		"go.toolsManagement.checkForUpdates": "off",
		"go.gopath": "/go",
		"go.gocodeAutoBuild": true,
		"go.formatTool": "gofmt",
		"go.useLanguageServer": true,
		"editor.formatOnSave": false,
		"[go]": {
			"editor.formatOnSave": true
		}
	},
	"extensions": [
		"golang.go"
	],
}

extensionsの部分で、ワークスペースに任意の VSCode 拡張をインストールすることができます。今回は、最低限の設定として Go の VSCode 拡張を入れています。

他にも、今回は軽量なalpineイメージを使用するので、

"terminal.integrated.shell.linux": "/bin/ash",

の部分でワークスペースで使用するシェルにashを指定しています。
alpineでもbashを使いたい方は、イメージビルド時に bash を入れたりするなど、適宜カスタマイズしてください。

開発環境の起動

Docker イメージのビルド

docker-compoase build

コンテナの立ち上げ

docker-compose up -d

docker-compose logs -f web でコンテナのログを見ると、ライブリロードのairが立ち上がっていることがわかります。

web_1  |   __    _   ___
web_1  |  / /\  | | | |_)
web_1  | /_/--\ |_| |_| \_  // live reload for Go apps, with Go
web_1  |

開発コンテナ接続

Remote Container でコンテナに接続する方法はいくつかあります。以下のうちどれかを行います。(どれでもいい)

以下、全て VSCode での作業

  • [Cmd + Shift + P] > [reopen in container]を選択

  • VSCode の左下にある >< を押す > [reopen in container]を選択

  • 左側のアイコン(Remote Explerer) > Containers > 該当のコンテナを選択
    Screenshot 2021-04-18 10.34.49.png
    Docker のコンテナ内で、VSCode を開くことができました。

コーディングしてみる

Go コンテナの中に入ることができたので、とりあえず Gin で Web サーバーを立てて動作を確認します。

パッケージのインストール

ash
go mod init プロジェクト名

で go.mod を作成したら、

ash
go get -u github.com/gin-gonic/gin

ginをインストール。

サーバー立ち上げ

ash
touch main.go
main.go
package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

動作確認

localhost:8080/ping

{ "message": "pong" }

ちゃんと動いてそうです。

ライブリロードの確認

コードを少し変更してみます。

main.go
package main

import "github.com/gin-gonic/gin"

func main() {
	r := gin.Default()
	r.GET("/ping", func(c *gin.Context) {
		c.JSON(200, gin.H{
			"message": "pong",
		})
	})
+    r.GET("/hoge", func(c *gin.Context) {
+      c.JSON(200, gin.H{
+           "message": "fuga",
+       })
+    })
	r.Run() // listen and serve on 0.0.0.0:8080 (for windows "localhost:8080")
}

再度動作確認

web_1  | main.go has changed
web_1  | building...
web_1  | running...
web_1  | [GIN-debug] GET    /ping                     --> main.main.func1 (3 handlers)
web_1  | [GIN-debug] GET    /hoge                     --> main.main.func2 (3 handlers)

localhost:8080/hoge

{ "message": "fuga" }

ちゃんと変更が反映されていることがわかります。

おわりに

手軽な Go の開発環境構築として、Docker・Air・VSCode Remote Container を使用する方法を紹介させていただきました。

DB コンテナも使いたい」となったらdocker-compose.ymlに DB コンテナの記述を加えたり、「もっといろいろワークスペースをカスタマイズしたい」となったら拡張機能をワークスペースに入れたりなど、色々と柔軟に拡張できると思います。

最後に、メリットデメリットをまとめておきます。

本記事で紹介する環境のメリット/デメリット

メリット

  • Docker, VSCode があれば作れる
  • ローカルに Go をインストールせずに、コード補完等のサポートが効く
  • コードを変更すると、自動でソースコードをリビルドしてくれる
  • docker コマンドをいちいち流さなくても良い

デメリット

  • git 管理の構成を考えるのが難しい
  • 1 コンテナにつき開ける VSCode のウィンドウが一つ
  • 何らかのポートを開けっぱなしにするとき、VSCode のデバッグが使えない

メリットもある一方、デメリットも多くあるなぁと筆者自身感じています。特にデバッグ構成については、Web サーバの開発であればライブリロードと相性が悪いです。


(以下、デバッグと Air が共存できない例)

  1. 変更があるたびにソースコードがビルドされ、ポート:8080で Gin の Web サーバが立ち上がっている。
  2. ここで、VSCode でデバッグを行うと、デバッグのためにソースコードがビルドされる。
  3. デバッグでのビルド時、同じくポート:8080で Gin をサーバを立ち上げようとするため、ポートの競合が発生し、デバッグモードにできない。

こちらについては、未だベストな解決方法が思いついておりません。結局、ライブリロードをやめてデバッグモードでの開発が良いのかなと思っています。

以上のメリット・デメリットを踏まえた上で、今回の環境構築を試していただければと思います。

もっと良い方法があるよ!等ありましたら、是非教えていただきたいです 🙇‍♂️

参考資料

7
8
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
8