Today I had a task to add a program written in golang to a Dockerfile that I wrote a few weeks ago. The Dockerfile did not currently have golang so I started looking at installing it. The obvious method was using yum to install golang, but I noticed when I do that it installed tons of other things that I didn’t really need. Then I looked at compiling it myself, but I’d need tools like make and it isn’t as nice as one yum command. Then I remembered reading about Dockers multi-stage builds.
Browsing around the internet regarding this topic and there are a lot of posts about how to build your go application using a multi-stage build, but I couldn’t find anything about using multi-stage to grab the go binary and use it in a later stage, so here is how:
Installing go with yum
First lets look at installing golang with yum so we can see how big the image is, and then we can compare the multi-stage method to it.
$ cat Dockerfile
FROM amazonlinux:1
RUN yum install -y \
golang && \
yum clean all && \
rm -rf /var/cache/yum
This results in a 824MB image, wow.
$ docker images | grep go_test
go_test latest 01c6cc5c2bee 1 second ago 824MB
Installing with multi-stage
$ cat Dockerfile
FROM golang:1.12 as go
FROM amazonlinux:1
# Copy the go binary, and add the go binary locations to the PATH environment variable.
COPY --from=go /usr/local/go/bin/go /usr/local/go/bin/go
ENV PATH "/go/bin:/usr/local/go/bin:${PATH}"
This results in a 182MB image:
$ docker images | grep go_test
go_test latest 50cc70b3eed3 40 minutes ago 182MB
Installing a go program along side the go binary
Now if you want to use go get
to install a go program it’s as simple as:
FROM golang:1.12 as go
RUN go get -u github.com/awslabs/amazon-ecr-credential-helper/ecr-login/cli/docker-credential-ecr-login
FROM amazonlinux:1
COPY --from=go /usr/local/go/bin/go /usr/local/go/bin/go
COPY --from=go /go/bin/docker-credential-ecr-login /go/bin/docker-credential-ecr-login
ENV PATH "/go/bin:/usr/local/go/bin:${PATH}"