VM vs Container
-
VMs have their own OS. Therefore each VM can be in GBs.
-
Therefore, VMs will take more time to boot up.
-
On the other hand containers share the OS and only have their own binaries/libraries with a shared container runtime.
-
Which causes the images lightweight and the boot time faster.
-
Each VM is a node and there are one or more containers are inside a node. These are managed by orchastrators like k8s. Nomad from Hashicorp and Docker Swarm are two other orchastrators.
Note: There is much more nuance to "performance" than this chart can capture. A VM or container doesn't inherently sacrifice much performance relative to the bare metal it runs on, but being able to have more control over things like connected storage, physical proximity of the system relative to others it communicates with, specific hardware accelerators, etc... do enable performance tuning.
- Namespaces
- Control groups (Cgroups)
- Union Filesystem
Docker Desktop Architecture
Building Container Images
General principles to build Docker image
Optimization | Security | Build Speed | Clarity |
---|---|---|---|
Pin specific versions | β | β | β |
Base images (either major +minor OR SHA256 hash) | β | β | |
System Dependencies | β | β | |
Application Dependencies | β | β | |
Use small + secure base images | β | β | |
Protect the layer cache | β | β | |
Order commands by frequency of change | β | ||
COPY dependency requirements file β install deps β copy remaining source code | β | ||
Use cache mounts | β | ||
Use COPY --link | β | ||
Combine steps that are always linked (use heredocs to improve tidiness) | β | β | |
Be explicit | β | β | |
Set working directory with WORKDIR | β | ||
Indicate standard port with EXPOSE | β | ||
Set default environment variables with ENV | β | β | |
Avoid unnecessary files | β | β | β |
Use .dockerignore | β | β | β |
COPY specific files | β | β | β |
Use non-root USER | β | ||
Install only production dependencies | β | β | β |
Avoid leaking sensitive information | β | ||
Leverage multi-stage builds | β | β |
A sample best Docker image
# syntax=docker/dockerfile:1.5
FROM node:19.4-bullseye AS build
# Specify working directory other than /
WORKDIR /usr/src/app
# Copy only files required to install
# dependencies (better layer caching)
COPY package*.json ./
# Use cache mount to speed up install of existing dependencies
RUN --mount=type=cache,target=/usr/src/app/.npm \
npm set cache /usr/src/app/.npm && \
npm install
COPY . .
RUN npm run build
# Use separate stage for deployable image
FROM nginxinc/nginx-unprivileged:1.23-alpine-perl
# Use COPY --link to avoid breaking cache if we change the second stage base image
COPY --link nginx.conf /etc/nginx/conf.d/default.conf
COPY --link --from=build usr/src/app/dist/ /usr/share/nginx/html
EXPOSE 8080
Additional Features
# syntax=docker/dockerfile:1.5
# escape=\
# ^ OPTIONAL "directives" (must be at top if used)
# THIS IS A COMMENT
# ARG is the only instruction that can come before FROM
ARG BASE_IMAGE_TAG=19.4
# ARGs can be overriden at build time
# > docker build --build-arg BASE_VERSION=19.3 .
FROM node:${BASE_IMAGE_TAG}
LABEL org.opencontainers.image.authors="[email protected]"
RUN echo "Hey Team π (shell form)"
RUN ["echo", "Hey Team π (exec form)"]
# Heredocs allow for specifying multiple commands to
# be run within a single step, across multiple lines
# without lots of && and \
RUN <<EOF
apt update
apt install iputils-ping -y
EOF
# --mount allows for mounting additional files
# into the build context
# RUN --mount=type=bind ...
# RUN --mount=type=cache ...
# RUN --mount=type=ssh ...
RUN --mount=type=secret,id=secret.txt,dst=/container-secret.txt \
echo "Run the command that requires access to the secret here"
# Available only at build time
# (Still in image metadata though...)
ARG BUILD_ARG=foo
# Available at build and run time
ENV ENV_VAR=bar
# Set the default working directory
# Use the convention of your language/framework
WORKDIR path/to/the/working/directory
ENTRYPOINT [ "echo", "Hey Team π (entrypoint)" ]
CMD [ "+ (cmd)" ]
Container Registry
Running Containers
with Docker compose.
https://www.chainguard.dev/ provides secure docker images.
sneak and trivy to scan docker images.
Image Security
Β«What vulnerabilities exist in your image
that an attacker could exploit?"
β’ Keep attack surface area as small as possible:
β’ Use minimal base images (multi-stage builds are a key
enabler)
β’ Don't install things you don't need (don't install dev deps)
β’ Scan images!
β’ Use users with minimal permissions
β’ Keep sensitive info out of images
β’ Sign and verify images
β’ Use fixed image tags
β’ Either pin major.minor (allows patch fixes to be integrated)
β’ Pin specific image hash
Runtime Security
If an attacker successfully compromises a
container, what can they do? How difficult
will it be to move laterally?
β’ Docker daemon (dockerd)
β’ Start with --userns-remap option
(https://docs.docker.com/engine/security/userns-remap/
β’ Individual containers:
β’ Use read only filesystem if writes are not needed
β’ --cap-drop=all, then --cap-add anything you need
β’ Limit cpu and memory --cpus="0.5" --memory 1024m
β’ Use β security-opt
β’ seccomp profiles (https://docs.docker.com/engine/
security/seccomp/
β’ apparmor profiles (https://docs.docker.com/engine/
security/ apparmor/)
Developer Experience
β’ Easy/simple set up
β’ Iterate without needing to rebuild container image
β’ Bind mount code into container
β’ Use hot reloading utilities
β’ Include profiling and debugging tooling
β’ Debug specific compose overlay file
β’ Execute tests within container
β’ Test specific compose overlay file
β’ Continuous Integration
β’ Ephemeral environments
Resources
- Sample App: https://github.com/sidpalas/devops-directive-docker-course/tree/main/05-example-web-application
- Dockerfiles: https://github.com/sidpalas/devops-directive-docker-course/tree/main/06-building-container-images
- Docker-Compose: https://github.com/sidpalas/devops-directive-docker-course/tree/main/11-development-workflow
- Docker CI/CD Automation: https://github.com/BretFisher/docker-ci-automation
Resume from 2:24:43
Complete Docker Course - From BEGINNER to PRO! (Learn Containers) - YouTube