2022-12-25 19:13:58 +00:00
<!DOCTYPE html>
< html >
< head >
< meta charset = "utf-8" / >
< meta name = "viewport" content = "width=device-width, initial-scale=1" / >
< link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/github-markdown-css/5.1.0/github-markdown.min.css"
/>
< / head >
< style >
/* https://github.com/sindresorhus/github-markdown-css */
.markdown-body {
box-sizing: border-box;
min-width: 200px;
max-width: 980px;
margin: 0 auto;
padding: 45px;
}
2022-07-10 11:09:42 +00:00
2022-12-25 19:13:58 +00:00
@media (max-width: 767px) {
.markdown-body {
padding: 15px;
}
}
< / style >
< body class = "markdown-body" >
2022-12-25 19:22:39 +00:00
< div >
< a href = "index" > Index< / a >
< / div >
2022-12-25 19:13:58 +00:00
< h1 > < a id = "user-content-dockerfile-for-go" class = "anchor" aria-hidden = "true" href = "#dockerfile-for-go" > < span aria-hidden = "true" class = "octicon octicon-link" > < / span > < / a > Dockerfile for Go< / h1 >
< p > Each time I start a new Go project, I repeat many steps.
Like set up < code > .gitignore< / code > , CI configs, Dockerfile, ...< / p >
< p > So I decide to have a baseline Dockerfile like this:< / p >
< div class = "highlight highlight-source-dockerfile" > < pre > < span class = "pl-k" > FROM< / span > golang:1.19-bullseye as builder
< span class = "pl-k" > RUN< / span > go install golang.org/dl/go1.19@latest \
2022-10-09 10:45:31 +00:00
& & go1.19 download
2022-07-10 11:09:42 +00:00
2022-12-25 19:13:58 +00:00
< span class = "pl-k" > WORKDIR< / span > /build
2022-07-10 11:09:42 +00:00
2022-12-25 19:13:58 +00:00
< span class = "pl-k" > COPY< / span > go.mod .
< span class = "pl-k" > COPY< / span > go.sum .
< span class = "pl-k" > COPY< / span > vendor .
< span class = "pl-k" > COPY< / span > . .
2022-07-10 11:09:42 +00:00
2022-12-25 19:13:58 +00:00
< span class = "pl-k" > RUN< / span > CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOAMD64=v3 go build -o ./app -tags timetzdata -trimpath .
2022-07-10 11:09:42 +00:00
2022-12-25 19:13:58 +00:00
< span class = "pl-k" > FROM< / span > gcr.io/distroless/base-debian11
2022-07-10 11:09:42 +00:00
2022-12-25 19:13:58 +00:00
< span class = "pl-k" > COPY< / span > --from=builder /build/app /app
2022-07-10 11:09:42 +00:00
2022-12-25 19:13:58 +00:00
< span class = "pl-k" > ENTRYPOINT< / span > [< span class = "pl-s" > "/app"< / span > ]< / pre > < / div >
< p > I use < a href = "https://docs.docker.com/develop/develop-images/multistage-build/" rel = "nofollow" > multi-stage build< / a > to keep my image size small.
First stage is < a href = "https://hub.docker.com/_/golang" rel = "nofollow" > Go official image< / a > ,
second stage is < a href = "https://github.com/GoogleContainerTools/distroless" > Distroless< / a > .< / p >
< p > Before Distroless, I use < a href = "https://hub.docker.com/_/alpine" rel = "nofollow" > Alpine official image< / a > ,
2022-12-25 18:52:03 +00:00
There is a whole discussion on the Internet to choose which is the best base image for Go.
After reading some blogs, I discover Distroless as a small and secure base image.
2022-12-25 19:13:58 +00:00
So I stick with it for a while.< / p >
< p > Also, remember to match Distroless Debian version with Go official image Debian version.< / p >
< div class = "highlight highlight-source-dockerfile" > < pre > < span class = "pl-k" > FROM< / span > golang:1.19-bullseye as builder< / pre > < / div >
< p > This is Go image I use as a build stage.
This can be official Go image or custom image is required in some companies.< / p >
< div class = "highlight highlight-source-dockerfile" > < pre > < span class = "pl-k" > RUN< / span > go install golang.org/dl/go1.19@latest \
& & go1.19 download< / pre > < / div >
< p > This is optional.
In my case, my company is slow to update Go image so I use this trick to install latest Go version.< / p >
< div class = "highlight highlight-source-dockerfile" > < pre > < span class = "pl-k" > WORKDIR< / span > /build
< span class = "pl-k" > COPY< / span > go.mod .
< span class = "pl-k" > COPY< / span > go.sum .
< span class = "pl-k" > COPY< / span > vendor .
< span class = "pl-k" > COPY< / span > . .< / pre > < / div >
< p > I use < code > /build< / code > to emphasize that I am building something in that directory.< / p >
< p > The 4 < code > COPY< / code > lines are familiar if you use Go enough.
2022-12-25 18:52:03 +00:00
First is < code > go.mod< / code > and < code > go.sum< / code > because it defines Go modules.
2022-12-25 19:13:58 +00:00
The second is < code > vendor< / code > , this is optional but I use it because I don't want each time I build Dockerfile, I need to redownload Go modules.< / p >
< div class = "highlight highlight-source-dockerfile" > < pre > < span class = "pl-k" > RUN< / span > CGO_ENABLED=0 GOOS=linux GOARCH=amd64 GOAMD64=v3 go build -o ./app -tags timetzdata -trimpath .< / pre > < / div >
< p > This is where I build Go program.< / p >
< p > < code > CGO_ENABLED=0< / code > because I don't want to mess with C libraries.
2022-12-25 18:52:03 +00:00
< code > GOOS=linux GOARCH=amd64< / code > is easy to explain, Linux with x86-64.
2022-12-25 19:13:58 +00:00
< code > GOAMD64=v3< / code > is new since < a href = "https://go.dev/doc/go1.18#amd64" rel = "nofollow" > Go 1.18< / a > ,
I use v3 because I read about AMD64 version in < a href = "https://gitlab.archlinux.org/archlinux/rfcs/-/blob/master/rfcs/0002-march.rst" rel = "nofollow" > Arch Linux rfcs< / a > . TLDR's newer computers are already x86-64-v3.< / p >
< p > < code > -tags timetzdata< / code > to embed timezone database incase base image does not have.
< code > -trimpath< / code > to support reproduce build.< / p >
< div class = "highlight highlight-source-dockerfile" > < pre > < span class = "pl-k" > FROM< / span > gcr.io/distroless/base-debian11
< span class = "pl-k" > COPY< / span > --from=builder /build/app /app
2022-07-10 11:09:42 +00:00
2022-12-25 19:13:58 +00:00
< span class = "pl-k" > ENTRYPOINT< / span > [< span class = "pl-s" > "/app"< / span > ]< / pre > < / div >
< p > Finally, I copy < code > app< / code > to Distroless base image.< / p >
2022-07-10 11:09:42 +00:00
2022-12-25 19:22:39 +00:00
< div >
Feel free to ask me via
< a href = "mailto:hauvipapro+posts@gmail.com" > email< / a > or
< a rel = "me" href = "https://hachyderm.io/@haunguyen" > Mastodon< / a >
< / div >
2022-12-25 19:13:58 +00:00
< / body >
< / html >