Let's assume we have a sample Golang application (in a Go project folder).
Contents of main.go
package main
import "fmt"
func main() {
fmt.Println("hello world")
}
In the same folder, run the following commands to initialize go modules
# initialize go modules
go mod init github.com/username/hello-world
# cleans up dependencies and fetches if not present
go mod tidy
Now, create a Dockerfile in the same folder
Contents of Dockerfile
FROM golang:alpine as builder
RUN apk update && apk upgrade && \
apk add --no-cache bash git
WORKDIR /app
COPY . .
RUN go mod tidy
RUN GOFLAGS= GOOS=linux CGO_ENABLED=0 go build -v -o bin/app main.go
FROM alpine:3
RUN apk update \
&& apk add --no-cache ca-certificates \
&& update-ca-certificates 2>/dev/null || true
COPY --from=builder /app/bin/app /app
CMD ["/app"]
What's happening in the above Dockerfile?
We use a builder container (
golang:alpine
) to gather dependenciesWe build the executable in the builder container
We create an
alpine
container and copy the executable to that.We also specify CMD which tells docker to run our executable
In the final Docker image, we will only have the final container.
Note that we use alpine images to keep the image size lower.
If you do not want to give your app root access to the container, you can also add a new user and run the executable as that user. Refer GIST
You can now build your docker image
docker build -t app:latest -t mridulganga/app:latest .
You can push or run this docker image now.
# run using the local image
docker run app:latest
# push the image to dockerhub mridulganga's account
docker push mridulganga/app:latest
Make sure you are logged into Docker hub, try docker login
if not