Private Go package repos and Docker

·

If you’re working in a corporate environment with Go and Docker images you likely have encountered the issue with go get and Go packages in private source repositories. Ivan Daniluk wrote an excellent article on that topic — highly recommended.

I think an even more elegant solution and easier to share with other developers and multiple projects is to create a private build image with the necessary setup.

  1. Create a shared user account with read-only access to the private repositories.
  2. Run ssh-keygen -t rsa -P "" -C shareduser@example.com -f shared_rsa to create a SSH keypair without passwort.
  3. Add the public key (shared_rsa.pub) to the shared user account.
  4. Build a base image with the keys and necessary configuration.

Files for base image

gitconfig:

[url "git@github.com:"]
    insteadOf = https://github.com/

Dockerfile:

FROM golang:1.10.3
COPY gitconfig /root/.gitconfig
COPY shared_rsa /root/.ssh/id_rsa
COPY shared_rsa.pub /root/.ssh/id_rsa.pub
RUN ssh-keyscan -t rsa github.com >> ~/.ssh/known_hosts

Now you have a base image that you can use in multi-staged builds. This is also a great place to install additional build tools as needed, for example dep.

As the resulting image contains the private key of your shared user you should never use this image directly for deployment and only ever push it to a private repository.

Usage

Using the pre-configured Docker image allows much cleaner Dockerfiles in projects that need access to private repositories. Illustrated in the example below.

FROM repository.example.com/go-build:1.10.3-v1 as build
RUN go get github.com/example/private-lib
RUN CGO_ENABLED=0 go build -o /app main.go

FROM alpine:latest
RUN apk add --no-cache --virtual ca-certificates
COPY --from=build /app .
RUN ["./app"]