2 Methods to Run Golang App With Docker

Do you want to run your Golang application with docker? Read this post. We will try two methods of running a golang application with docker. You can see which method is more suitable for you.

To run a go app with docker, we need to create a docker container. Then run the container with the necessary resources. But before going to the docker part, of course, we need to have a go app first.

The Go application

This is a simple web server that we are going to use.

package main

import (
    "fmt"
    "net/http"

    "github.com/gorilla/mux"
)

func main() {
    r := mux.NewRouter()

    r.HandleFunc("/get_city", cityHandler)

    fmt.Println("listening..")
    http.ListenAndServe(":5005", r)
}

func cityHandler(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte(`{"city":["jakarta","bandung","bandar lampung"]}`))
}

To create a docker container, we need a Dockerfile.
Create a file named Dockerfile in your go application root directory.

Dockerfile golang root

As written in the beginning, we will try two methods of running the go app with docker. Now let’s start with method one.

Method 1: Build Go app binary in docker

In this method, we copy our source code to the container. Then fetch vendor libraries and build the application in the docker. We use a multi-staged build to omit the source code in the resulting image. So even though the source code is copied, the resulting image will only contain the application binary. This can significantly reduce the image size.
Below is the Dockerfile for this method.

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
FROM golang:1.15.8-alpine AS builder
WORKDIR /build
# Copy our go codes to workdir
COPY . .

ENV CGO_ENABLED=0 
RUN go mod vendor \
    && go build -o myapp .

# Build from scratch
FROM scratch
COPY --from=builder /build/myapp /
ENTRYPOINT ["/myapp"]

The first stage is builder, we use golang:1.15.8-alpine image as the base image for our container. You can change the Go version if you need to use another version. We name the first stage builder as you can see on the first line. On line 4, we copy all our source code to the container. If you want to exclude something such as the vendor folder, you can put it in the .dockerignore file. Then we fetch vendor libraries and build the application on the next line. I use go mod for this example. You may need to modify this if you use another tool other than go mod.

The next stage starts from line 11. We create the container from scratch because we only need the application binary to run the application. So we copy only the binary from the builder stage to the last stage. Entrypoint specifies which application to run when the container is run, which is our Go application.

Use this command to build the image.

docker build -t godocker .

After it is built, you can see it in your image list with the command docker images or docker image ls.

To create and run the container using the image, use this command.

docker run -p 5005:5005 --rm godocker
The option -p 5005:5005 is to publish container port 5005 to host port 5005. This means that by sending a request to the host port, the request will go to our container. The option --rm is to remove the container if it is stopped.

Now, your go application should already be running in docker. To see it, you can use the command docker ps or docker container ls.

docker ps

That’s it for method 1. Now let’s see method 2.

Methods 2: Copy the binary only

In this method, the binary is built in another environment, such as our local environment. We only copy the Go app binary to docker. But we need to set variables CGO_ENABLED=0 and GOOS=linux when building the Go app so that it can run on the docker container. You can simplify the command by using a tool like Makefile. Below is our command to build the app.

CGO_ENABLED=0 GOOS=linux go build -o myapp

This is the Dockerfile for this method.

FROM scratch
COPY myapp /
ENTRYPOINT ["/myapp"]

It is similar to the last stage of method 1. The difference is that we copy the binary from the host machine rather than build it in the docker.

Conclusion

We have tried 2 methods to run Golang application with docker. You may choose which one is more suitable for you. Or maybe you have another method besides these two, like pulling the source code from git in the docker. Leave a comment.


See also