Multi-stage builds with container

Print

Systems quickly become very large when you ship it complete. This includes the build and often the build and test environment. Even if the extraction of the files to be shipped is not a problem, it is time consuming.

Containers offer the possibility to do this automatically.

 

Here you have the option to define multiple containers in one file. A website created in JavaScript and build with Node.js are a good example.

Example:

Node.js: ~ 400 Mbyte - 600 Mbyte
Webserver nginx: ~ 20 Mbyte
Website: ~ 2 Mbyte

 

The whole system as a container results in a total of over 600 Mbyte, although only 22 Mbyte (webserver + website) are needed. In addition, there is a security risk for the system because software is present, which is not needed for a productive operation. A solution here is a multi-stage build.

In a multi-stage build several containers are defined in one file and then only the necessary data from one container to the other are transmitted.

 

Example multi-stage dockerfile

 

To stay with the Node.js, here is a multi-stage build example. The first container contains Node.js as build system, in it the website is created. The second container contains the web server, which copies the necessary data from the first container after the build.

## Base System Stage 1
## Use community Node.js container
FROM node:8.11.3 as buildsystem

## Add source from our Git project
COPY ./source /root/frontend

## Build frontend with Nodejs
WORKDIR /root/frontend/
RUN npm install \
&& npm run build

#####################################################################
#####################################################################

## Base System Stage 2
## Use community nginx container
FROM nginx:alpine 

## Copy build from stage 1
RUN mkdir -p /var/www/html/<MyApp>
COPY --from=buildsystem /root/frontend/dist/ /var/www/html/<MyApp>/

## Add default config for nginx
ADD default.conf /etc/nginx/conf.d/

## Publish Port
EXPOSE 80

## Start nginx
CMD ["nginx", "-g", "daemon off;"]

 

The result is a small container that contains only the most necessary. We use a very small Linux distribution for nginx with alpine.

Another advantage is that you can access two ready-made community containers and therefore have no work to create and maintain them. For system updates, the community containers are simply replaced regularly. The whole thing can be wonderfully automated in a pipeline with GitLab (or other tools).