Last Updated: February 26, 2021
·
771
· bneil

Faster Multistage Golang Docker Builds

I was experimenting with creating faster caching steps via dockers multistage build. Please note that im pulling from a private repo in the package layer step which is why you see all that ssh manipulation. The idea for that was to have CI provide the "privkey" at build time, copy that into the image thus allowing access to the private repo. Also note the GOPRIVATE env variable, you'd want to update `companyname` with a wildcard or your company name.

# ======================== [ Base Layer ]
FROM golang:alpine AS base

RUN apk add --no-cache --update make git openssh
WORKDIR /app
COPY go.mod go.sum ./

 # ======================== [ Package Layer ]
FROM base AS dependencies
ARG priv_key

RUN mkdir -p ~/.ssh && umask 0077
COPY priv_key /root/.ssh/id_rsa
RUN chmod 600 /root/.ssh/id_rsa
RUN git config --global url."git@github.com:".insteadOf https://github.com/ \
    && ssh-keyscan github.com >> ~/.ssh/known_hosts
ENV GOPRIVATE=github.com/your_company

RUN go mod download

COPY . .

RUN make build

# ======================== [ Create Final ]
FROM base as release

RUN apk --no-cache add ca-certificates

WORKDIR /app

EXPOSE 3000

COPY --from=dependencies /app/bin/service /app/service
COPY --from=dependencies /app/config /app/config

ENTRYPOINT ["/app/service"]   

you may notice make build in the builder step, that file looks like the following

.PHONY: build clean test

build:
    env GOOS=linux go build -ldflags="-s -w" -o bin/service cmd/main.go

darwin:
    env GOOS=darwin go build -o bin/d_service cmd/main.go

test:
    go -v ./...

clean:
    rm -rf ./bin  

the actual build was done using this command

DOCKER_BUILDKIT=1 docker build -t amazing_service_image .