Containerizing Go Applications with Docker: Basic
Don't Copy
Writing a Dockerfile
FROM golang:1.15-buster
WORKDIR /app
COPY . .
RUN go build -o /opt/my-echo
ENTRYPOINT ["/opt/my-echo"] 
Building the Image docker build . -t my-echo:alpha Running a Container using the Image docker run -i my-echo:alpha hello world Use docker rm to do some clean up on your system run.
Container Orchestration
Docker & Kubernetes

Infrastucture as Code
Ansible & Terraform

Micrservices
Go API Server

Containerizing Go Applications with Docker: Advanced
Don't Copy
Writing a Dockerfile
FROM golang:1.15-buster
EXPOSE 8000
WORKDIR /app
COPY . .
RUN go mod download
RUN go build -o /opt/greeter-server
CMD ["/opt/greeter-server"]
Projects using go mod need some way of downloading the libraries. Notice how instead of ENTRYPOINT, the CMD keyword is used. This allows for overwriting the first command being executed when starting the container. This is helpful for debugging in scenarios where you want to access a shell within the container before starting the web server. The EXPOSE keyword within the Dockerfile does not automatically open the port when running the container.
Building the Image docker build . -t greeter-server:alpha You can confirm it was built, and get some information about the docker image by using the docker images command.
You'll use the docker run command, docker run -d --rm -p 8000:8000 greeter-server:alpha to test the build image and make sure it functions the same in the container as it does on your local machine. This time, use the -d flag when executing the docker run command. This stand for detached, and allows you to run the container in the background. You will also need to do some port forwarding so you can access the server within the container by using the -p flag. We'll forward all incoming traffic on 8000 of the local machine to port 8000 inside the container, -p 8000:8000.
Refactoring Docker Builds
Don't Copy
Writing a Dockerfile
FROM golang:1.15-buster AS builder
EXPOSE 8000
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY greeter-server.go .
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o /opt/greeter-server

# final build
FROM alpine:latest
COPY --from=builder /opt/greeter-server /opt/greeter-server
ENTRYPOINT ["/opt/greeter-server"]
Building the Image To keep things light, you'll leverage the alpine build within Docker Hub. docker build . -t greeter-server:beta optimized your Dockerfile for a reduced images size.

Instructions

1. When using a multi-stage build, it's best to label the stages in the FROM keyword. Modify the first line so that it says FROM golang:1.15-buster AS builder. You'll see why this is important in a moment.
2. For this particular build process, there are a couple of flags that need to be appended to the build command: CGO_ENABLED=0 GOOS=linux GOARCH=amd64. These are special environment variables that the go compiler uses, and affects the binary output. The key piece is the CGO_ENABLED=0, which disables linking the glibc libraries on the OS and includes them in the binary. This is due to the fact that Alpine uses musl and the resulting Go binary would not be able to find the required libraries on the Alpine OS and crash. Don't fret too much if that doesn't make sense, just remember to compile with CGO_ENABLED=0 when using Alpine as the final build container base.
3. You need to remove the CMD line from the builder container. Making the RUN go build the final step in the builder container. Next, you'll add in another FROM keyword. This creates another stage in the build process. You need to tell it to pull the alpine image with FROM alpine:latest.
4. Next, you need to copy the built binary from the builder stage into this current container. Luckily, you can still use the COPY keyword but provide docker where to copy from with --from=builder
5. To keep the downloading-of-dependencies layer cached, you will want to COPY the Go mod files first, and then run go mod download.