Golang als mini Container

02. April 2019 Andreas Peters

Unsere RestAPI Entwicklungen laufen zumeist in MESOS Sandbox oder Docker Umgebungen. Da sie Scalierbar sind und möglichst schnell deployed werden sollen, schreiben wir entsprechend effizienten Code und erstellen möglichst Docker Images geringer größe.


Beispiel docker images einiger unserer API Entwicklungen

Wie am Beispiel zu erkennen ist, bewegen wir uns immer um die 17MB pro Image. Das Erstellen ist dabei denkbar einfach und möchten wir an dieser Stelle einmal nachvollziehbar darstellen.

Als basis Image verwenden wir Golang mit Alpine.

FROM golang:alpine as builder

In das Image kopieren wir unser Code und kompilieren diesen mit den benötigten Flags.

WORKDIR /build

COPY . /build/

RUN apk add git && \
    go get -d

RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags "-X main.MinVersion=`date -u +%Y%m%d%.H%M%S` -extldflags \"-static\"" -o main app.go init.go

Nun erstellen wir im gleichen Dockerfile ein weiteres Image. Wieder auf Alpine basierend, aber ohne Golang.

FROM alpine
LABEL maintainer="NAME <EMAIL>"

Wir setzen ein paar default Parameter die in unserem Beispiel verwendet werden.

ENV API_PORT=10777
ENV API_BIND=0.0.0.0
ENV LOGLEVEL=info

Damit der laufenden Prozess nicht unter Root läuft, legen wir einen entsprechenden User an und wechseln zu diesen.

RUN adduser -S -D -H -h /app appuser

USER appuser

Nun kopieren wir die kompilierte Binary aus dem vorherigen Image in das neuen.

COPY --from=builder /build/main /app/

Anschließend nur noch den benötigten Port exposen und das Arbeitsverzeichnis setzen.

EXPOSE 10777

WORKDIR "/app"

CMD ["./main"]

Dockerfile

Im ganzen sieht das Dockerfile wie folgt aus:

FROM golang:alpine as builder

WORKDIR /build

COPY . /build/

RUN apk add git && \
    go get -d

RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -ldflags "-X main.MinVersion=`date -u +%Y%m%d%.H%M%S` -extldflags \"-static\"" -o main app.go init.go


FROM alpine
LABEL maintainer="NAME <EMAIL>"

ENV API_PORT=10777
ENV API_BIND=0.0.0.0
ENV LOGLEVEL=info

RUN adduser -S -D -H -h /app appuser

USER appuser

COPY --from=builder /build/main /app/

EXPOSE 10777

WORKDIR "/app"

CMD ["./main"]