In this blog we are looking at the common patterns for Docker.
In Docker we always want to focus on two issues: size and surface area. A way to solve this is the Build Pattern.
A builder pattern refers to having two Dockerfiles:
- one is for development. It contains everything for building the application
- one is for production. It contains only necessary elements for the container to run.
A script file is needed like dockerbuild.sh
which builds the development version first and copies the necessary layers or files into some folder and build the production version from there with only the files we need.
This is nice but we have the hassle to maintain two docker files, a shell script all the time. That’s why Multi-Stage Builds is introduced.
Docker 17.05 introduced multi-stage builds, which allow you to use multiple FROM
statements in a single Dockerfile.
With multi-stage builds, you use multiple FROM statements in your Dockerfile. Each FROM instruction can use a different base, and each of them begins a new stage of the build. You can selectively copy artifacts from one stage to another, leaving behind everything you don’t want in the final image.
For a common node-based Docker file:
//Dockerfile
FROM node:12-alpine as base
WORKDIR /src
COPY package.json package-lock.json /src/
COPY . /src
EXPOSE 8080FROM base as production
ENV NODE_ENV=production
RUN npm install --production
CMD ["node", "index.js"]FROM base as dev
ENV NODE_ENV=development
RUN npm config set unsafe-perm true && npm install -g nodemon
RUN npm install
CMD ["npm", "start"]
Docker-compose file after multi-stage build
version: '3.5'
services:
web:
build:
context: ./
target: dev
volumes:
- .:/src
command: npm start
ports:
- "8080:8080"
environment:
NODE_ENV: dev
VIRTUAL_HOST: 'currency.test'
VIRTUAL_PORT: 8080
We ran the following commands to build the dev image:
docker build . -t currency-api-dev -target=dev
To build for production, pass in a different params:
docker build . -t currency-api-dev -target=production
You can also build it imperatively with the flag — target
:
docker build --target base -t myApp:v1 .
The from command is not only limited to build from the current image. We can use — from flag with external docker images as well.
COPY --from=busy-box:latest