Skip to content

Instantly share code, notes, and snippets.

@vahanNasibyan
Last active October 2, 2018 08:44
Show Gist options
  • Save vahanNasibyan/c8a2a5fd7c2a6200f960d6bdc239c895 to your computer and use it in GitHub Desktop.
Save vahanNasibyan/c8a2a5fd7c2a6200f960d6bdc239c895 to your computer and use it in GitHub Desktop.
multistage builds for docker images
docker build -t ${package.config.repo_name} --target=production .
# Stage-1 dependencies
FROM node:8.12.0-alpine as pre
RUN apk add --update git && \
rm -rf /tmp/* /var/cache/apk/*
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
COPY package.json package.json
RUN apk add --no-cache --virtual .build-deps alpine-sdk python \
&& npm install --production --silent \
&& apk del .build-deps
COPY . .
CMD ["pm2-docker", "npm", "--", "start"]
# Stage-2 final image
FROM node:8.12.0-alpine as production
RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app
RUN npm install pm2 -g
COPY --from=pre /usr/src/app ./
CMD ["pm2-docker", "npm", "--", "start"]
@grigorkh
Copy link

grigorkh commented Oct 2, 2018

# Stage-1 dependencies
FROM node:8.12.0-alpine as pre

# Use --no-cache insted of removing tmp and cache.
#RUN apk add --update git && \
#  rm -rf /tmp/* /var/cache/apk/*
RUN apk add --no-cache git

# The instructions RUN, COPY, ADD create layers. Other instructions create temporary intermediate images, 
# and do not directly increase the size of the build.
# The WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it in the Dockerfile. 
# If the WORKDIR doesn’t exist, it will be created even if it’s not used in any subsequent Dockerfile instruction.
#RUN mkdir -p /usr/src/app
WORKDIR /usr/src/app

COPY package.json package.json

RUN apk add --no-cache --virtual .build-deps alpine-sdk python \
 && npm install --production --silent \
 && apk del .build-deps

COPY . .

# We don't need to use CMD here.
#CMD ["pm2-docker", "npm", "--", "start"]

# Stage-2 final image
FROM node:8.12.0-alpine as production

#RUN mkdir -p /usr/src/app

WORKDIR /usr/src/app

RUN npm install pm2 -g

COPY --from=pre /usr/src/app ./

# When creating an image, you can bypass the package.json's start command and bake it directly into the image itself. 
# First off this reduces the number of processes running inside of your container. 
# Secondly it causes exit signals such as SIGTERM and SIGINT to be received by the Node.js process instead of npm swallowing them.
CMD ["pm2-docker", "npm", "--", "start"]

@grigorkh
Copy link

grigorkh commented Oct 2, 2018

Avoid npm and pm2 in CMD

When creating an image, you can bypass the package.json's start command and bake it directly into the image itself.
First off this reduces the number of processes running inside of your container.
Secondly it causes exit signals such as SIGTERM and SIGINT to be received by the Node.js process instead of npm swallowing them.

CMD ["node","index.js"]

Non-root user

By default, Docker runs container as root which inside of the container can pose as a security issue. You would want to run the container as an unprivileged user wherever possible. The node images provide the node user for such purpose.
At the end, set the user to use when running this image:

USER node

Add .dockerignore

The COPY instructions in a Dockerfile will skip any files/directories listed in an associated .dockerignore file:

.dockerfile example for node.js

# Git
.git
.gitignore

# Build step outputs
build
.happypack

# Docker configuration
Dockerfile
Makefile
docker-compose.yml

# NPM dependencies
node_modules
#**/node_modules

# Other
.editorconfig
.ebextensions
logging.conf

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment