use COPY, not ADD (if you do not have good reason to). COPY only supports the basic copying of local files into the container, while ADD has some features (like local-only tar extraction and remote URL support) that are not immediately obvious
after npm i run npm cache-clean --force to make your image as small as possible
CMD ["node","index.js"], instead of CMD ["npm","start"] – npm requires another process and we are not literal as we should be in Dockerfile. There is also a problem with handling signal termination by npm. For more details look here.
use WORKDIR /folder instead of RUN mkdir /folder & RUN cd /folder – WORKDIR will create folder if not exists and cd to it. WORKDIR creates folders with root:root permissions.
use unprivileged user, in node : USER node – only CMD, ENTRYPOINT & RUN will be run as user that has been set. No matter where you will change user.
COPY twice: package-lock.json and after npm i -> copy the rest of the project . .
use apt commands once and as soon as possible
build and image using a Dockerfile from STDIN, without sending build context – it will not sent any file as build context to the daemon – thus the build itself will be faster. It can be useful, when your Dockerfile does not require files to be copied into the image
if need some files from the context, but not all of them, use .dockerignore
each container should have only one concern
only the instructions RUN, COPY, ADD create layers. Other instructions create temporary intermediate images, and do not increase the size of the build.
sort multi-line arguments
if you do not want to use the cache at all, you can use the --no-cache=true option on the docker build command
once the cache is invalidated, all subsequent Dockerfile commands generate new images and the cache is not used
always combine RUN apt-get update with apt-get install in the same RUN statement
clean up apt cache by running rm -rf /var/lib/apt/lists/* after running the apt update && apt upgrade. Official Debian and Ubuntu images automatically run apt-get clean, so explicit invocation is not required.
CMD should almost always be used in the form of CMD ["executable", "param1", "param2"…]
the best use for ENTRYPOINT is to set the image’s main command, allowing that image to be run as though it was that command (and then use CMD as the default flags).
for clarity and reliability, you should always use absolute paths for your WORKDIR
an ONBUILD command executes after the current Dockerfile build completes. A Docker build executes ONBUILD commands before any command in a child Dockerfile. Images built with ONBUILD should get a separate tag, for example: ruby:1.9-onbuild
Dockerfile should specify at least one of CMD or ENTRYPOINT commands
ENTRYPOINT should be defined when using the container as an executable
CMD should be used as a way of defining default arguments for an ENTRYPOINT command or for executing an ad-hoc command in a container
CMD will be overridden when running the container with alternative arguments
stick to even image versions – those tend to be LTS
use current official images as the basis for your images