run container using remote debug
The best known remote debugger for Golang apps is Delve. Is is also suitable for running in Docker containers. So, we can build a new container, for example, as described:
Dockerfile-1.12
FROM golang:1.12-alpine
ENV CGO_ENABLED 0
RUN apk update \
&& apk add --no-cache dep bash mc git build-base libc6-compat vim \
&& mkdir /.cache \
&& chmod -R a+rw /.cache \
&& go get -u github.com/go-delve/delve/cmd/dlv \
&& mkdir -p ~/.config/dlv \
&& echo "aliases: {}" > ~/.config/dlv/config.yml \
&& echo "substitute-path: []" >> ~/.config/dlv/config.yml \
&& echo "max-string-len: 2048" >> ~/.config/dlv/config.yml \
&& echo "max-array-values: 512" >> ~/.config/dlv/config.yml \
&& echo "max-variable-recurse: 128" >> ~/.config/dlv/config.yml \
&& echo "show-location-expr: false" >> ~/.config/dlv/config.yml \
&& echo "source-list-line-color: 34" >> ~/.config/dlv/config.yml \
&& echo "debug-info-directories:" >> ~/.config/dlv/config.yml \
&& echo " - /usr/lib/debug/.build-id" >> ~/.config/dlv/config.yml
You can replace 1.12 to 1.13 in your Dockerfile name and content to use Go 1.13, for example. This allows you to easily switch between different Golang versions at the same machine.
The ~/.config/dlv/config.yml is a Delve’s configuration file. Here we try to avoid some known restrictions of Delve, for example, max-string-len: 4096 changes the maximum string length, used for evaluating string variables, to 4096 bytes; by default this limit is 64 bytes which is too short.
Also, here we install dep for some projects using dep. You don’t need to use it if you use other package managers, for example, vgo. The /.cache dir is created only for dep’s working, you can remove the instruction to create && chmod this folder if you don’t need dep.
To Build container, run the following standard command:
docker build -t go-debug:1.12 -f Dockerfile-1.12 .
Again, it’s better to tag container version by Golang version used inside to easily switch between versions
To RUN container execute the following command:
docker container run -v $GOPATH/src:/go/src --rm -p 8081:8081 -p 40000:40000 --security-opt="apparmor=unconfined" --cap-add=SYS_PTRACE --name go12 -it go-debug:1.12 /bin/sh
Here we assigned the name go12 to our container. It allows us to easily operate with our running container. Mind that you should bind your code in the volume (-v
parameter) and forward needed ports (-p
parameters) while running your container. More info here.
Also, forward the port 40000 for Delve headless mode -p "40000:40000"
and add --security-opt=apparmor=unconfined" --cap-add=SYSPTRACE
to be able to debug.
To run command without debug - do the same as usual, just run it in container:
cd $GOPATH/src/your_project/
go run main.go
or, quickly run from the outside:
docker exec -it go12 /bin/sh -c "cd src/your_project && go run main1.go"
docker exec -it go12 /bin/sh -c "cd src/your_project && go run main2.go"
docker exec -it go12 /bin/sh -c "cd src/your_another_project && go run main.go"
To run command with debug use Delve to build and run or only to run your application.
- add debug configuration to Goland:
cd $GOPATH/src/your_project/
dlv --listen=:40000 --headless=true --api-version=2 --accept-multiclient debug ./main.go
- After running click on “start debug” button in Golang
- Add breakpoints to your code
- if you can’t kill your process after debug by Ctrl+C, just kill container from host system:
docker rm -f go12
For frequent debugging without editing code, you can build your project once: replace this one command
dlv --listen=:40000 --headless=true --api-version=2 --accept-multiclient debug ./main.go
to this two ones:
go build -gcflags "all=-N -l" -o main main.go;
dlv --listen=:40000 --headless=true --api-version=2 --accept-multiclient exec ./main
Here we build our project only once and then run the binary under debugging.
more info
- https://github.com/go-delve/delve
- https://blog.jetbrains.com/go/2018/04/30/debugging-containerized-go-applications/
- https://blog.jetbrains.com/go/2019/02/06/debugging-with-goland-getting-started/
short strings/array in debug eval/console
By default, Delve uses restrictions for variable evaluation. For example, string length is limited by 64 bytes and longer strings will be shown truncated. To override the limitation, we add config file while container builds,
delve exec ./main
config -list
config max-string-len 4096
config -save