54
41

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

スタートトゥデイ工務店Advent Calendar 2016

Day 12

Docker+GolangをVisualStudioCodeでリモートデバッグする

Posted at

#はじめに
DockerにGolangの環境を閉じ込めたときデバッグどうするの?と思ってなかなか情報を集められなかったのでまとめます。

##検証環境

ホスト側
  • Windows10 + Boot2Docker + VisualStudioCode
  • Sierra + Docker for Mac + VisualStudioCode
コンテナ側
  • golang:onbuildを使用(執筆時点ではgolang 1.7)

#Golangのデバッガについて
VisualStudioCodeではDelveを使うようなので、Delveを使います。
ドキュメントやissuse見てるとリモートデバッグもサポートしていて、もしかしてDockerもいけるかもってところが発端。

#Dockerのリモートデバッグについて
リモートデバッグが可能なようで、こちらをベースにGolang用に書き換えます。
Live Debugging With Docker

#用意したファイル
$GOPATH/src/github.com/user
|--.vscode
|  launch.json
|--docker-compose.yml
|--Dockerfile
|--main.go

main.go
// main.go
package main

import (
	"fmt"
	"log"
	"net/http"

	"github.com/garyburd/redigo/redis"
)

func main() {
	redi, err := redis.Dial("tcp", "redis:6379")
	if err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		res, err := redi.Do("incr", "counter")
		if err != nil {
			w.WriteHeader(500)
			w.Write([]byte(err.Error()))
			return
		}

		if res, ok := res.(int64); ok {
			w.Write([]byte(fmt.Sprintf("counter: %d", res)))
		} else {
			w.WriteHeader(500)
			w.Write([]byte("unexpected value"))
		}
	})
	log.Fatal(http.ListenAndServe(":5000", nil))
}
Dockerfile
# Dockerfile
FROM golang:onbuild
RUN go get github.com/derekparker/delve/cmd/dlv
docker-compose.yml
# docker-compose.yml
app:
  build: .
  ports:
    - "5000:5000" #golang webserver用のポート
    - "5050:5050" #delve用のポート
  links:
    - redis
  volumes:
    - ".:/go/src/app"
  privileged: true # Delveで必要なので付与します。セキュリティ面から本番環境では使うべきではありません。 
  command: dlv debug --headless --listen=:5050 --log 

redis:
  image: redis
launch.json
{
    "version": "0.2.0",
    "configurations": [
         {
            "name": "Remote",
            "type": "go",
            "request": "launch",
            "mode": "remote",
            "remotePath": "/go/src/app", //コンテナ内のパス
            "port": 5050, // dlv debugのポートを指定(WEBのポートではない)
            "host": "192.168.99.100", //左の設定はToolBoxを使った場合のDocker MachineのIP. for Macの場合はlocalhostでよかった.
            "program": "${workspaceRoot}", //${workspaceRoot} = $GOPATH/src/github.com/user
            "env": {},
            "args": [],
            "showLog": true
        }
    ]
}

main.goはこちらの記事を参考にしています。
redisを使って数字をインクリメントして表示するシンプルな処理。
参考)Dockerを使ったGolang開発環境

#リモートデバッグを行う
##コンテナを起動する
main.goのカレントでコンテナをビルドして、起動

> docker-compose build
redis uses an image, skipping
Building app
Step 1 : FROM golang:onbuild
# Executing 3 build triggers...
Step 1 : COPY . /go/src/app
Step 1 : RUN go-wrapper download
 ---> Running in ff0ae2dae819
+ exec go get -v -d
github.com/garyburd/redigo (download)
Step 1 : RUN go-wrapper install
 ---> Running in d778a728a336
+ exec go install -v
github.com/garyburd/redigo/internal
github.com/garyburd/redigo/redis
app
 ---> 0b0ffd816054
Removing intermediate container ff0ae2dae819
Removing intermediate container d778a728a336
Removing intermediate container 677062574a96
Step 2 : RUN go get github.com/pilu/fresh
 ---> Running in 06b38d625b20
 ---> 3bc412d615be
Removing intermediate container 06b38d625b20
Step 3 : RUN go get github.com/derekparker/delve/cmd/dlv
 ---> Running in 10b51b638607
 ---> 206e4fb5f2c0
Removing intermediate container 10b51b638607
Successfully built 206e4fb5f2c0
> docker-compose up -d
> docker-compose ps
      Name                    Command               State                       Ports

----------------------------------------------------------------------------------------------------------
user_app_1     dlv debug --headless --lis ...   Up      0.0.0.0:5000->5000/tcp, 0.0.0.0:5050->5050/tcp
user_redis_1   docker-entrypoint.sh redis ...   Up      6379/tcp

コンテナが二つ立ち上がってればオッケーです。

##VisualStudioCodeでデバッグを開始する
ミソはVisualStudioCodeからコンテナ内のコードを起動することらしい。
まずはVisualStudioCodeのデバッグビューを開いて、ブレークしたいコードにブレークポイントを置いておきます。

image

そんで左上のデバッグをRemoteにして実行。
※うまくいくと下のバーがオレンジになる。

image

この状態になれば、コンテナ内のmain.goが起動されているので、ブラウザでIPを叩く。(docker-machineのIPかlocalhostでいけるはず)
ブレークポイントを置いた場所にブレークするようになります。

image

あとは通常のデバッグと同じく、好きなようにデバッグできますね。

#解決できていない問題点
リモートデバッグはできるようになったものの以下の問題点があって、まだ使いづらさあります。

  1. 実行中にブレークポイントの付け替えができない
  2. リモートデバッグを停止したのち再度実行するとデバッガがハングアップする
  3. DockerのprivilegedをTrueにする必要があってよろしくない

1.に関しては再起動やホットデプロイを仕込めばいけそうですが、
2.はVSCode上で停止しても新しくリモートデバッグが開始できず、結局コンテナの再起動が必要になっています。(コンテナ内にプロセスが残りっぱなしになるのがだめっぽい。killもできない。)
3. はDelveで必要な権限がわからず、全権限渡してますが、セキュリティ的によくないですね。開発環境だけにするとかの対処が必要そうです。

何かいい方法はないでしょうか・・・

#さいごに
VisualStudioCodeとGolangの相性はとてもよく、エディタでありながら、IDEのように使えるし、とても使いやすいです。
Dockerを使った開発手法を確立させて、効率を上げていきたいですね。

54
41
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
54
41

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?