Containerizing a Go API with Docker For Mac

I’m working through creating a RESTful API template. As part of it, I want to be able to “Containerize” my app using docker and deploy it to “the cloud”. Baby steps for me though — I want to get everything working locally first. This post is about “containerizing” my API using Docker and getting it to work locally on my Mac. Right now, from a networking perspective, my app is pretty simple — it needs connectivity on two ports: 1 port for database traffic, 1 port for http traffic.

Part 1 — Simple build against local PostgreSQL, exposing ports 5432 for PostgreSQL and 8080 for http traffic from my local host to my container.

First off, you must have Docker for Mac installed. Once installed, you’ll need to familiarize yourself with the various docker commands and idioms. I highly recommend Docker Deep Dive. I read a lot of different blogs and how-tos on Docker and wasn’t able to really put it all together until I read this book.

dbName := os.Getenv("PG_DBNAME_TEST")
dbUser := os.Getenv("PG_USERNAME_TEST")
dbPassword := os.Getenv("PG_PASSWORD_TEST")
dbHost := os.Getenv("PG_HOST_TEST")
dbPort, err := strconv.Atoi(os.Getenv("PG_PORT_TEST"))
if err != nil {
log.Error().Err(err).Msg("Unable to complete string to int conversion for dbPort")
return nil, err
}
# Start from a Debian image with the latest version of Go installed
# and a workspace (GOPATH) configured at /go.
FROM golang:latest
# Create WORKDIR (working directory) for app
WORKDIR /go/src/github.com/gilcrest/go-API-template
# Copy the local package files to the container's workspace
# (in the above WORKDIR)
ADD . .
# Switch WORKDIR to directory where server main.go lives
WORKDIR /go/src/github.com/gilcrest/go-API-template/cmd/server
# Build the go-API-template userServer command inside the container
# at the most recent WORKDIR
RUN go build -o userServer
# Run the userServer command by default when the container starts.
# runs command at most recent WORKDIR
ENTRYPOINT ./userServer
# Document that the container uses port 8080
EXPOSE 8080
# Document that the container uses port 5432
EXPOSE 5432
# Build image with gilcrest as repository name, go-api-template as build name and latest as build tag from the current directory$ docker image build -t gilcrest/go-api-template:latest .
# Run container using previously built image (gilcrest/go-api-template)
# -d Run in the background (detached)
# -p publish port 5432 on the host to port 5432 on the container for postgres
# -p publish port 8080 on the host to port 8080 on the container for http access
# --env-file load environment variables using the env file
# --name name the container user-server
$ docker container run -d -p 5432:5432 -p 8080:8080 --env-file ./test.env --name user-server gilcrest/go-api-template
// ListenAndServe on port 8080, not specifying a particular IP address for this particular implementation
if err := http.ListenAndServe(":8080", nil); err != nil {
log.Fatal(err)
}
$ docker container run -d -p 5432:5432 -p 8080:8080 --env-file ./test.env --name user-server gilcrest/go-api-template
PG_DBNAME_TEST
PG_USERNAME_TEST
PG_PASSWORD_TEST
PG_HOST_TEST=host.docker.internal
PG_PORT_TEST
# Docker env files
*.env
##################################################################### Builder Stage                                                    # ##################################################################### Start from the golang:alpine image with the latest version of Go installed
FROM golang:alpine AS builder
# Create WORKDIR using project's root directory
WORKDIR /go/src/github.com/gilcrest/go-API-template
# Copy the local package files to the container's workspace
# in the above created WORKDIR
ADD . .
# Build the go-API-template command inside the container
RUN cd cmd/server && go build -o userServer
##################################################################### Final Stage # ##################################################################### Pull golang alpine image (very small image, with minimum needed to run Go)
FROM alpine
# Create WORKDIR
WORKDIR /src/github.com/gilcrest/go-API-template/input
# Copy json file needed for feature flags to directory expected by app
# File is copied from the Builder stage image
COPY --from=builder /go/src/github.com/gilcrest/go-API-template/input/httpLogOpt.json .
# Create WORKDIR
WORKDIR /app
# Copy app binary from the Builder stage image
COPY --from=builder /go/src/github.com/gilcrest/go-API-template/cmd/server/userServer .
# Run the userServer command by default when the container starts.
ENTRYPOINT ./userServer
# Document that the service uses port 8080
EXPOSE 8080
# Document that the service uses port 5432
EXPOSE 5432

Go enthusiast; Loyalty/CRM Technology Leader; Drummer; Vinyl geek; Husband/Dad