はじめに
Docker上で動いているGo言語のアプリケーションを、VScodeでリモートデバッグします。
その際に、デバッガツールの delve と、ホットリロードツールの air を使います。
ディレクトリ構成
├── .vscode
│ └── launch.json
├── cmd
│ ├── .air.toml
│ ├── go.mod
│ └── main.go
├── Dockerfile
└── docker-compose.yml
Dockerfile
まず、Dockerで以下の2つをインストールします。
FROM golang:1.17.2
RUN go install github.com/go-delve/delve/cmd/dlv@latest
RUN go install github.com/cosmtrek/air@latest
docker-compose.yml
version: '3.7'
services:
app:
build: .
ports:
- "2345:2345" #delve用のポート
volumes:
- ./:/go/src
working_dir: /go/src/cmd
command: air -c .air.toml
commandでairを実行しています。
(airの設定ファイル.air.toml
の中で、delve実行も設定している)
.air.toml
air_example.toml
こちらをコピペして使いました。
変更ポイントは、cmd
とfull_bin
だけです。
# Config file for [Air](https://github.com/cosmtrek/air) in TOML format
# Working directory
# . or absolute path, please note that the directories following must be under root.
root = "."
tmp_dir = "tmp"
[build]
# Just plain old shell command. You could use `make` as well.
cmd = "go build -gcflags \"all=-N -l\" -o tmp/main ."
# Binary file yields from `cmd`.
bin = "tmp/main"
# Customize binary.
full_bin = "dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec ./tmp/main"
# Watch these filename extensions.
include_ext = ["go", "tpl", "tmpl", "html"]
# Ignore these filename extensions or directories.
exclude_dir = ["assets", "tmp", "vendor", "frontend/node_modules"]
# Watch these directories if you specified.
include_dir = []
# Exclude files.
exclude_file = []
# Exclude specific regular expressions.
exclude_regex = ["_test.go"]
# Exclude unchanged files.
exclude_unchanged = true
# Follow symlink for directories
follow_symlink = true
# This log file places in your tmp_dir.
log = "air.log"
# It's not necessary to trigger build each time file changes if it's too frequent.
delay = 1000 # ms
# Stop running old binary when build errors occur.
stop_on_error = true
# Send Interrupt signal before killing process (windows does not support this feature)
send_interrupt = false
# Delay after sending Interrupt signal
kill_delay = 500 # ms
[log]
# Show log time
time = false
[color]
# Customize each part's color. If no color found, use the raw app log.
main = "magenta"
watcher = "cyan"
build = "yellow"
runner = "green"
[misc]
# Delete tmp directory on exit
clean_on_exit = true
-
cmd
="go build -gcflags \"all=-N -l\" -o tmp/main ."
dlv exec
を使うためには、-gcflags=all='-N -l'
が必要になります。
go build
-gcflags '[pattern=]arg list'
arguments to pass on each go tool compile invocation.
-
full_bin
=
"dlv --listen=:2345 --headless=true --api-version=2 --accept-multiclient exec ./tmp/main"
cf. dlvコマンドのoption詳細
--api-version int Selects API version when headless. New clients should use v2. Can be reset via RPCServer.SetApiVersion. See Documentation/api/json-rpc/README.md. (default 1)
--accept-multiclient Allows a headless server to accept multiple client connections.
.vscode/launch.json
{
"version": "0.2.0",
"configurations": [
{
"name": "Remote",
"type": "go",
"request": "attach",
"mode": "remote",
"remotePath": "/go/src/cmd",
"port": 2345,
"host": "localhost",
"cwd": "${workspaceRoot}/cmd",
"env": {},
"args": [],
}
]
}
-
name
: お好きな名前 -
type
: デバッガーの種別 -
request
: デバッグ時にプログラムを起動するか(launch)、
既に起動しているプログラムにデバッガーをアタッチするか(attach) -
remotePath
: コンテナ内のパス -
port
: dlvのポート -
cwd
: デバッグ実行を行うディレクトリ -
${workspaceRoot}
: VSコードで開いたディレクトリのパス