I ran into this deploying to google cloud run with a distroless (aka very slim) docker image. I decided to just downgrade to go 1.19 at the time and it works fine. According to this comment building on a machine with the same version of glibc might make it use older symbols (which I believe is what @peakedshout is referring to).
I’m not sure if it’s the smallest image, but have you tried alpine?
A minimal Docker image based on Alpine Linux with a complete package index and only 5 MB in size!
I created a minimal image that serves web traffic with the following main.go
:
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
// Hello world, the web server
helloHandler := func(w http.ResponseWriter, req *http.Request) {
io.WriteString(w, "Hello, world!\n")
}
port := ":6830"
fmt.Println("Starting web server on", port)
http.HandleFunc("/hello", helloHandler)
log.Fatal(http.ListenAndServe(port, nil))
}
With this as my Dockerfile:
# syntax=docker/dockerfile:1
## Build our binary
FROM golang:latest AS build
WORKDIR /app
# Copy our source code
# NOTE: usually here I would copy over go.mod and go.sum
# and then run `RUN go mod download`. For simple demo though
# we don't even have a module.
COPY main.go ./
# Build our package
RUN CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -ldflags="-w -s" -o kardis main.go
## Pull our binary to smaller alpine image for final image
FROM alpine:latest
WORKDIR /app
# Copy binary from build stage
COPY --from=build /app/kardis .
EXPOSE 6380
ENTRYPOINT ["/app/kardis"]
Note I’m using build stages there so I can use that large golang image but it won’t affect our final image size. Anyway, I built it and ran it:
# Build/tag
docker build -t kardis .
# Run with exposed port to verify it is working:
docker run -p 6830:6830 kardis
… and then checked the image size and it is pretty small:
REPOSITORY TAG IMAGE ID CREATED SIZE
kardis latest 1b01dcc2b490 11 minutes ago 12.9MB
You could PROBABLY get something smaller than 12.9mb (some of that is obviously our binary too) but there’s going to be a point of diminishing returns. That said, I was able to change my FROM
to scratch and my dockerfile above worked fine. Have you tried building with cgo disabled and -a
? From the docs:
-a
force rebuilding of packages that are already up-to-date.