Multi-staged Dockers to your rescue

Milindu S. Kumarage
GDG SRILANKA
Published in
2 min readJul 23, 2018

Containerizing apps is becoming the new norm and Dockers are already the household tool for it! Making your Docker images slim is an interesting task.

Say we have a web app, a single page web app written in React with a Go Lang back-end for it. We need NodeJS and Yarn to build the React app, Go Lang to build the REST back-end but need only NGINX for serving the static files from the React app with a reverse proxy to the running Go back-end’s binary for API calls.

We can either build the React app and Go app separately on the CI and copy the artifacts to a NGINX Docker, but that’s not the true Docker way. We all love to build React app on an official `node` image and build the Go app on official `golang` image, because it makes sure you always gets the same environment, not what’s on the CI tool or on a local machine.

But, how can we have a Node Docker, Go Docker and NGINX Docker at once? Well, we can. This is where the new multi-stage Dockers comes into play.

FROM node:9-alpine AS frontendWORKDIR /app/web
ADD web .
RUN yarn && yarn build
FROM golang:alpine AS backendADD api /go/src/github.com/agentmilindu/mywebapi
RUN go install github.com/agentmilindu/mywebapi
FROM nginx:alpineCOPY nginx.conf /etc/nginx/nginx.conf
COPY --from=frontend /app/web/build /usr/share/nginx/html
COPY --from=backend /go/bin/mywebapi /opt/app/api

Here we first use `node:9-alpine` image to build the web app, then uses `golang:alpine` to build the Go app, the copies `/app/web/build` from “frontend” stage and `/go/bin/mywebap` from “backend” stage into the final NGINX stage. This stage does not have NodeJS or Go lang, it is simply a lightweight NGINX Docker with your build artifacts.

The potential of this is limitless! Say now you want to run tests and send coverage reports to your SonarQube. It is easy with multi-stage Dockers, simply add a Sonar scanner Docker stage, scan your code and send reports to a SonarQube!

If you like to stop the build at a specific stage, you can do,

docker build --target builder .

Or if you want to copy something from an existing Docker image, you can,

FROM alpineCOPY --from=nginx:latest /etc/nginx/nginx.conf /nginx.conf
COPY --from=frontend /app/web/build /usr/share/nginx/html

--

--