概要
Golandを使ってコーディングしている時に、Dockerで立ち上げたwebアプリケーションをデバッグしたいと思い、リモートデバッグができるdelveを導入することにした。
DockerではAPIサーバとMySQLを動かしている。
compose_dev.yaml
デバッグ用とデバッグなしで動かす用の2つを使い分けたいので、compose_dev.yamlとしている。
compose_dev.yamlは以下の通りにした。
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- '8080:8080'
- '2345:2345'
volumes:
- '.:/go/src'
depends_on:
- 'db'
tty:
true
db:
image: 'mysql:8.0'
ports:
- '3306:3306'
volumes:
- './tmp/mysql:/var/lib/mysql'
- portsはAPI用の8080とリモートデバッグ接続用の2345の2つを開けている。
- dockerfileでDockerfile.devを指定している。
Dockerfile.dev
Dockerfile.devは以下の通りにした。
FROM golang:1.20 as builder
WORKDIR /go/src
RUN go install github.com/cosmtrek/air@latest
RUN go install github.com/go-delve/delve/cmd/dlv@latest
ENV GO111MODULE=on
COPY go.mod go.sum ./
RUN go mod download
ENV DOTENV_PATH=/go/src/.env
COPY .air.toml ./
CMD ["air"]
- airとdelveの最新版をインストールしている
- .air.tomlを指定してairを実行する
- 開発で.envファイルを使用しているので
ENV DOTENV_PATH=/go/src/.env
でパス指定しているが、人によるため必須ではない
.air.toml
.air.tomlは以下の通りにした。
root = "."
tmp_dir = "tmp"
[build]
cmd = "dlv debug --headless --listen=:2345 --api-version=2 --log"
bin = "tmp/main"
include_ext = ["go", "tpl", "tmpl", "html"]
exclude_dir = ["assets", "tmp", "vendor", "testdata"]
exclude_file = []
exclude_regex = []
include_dir = []
kill_delay = "1000ms"
stop_on_error = true
send_interrupt = true
log = "build-errors.log"
[color]
app = ""
build = "yellow"
runner = "green"
[log]
time = false
level = "debug"
この設定では、Airがソースコードの変更を検知すると、dlv debug
コマンドを使用してアプリケーションをデバッグモードで再起動する。Delveのデバッグサーバーはポート2345でリッスンし、IDEなどの外部ツールから接続可能になっている。
Golandの設定
- golandの右上から
Edit COnfiguration
を選択する。 -
+
ボタンからGo Remoteを選択する。 - Hostはlocalhost, Portは2345を指定する。
-
Ask
にチェックを入れて保存する。
デバッグの実行
この設定でdocker-compose -f compose_dev.yaml up --build
をするとターミナルに以下のようなログが表示される。
app | API server listening at: [::]:2345
app | 2023-11-28T02:50:45Z warning layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)
app | 2023-11-28T02:50:46Z debug layer=debugger Adding target 126 "/go/src/__debug_bin2673177628"
この状態で、ブレイクポイントを適当に配置し、Golandのデバッグを実行する。以下のような画面になると成功である。
(補足).air.tomlを指定しない通常の実行方法を共存させる方法
delveを使わない場合は.air.tomlを使わないこともあると思うので、通常時に.air.tomlを無視する方法について説明する。
まず、compose.yamlを以下のようにする。
version: '3'
services:
app:
build:
context: .
dockerfile: Dockerfile
ports:
- '8080:8080'
volumes:
- '.:/go/src'
depends_on:
- 'db'
tty:
true
db:
image: 'mysql:8.0'
ports:
- '3306:3306'
volumes:
- './tmp/mysql:/var/lib/mysql'
上で解説したcompose_dev.yamlと違う点は指定しているdockerfileだけである。
次にDockerfileの内容を以下のようにする。
FROM golang:1.20 as builder
WORKDIR /go/src
RUN go install github.com/cosmtrek/air@latest
ENV GO111MODULE=on
COPY go.mod go.sum ./
RUN go mod download
ENV DOTENV_PATH=/go/src/.env
CMD ["air", "-c", "empty.air.toml"]
コマンドにair -c empty.air.toml
としている。これで後述する空のtomlファイルを指定している。
そして、empty.air.tomlというファイルを作成し、内容は空で保存する。
これでdocker-compose up --build
とすれば、airだけが効いたDockerを立ち上げることができる。