forked from ccampo133/go-docker-alpine-remote-debug
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
159 additions
and
3 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,6 @@ | ||
<component name="ProjectRunConfigurationManager"> | ||
<configuration default="false" name="remote-debug" type="GoRemoteDebugConfigurationType" factoryName="Go Remote" port="40000"> | ||
<option name="disconnectOption" value="ASK" /> | ||
<method v="2" /> | ||
</configuration> | ||
</component> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,32 @@ | ||
FROM golang:alpine3.17 AS build | ||
|
||
WORKDIR /app | ||
|
||
# Turning off Cgo is required to install Delve on Alpine. | ||
ENV CGO_ENABLED=0 | ||
|
||
# Download and install the Delve debugger. | ||
RUN go install github.com/go-delve/delve/cmd/dlv@latest | ||
|
||
COPY go.mod . | ||
COPY go.sum . | ||
|
||
RUN go mod download | ||
|
||
# You'll want to copy all your .go files here in a bigger project. | ||
COPY main.go . | ||
|
||
# Disable inlining and optimizations that can interfere with debugging. | ||
RUN go build -gcflags "all=-N -l" -o /main main.go | ||
|
||
FROM alpine:3.17 | ||
|
||
WORKDIR / | ||
|
||
COPY --from=build /go/bin/dlv /bin/dlv | ||
COPY --from=build /main /bin/app | ||
COPY run.sh /bin/run.sh | ||
|
||
EXPOSE 8080 | ||
|
||
ENTRYPOINT ["/bin/run.sh"] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,75 @@ | ||
# go-docker-alpine-remote-debug | ||
Example how to enable remote debugging using Delve for a Dockerized Go application. | ||
|
||
A simple example on how to enable remote debugging using [Delve](https://github.com/go-delve/delve) | ||
for a Go application running in an Alpine Linux Docker container. | ||
|
||
## Background | ||
|
||
This example contains a simple Go web application which returns `Hello world!` | ||
on all HTTP requests to the endpoint `/hello`. The application is packaged into | ||
a Docker image which includes the Delve debugger and can accept remote debugging | ||
sessions on a user specified port. | ||
|
||
Explore the code to see how this is accomplished :). | ||
|
||
## Build and Run | ||
|
||
Build the application and Docker image. This example utilizes a multi-stage | ||
Docker build to download and install Delve, and compile the application: | ||
```sh | ||
$ docker build ./ -t debug-example:latest -f Dockerfile | ||
|
||
[+] Building 9.5s (18/18) FINISHED | ||
... | ||
```` | ||
|
||
Run a container: | ||
```sh | ||
$ docker run \ | ||
--rm \ | ||
-p 8080:8080 \ | ||
-p 40000:40000 \ | ||
-e REMOTE_DEBUG_PORT=40000 \ | ||
-e REMOTE_DEBUG_PAUSE_ON_START=true \ | ||
debug-example:latest | ||
Starting application with remote debugging on port 40000 | ||
Process execution will be paused until a debug session is attached | ||
Executing command: /bin/dlv --listen=:40000 --headless=true --log --api-version=2 --accept-multiclient exec /bin/app -- | ||
API server listening at: [::]:40000 | ||
... | ||
``` | ||
Once the container is running, you can establish a remote debugging session for | ||
the application on port `40000` (feel free to change the port - there's nothing | ||
special about `40000`, I just like that number). While you can always use the | ||
[Delve command line client](https://github.com/go-delve/delve/blob/master/Documentation/cli/README.md) | ||
to debug, I recommend using your IDE for this: | ||
* [GoLand / IDEA](https://www.jetbrains.com/help/go/attach-to-running-go-processes-with-debugger.html) | ||
* [Visual Studio Code](https://github.com/golang/vscode-go/blob/master/docs/debugging.md) | ||
Note that because we set `REMOTE_DEBUG_PAUSE_ON_START`, the `main` function will | ||
not be executed until a debug session is connected. This is particularly useful | ||
if you want to debug an application from its first line of execution, however if | ||
you don't need that, feel free to omit that environment variable and the | ||
application will start normally. | ||
Finally, set some breakpoints and make a request: | ||
```sh | ||
$ curl http://localhost:8080/hello | ||
Hello world! | ||
``` | ||
## GoLand/IDEA Run/Debug Configuration | ||
The [`.run`](.run) directory contains a | ||
[run/debug configuration](https://www.jetbrains.com/help/go/run-debug-configuration.html) | ||
which you use for this example. | ||
## References | ||
* https://github.com/go-delve/delve/blob/master/Documentation/faq.md#how-do-i-use-delve-with-docker | ||
* https://github.com/go-delve/delve/blob/master/Documentation/usage/dlv_exec.md | ||
* https://www.jetbrains.com/help/go/attach-to-running-go-processes-with-debugger.html#attach-to-a-process-on-a-remote-machine |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,3 @@ | ||
module github.com/ccampo133/go-docker-alpine-remote-debug | ||
|
||
go 1.19 |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
package main | ||
|
||
import ( | ||
"fmt" | ||
"net/http" | ||
) | ||
|
||
func main() { | ||
// This is a good spot for a breakpoint :) | ||
http.HandleFunc("/hello", hello) | ||
if err := http.ListenAndServe(":8080", nil); err != nil { | ||
panic(err) | ||
} | ||
} | ||
|
||
func hello(w http.ResponseWriter, req *http.Request) { | ||
// Try setting a breakpoint here too :) | ||
if _, err := fmt.Fprintf(w, "Hello world!\n"); err != nil { | ||
panic(err) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
#!/usr/bin/env sh | ||
|
||
# Ensure this script is executable! | ||
|
||
cmd="/bin/app" | ||
if [ "$REMOTE_DEBUG_PORT" ]; then | ||
echo "Starting application with remote debugging on port $REMOTE_DEBUG_PORT" | ||
dlvFlags="--listen=:$REMOTE_DEBUG_PORT --headless=true --log --api-version=2 --accept-multiclient" | ||
execFlags="" | ||
# Simply setting this environment variable is enough to force the debugger to | ||
# pause on start --- we don't care about the value. | ||
if [ "$REMOTE_DEBUG_PAUSE_ON_START" ]; then | ||
echo "Process execution will be paused until a debug session is attached" | ||
else | ||
execFlags="$execFlags --continue" | ||
fi | ||
cmd="/bin/dlv $dlvFlags exec $cmd $execFlags -- " | ||
fi | ||
|
||
echo "Executing command: $cmd $*" | ||
|
||
exec $cmd "$@" |