Andrii's blog Blog about programming

Debugging a Go Application Inside a Multi Stage Docker Container

Let’s imagine that you have a microservice on sale, each of which lives in its own Dockerfile and naturally, like all adult uncles, this is a multi-stage Dockerfile. More details about multi-stage can be found in the docks (, if laziness is just a Dockerfile which has 2 FROM keywords and in we that copy it from one layer to another.

So let’s go 🐎:

docker build -t goapp:latest .
Sending build context to Docker daemon 22.53kB
Step 1/7 : FROM golang AS builder
Successfully tagged goapp:latest

Every day we need to develop and debug this application: an attentive reader might suggest installing a debugger inside one of the layers. So let’s add something like:

--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,5 @@
FROM golang AS builder
+RUN go get -u
ADD . /src
RUN cd /src && go build -o goapp

And then we run something like this:

➜ debug-multi-stage-docker-and-go docker run -it --entrypoint=dlv goapp
docker: Error response from daemon: OCI runtime create failed: container_linux.go:344: starting container process caused "exec: \"dlv\": executable file not found in $PATH": unknown.

And here’s the bad luck, the same story will be if you have docker-compose for local development or something else. How to be) Docker build has a wonderful –target flag!

docker build --target builder -t goapp:latest .
docker run -it goapp sh
# dlv debug main.go
could not launch process: fork/exec /src/__debug_bin: operation not permitted

And how to fix this ☝️, read my last post

And Voila! A huge plus ⚡️ of this approach for me personally, the lack of Dockerfile-dev and options.

P.S. If you have docker-compose, then in your docker-compose.override.yml you can write like this:

version: "3.4"
image: goapp:dev
context: .
dockerfile: Dockerfile
target: builder


P.S. final gist ->:


comments powered by Disqus