ilbets
ilbets

Reputation: 768

Ho to debug Go app with DLV and MODD on Docker

I'm running a Go app on the Docker and want to use VSCode to debug it via DLV at the same time using MODD for app rebuild. So far I cannot figure out how to connect to the debugger.

Docker:

FROM golang:1.18 as dev
WORKDIR /root
RUN GO111MODULE=on go install github.com/cortesi/modd/cmd/modd@latest
RUN go install github.com/go-delve/delve/cmd/dlv@latest
COPY . .
CMD modd

MODD:

**/*.go !**/*_test.go {
    prep: go build -o app main.go
    prep: dlv exec --headless --continue --listen localhost:2345 --accept-multiclient ./app
    daemon +sigterm: ./app
}

DOCKER_COMPOSE (expose port):

ports:
      - "5000:5000"
      - "2345:2345"

VSCode configuration:

{
        "name": "Connect to Go server",
        "type": "go",
        "request": "attach",
        "mode": "remote",
        "remotePath": "${workspaceFolder}",
        "port": 2345,
        "host": "127.0.0.1",
    }

Q: How to make DLV work on Docker with MODD?

Thanks!

Upvotes: 7

Views: 1317

Answers (1)

natenho
natenho

Reputation: 5611

Well, afaik it is not trivial to do what you want, because you have to watch files being changed in your host to trigger dlv inside the container, messing up with vscode's ongoing debug session.

Here is hacky way to setup vscode to debug app in container and use modd to restart debug inside the container on file change.

(Make sure you have modd installed in your host machine)

dlv+docker+modd

.vscode/launch.json

 {
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug",
            "type": "go",
            "request": "attach",
            "mode": "remote",
            "remotePath": "/root",
            "port": 2345,
            "host": "127.0.0.1",
            "trace": "verbose",
            "preLaunchTask": "setup docker debug",
            "postDebugTask": "teardown docker debug"
        }
    ]
 }

.vscode/tasks.json - This file will instruct vscode to run your container via docker compose and to run modd in background

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "setup docker debug",
            "dependsOn": [               
                "show app console"                
            ]
        },
        {
            "label": "teardown docker debug",
            "dependsOrder": "sequence",
            "dependsOn": [
                "stop all containers"
            ]
        },
        {
            "label": "show app console",
            "command": "docker logs app --follow",
            "type": "shell",
            "isBackground": true,
            "presentation": {
                "reveal": "always",
                "panel": "dedicated",
                "clear": true,
                "showReuseMessage": true
            },
            "problemMatcher": [
                {
                    "pattern": [
                        {
                            "regexp": ".",
                            "file": 1,
                            "location": 2,
                            "message": 3
                        }
                    ],
                    "background": {
                        "activeOnStart": true,
                        "beginsPattern": ".",
                        "endsPattern": ".",
                    }
                }
            ],
            "dependsOn":[
                "start all containers",
                "modd"
            ]
        },
        {
            "label": "start all containers",
            "type": "shell",
            "command": "docker-compose up --build --force-recreate --detach",
            "presentation": {
                "reveal": "always",
                "panel": "shared",
                "clear": true,
                "showReuseMessage": true
            },
            "dependsOn":[
                "stop all containers"
            ]
        },
        {
            "label": "stop all containers",
            "type": "shell",
            "command": "docker-compose down",
            "presentation": {
                "panel": "shared",
                "clear": true
            },
        },
        {
            "label": "modd",
            "type": "shell",
            "isBackground": true,
            "command": "modd",
            "presentation": {
                "panel": "new", 
                "clear": true
            },
            "problemMatcher": [
                {
                    "pattern": [
                        {
                            "regexp": ".",
                            "file": 1,
                            "location": 2,
                            "message": 3
                        }
                    ],
                    "background": {
                        "activeOnStart": true,
                        "beginsPattern": ".",
                        "endsPattern": ".",
                    }
                }
            ],
        }
    ]
}

docker-compose.yml

version: "3.8"
services:
  app:
    container_name: app
    build:
      context: .
    restart: on-failure
    ports:
      - 5000:5000
      - 2345:2345
    security_opt:
      - apparmor=unconfined
    cap_add:
      - SYS_PTRACE

Dockerfile

FROM golang
WORKDIR /root
RUN go install github.com/go-delve/delve/cmd/dlv@latest
COPY . .
ENTRYPOINT dlv --listen=:2345 --api-version=2 --headless --accept-multiclient debug .

dlv.txt - This file will be used to call dlv to rebuild and continue

rebuild
continue

modd.conf - modd will copy all files back to the container and issue a rebuild and continue command to the running dlv

**/*.go !**/*_test.go {
    prep +onchange: docker cp ./ app:/root/
    prep +onchange: timeout 1 dlv connect localhost:2345 --init dlv.txt
}

You'll be able to set breakpoints and everything, but you'll notice that sometimes you'll need to manually pause and continue to recover the debugging session.

Upvotes: 1

Related Questions