LoginSignup
1

airとdelveを共存させたままコンテナ内で動くGoのWebアプリケーションをデバッグする方法

Last updated at Posted at 2023-11-28

概要

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にチェックを入れて保存する。

スクリーンショット 2023-11-28 11.49.00.png

デバッグの実行

この設定で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のデバッグを実行する。以下のような画面になると成功である。

スクリーンショット 2023-11-28 11.55.32.png

(補足).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を立ち上げることができる。

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
1