After browsing around the internet I couldn’t find any guides for exactly what I wanted to do with a prototype I was writing and so decided to share my discoveries. After writing your web app in
Go
to get it ready for deployment in docker (and later to the cloud) create a new file named dockerfile
in the main directory ~/go/src/<my-app>
.
Check the version of go you are using quickly with $ go version
and then add the following to your new dockerfile:
FROM golang:1.15.5-alpine
Here we import the docker image of the version of go being used, I prefer the alpine images based on their reputation for a smaller footprint. Now that we have a base Linux image to build from we need to define a working directory:
WORKDIR /app
Here app is nothing more than a convention and could be anything we desire. Now we can direct docker to add the local files to the image:
COPY . .
RUN go mod download
This will copy the files in the current directory, place them into the working directory, and follow that up with resolving the dependencies. Finally, let’s ask docker to build and run the application with:
RUN go build -o ./<my-app> .
CMD ["/<my-app>"]
If everything went well we could run and access the app using $ docker run -d -p 8080:8080 <my-app>
to get a detached container with port 8080 as the ingress. This is a situation where there are many roads all leading to Rome, the port mapping can be in an config file, exposed in the dockerfile or provided in the run command just pick one and try not to get too hung up on all the different ways to accomplish this. You might notice after using these steps that the container image is rather large, so let’s take a second approximation and shrink up the image.
FROM golang:1.15.5-alpine AS build
# Create app directory
WORKDIR /app
# Gather local files and Install app dependencies
COPY . .
RUN go mod download
# Build the binary
RUN go build -o ./<my-app> .
# Stage 2 - Copy only binary and static files
FROM alpine:latest
WORKDIR /
COPY --from=build /app/<my-app> /<my-app>
COPY --from=build /app/web /web
EXPOSE 8000
CMD ["/<my-app>"]
Now we’ve added a few more sophisticated options, let’s quickly go through them:
- Add a second stage to copy just the files we need to the final product
- Copy the binary and the static files, otherwise there is nothing to serve and the binary will panic
- Expose a port inside docker
That’s it for now, thanks for reading.