LoginSignup
6

More than 1 year has passed since last update.

goland + air + delveでdocker環境のリモートデバッグ

Last updated at Posted at 2022-12-19

こんにちは、トレタでサーバーサイドエンジニアをしている神山と申します。

こちらはトレタアドベントカレンダー12日目の記事です。
この記事ではdocker-compose環境におけるgolangのリモートデバッグについて記載したいと思います。

概要

docker-composeを使ってgolangの環境を構築し、そこでapplicationを動作させています。
既にairのホットリロードにより差分をすぐ反映することができるため、そこまで気にせず開発を進めていました。
ですがサービスのコード量や複雑な要件が増えるにつれて、デバッグが徐々に辛くなってきました。
そこでデバッグできるようにdelveを導入してみました。

環境

  • MacBook Pro(Apple M1)
  • go version go1.19.4 linux/arm64
  • Docker Compose version v2.13.0
  • air v1.40.4
  • delve v1.20.1

docker-compose.yml

docker-composeファイルはこのように書きました。

version: '3.7'

services:
  app:
    image: 'golang:1.19'
    working_dir: '/app'
    volumes:
      - type: bind
        source: '.'
        target: '/app'
    ports:
      - '8080:8080'
      - '2345:2345'
    command: >
      sh -c '
        go install github.com/go-delve/delve/cmd/dlv@latest
        go install github.com/cosmtrek/air@latest
        air -c .air.toml
      '
  • imageはそのままgolangの1.19を指定しています。
  • working_dirにソースコードをbindしています。
  • portsは二箇所開けています。
    • api用の8080
    • リモートデバッグ接続用の2345
  • commandでdocker-composeをbuildするタイミングでdelveとairををinstall、airを起動するようにしています。
    • 本記事では触れませんが、本番環境用に別でDockerfileを用意しています。
    • 本番環境ではdelve, airともにinstallしたくないのでここに記載する形にしました。

.air.toml

airを使っている場合、tomlファイルを作成しているかと思います。
編集したのは下記に記載の部分です。他は変えていません。

[build]
# Just plain old shell command. You could use `make` as well.
cmd = "go build -gcflags \"all=-N -l\" -o ./.air/main ./cmd/main.go"
# Binary file yields from `cmd`.
bin = "./.air/main"
# Customize binary.
full_bin = "APP_ENV=dev APP_USER=air dlv exec ./.air/main --headless=true --listen=:2345 --api-version=2 --accept-multiclient"
  • cmdでは、./cmd/main.goをbuildして、./.air/mainにバイナリを配置しています。
  • binでは、あらためてバイナリの位置を記載しています。
  • full_binでは、airコマンドを使ってdelve用のserverを起動します。

この状態でdocker-compose upをするとターミナルに下記のようなログが表示されるはずです。

app  | API server listening at: [::]:2345
app  | 2022-12-19T10:16:59Z warning layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)

リモートデバッグの接続

  • golandの右上からEdit Configurationを選択します。
  • +ボタンからGo Remoteを選択してください。
  • Nameは適当な名前を入れてください。
  • Hostはlocalhost, Portは2345を指定してください。
  • Leave it runnningにチェックを入れて保存してください。

スクリーンショット 2022-12-19 19.24.58.png

  • 下記のような表示になっているはずなので、デバッグマークを押してください。

スクリーンショット 2022-12-19 19.27.34.png

  • 問題なければ下記のようにConnectedが表示されるはずです。

スクリーンショット 2022-12-19 19.28.45.png

デバッグを試してみる

本番のソースコードとは全く違うのですが、こんなmain関数を用意しました。
GET http://localhost:8080/helloでアクセスするとレスポンスが返ってくるだけです。

package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/hello", helloHandler)
	http.ListenAndServe(":8080", nil)
}

func helloHandler(w http.ResponseWriter, r *http.Request) {
	test := "Hello Remote Debug!!"
	fmt.Fprint(w, test)
}

実際にブレイクポイントを置いてAPIを叩いてみます。
下部のデバッグコンソールで、testの変数値などが見えているかと思います。
ソースコードを変更して保存すれば、ホットリロードも有効になっています。

スクリーンショット 2022-12-19 19.31.27.png

注意点

どうやらM1 Macでplatformにlinux/amd64を指定したdocker環境ではdelveは使えないようです。
どういうことかというと、docker-compose.ymlを下記のように書き換えました。
golang1.19linux/amd64に対応していないimageのようだったので、golang:1.19-busterに書き換えています。

version: '3.7'

services:
  app:
+   platform: 'linux/amd64'
+   image: 'golang:1.19-buster'
-   image: 'golang:1.19'
    working_dir: '/app'
    volumes:
      - type: bind
        source: '.'
        target: '/app'
    ports:
      - '8080:8080'
      - '2345:2345'
    command: >
      sh -c '
        go install github.com/go-delve/delve/cmd/dlv@latest
        go install github.com/cosmtrek/air@latest
        air -c .air.toml
      '

他の設定は全てそのままにdocker-compose upを実行します。
起動はできるものの could not launch process: fork/exec /app/.air/main: function not implementedと言われてしまいました。

app  | API server listening at: [::]:2345
app  | 2022-12-19T10:37:43Z warning layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)
app  | could not launch process: fork/exec /app/.air/main: function not implemented

delveのissueを調べてみたらありました。
https://github.com/go-delve/delve/issues/2910

Nothing we can do anything about.

コメントのラリーもなくcloseされていました・・。無慈悲。

さいごに

やや中途半端ですが、delveを入れてリモートデバッグを実現しました。
本番環境のDockerfileではlinux/amd64golang:1.19-busterを使用しているので、このデバッグ環境100%信用して使うべきではないと思っています。
とはいえ、例えばチームメンバーからレビューが上がってきたときや複雑なロジックを書くときなどはデバッグがないと辛い・・・
そんな時は少しだけdocker-compose.ymlと.air.tomlを書き換えるだけでリモートデバッグ環境を構築することができるので、重宝しています。

特にgolangはfor文など愚直に書くことが多い言語なので、開発体験を整備すると効率があがりますね。。

なお、トレタではエンジニアの募集を行なっております。
興味がある方はぜひご連絡ください。

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
6