Best practices for using docker
Use official Docker images as base image.
- cleaner dockerfile
- verified and already built with best practices
- official docker image
Use specific image versions
- you might get different docker image versions
- might break stuff
- latest tag is unpredictable
Use small-sized official images(
alpline
version)- full blown OS distro with lots of tools installed inside uses larger image size
and more security vulnerabilities - leaner OS distro only bundle necessary utilities
- full blown OS distro with lots of tools installed inside uses larger image size
Optimize caching image layers
- order
Dockerfile
commands from least to most frequently changing,
this way optimize how fast the image gets build
- order
Use
.dockerignore
file to explicitly exclude files and folders in order to:- reduce image size
- prevent unintended secrets exposure
Make use of “Multi-Stagte Builds”
less dependencies and much smaller in size some contents in the project that you need for building the image during the build process but don’t need them in the final image that will increase the image size and the attack surface some.
a specific example for this ispackage.json
,palm.xml
or any other dependencies file.
more interesting use case is when building java based applications for example, we need jdk to compile the java source code but jdk is not needed to run the java application itself. that you might be using tools likemaven
orgradle
to build your java application those are also not needed in the final image.“Multi-Stagte” builds feature allows you to use multiple temporary.
an example docker file with two build stages:1
2
3
4
5
6
7
8
9# Build stage
FROM maven AS build
WORKDIR /app
COPY myapp /app
RUN mvn package1
2
3
4
5
6
7
8# Run stage
# we use the files generated in the previous build stage and copy them in the final iamge
# so the final application image is created only in the last stage
FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/myapp.war
Use the least privileged user
the bad security practices
- container could potentially have root access on the Docker host default when a docker file does not specify a user, it uses a root user but reality there is mostly no reason to run container with root privileges
- easier privilege escalation for an attacker. application inside the container with a root user will make it eaiser for an attacker to escalate privileges on the host and basically get hold of the underlying host and its processes,
not only inside the container itself especially if the application inside the container is vulnerable to exploitation
to avoid this is simply create a dedicated user and the dedicated group in the docker
1
2
3
4
5
6
7
8
9
10# create group and user
RUN groupadd -r foo && useradd -g foo foo
# set owership and permissions
RUN chown -R foo:foo /app
# switch to user
USER foo
CMD node index.jssome base images have a generic user bundled in which you can use , so you don’t have to create new one:
1
2
3
4
5RUN node:10-alpline
USER node
CMD ["node", "index.js"]
Scan your images for vulnerabilities
- uses the docker scan commands
docker scan [image-name]
- uses
snyk
to to the vulnerability scanning - configure docker hub to scan the images automatically
- uses the docker scan commands