SlideShare a Scribd company logo
Tibor Vass
Docker, Inc.
Dockerfile Best Practices
Sebastiaan van Stijn
Docker, Inc.
@tiborvass @thaJeztah
Dockerfile
A blueprint to build Docker images
Popular: 1+ million Dockerfiles on GitHub
https://docs.docker.com/engine/reference/builder/
Use latest Docker, enable BuildKit today!
Docker client:
export DOCKER_BUILDKIT=1
Docker daemon config:
{
"features": {"buildkit": true}
}
Windows support
coming soon
Quick refresher
image: template to instantiate running containers.
References list of filesystem layers
layer: a list of changes to a rootfs
copy-on-write filesystem: allows smaller disk usage
Quick refresher on Images
Quick refresher on Build
Parse Dockerfile and get build steps to perform
build caching: no need to perform build steps where files or RUN line
have not changed, reuse cached layers
build context: local files that can be copied to the image
Improving Dockerfiles
- Consistency/Repeatability
- (Incremental) build time
- Image size
- Maintainability
Areas of improvements
-rw-r--r-- 1 656 Dec 4 12:20 Dockerfile
drwxr-xr-x 2 6.1M Dec 4 09:44 docs/
-rw-r--r-- 1 1.7K Dec 3 09:48 pom.xml
-rw-r--r-- 1 1.0K Dec 4 10:12 README.md
drwxr-xr-x 4 44K Dec 3 09:48 src/
drwxr-xr-x 2 17M Dec 4 09:50 target/
Basic Java Spring Hello world web app
Example project
FROM debian
COPY . /app
RUN apt-get update
RUN apt-get -y install openjdk-8-jdk ssh emacs
CMD ["java", "-jar", "/app/target/app.jar"]
Let’s improve this Dockerfile
Let’s improve this Dockerfile
FROM debian
COPY . /app
RUN apt-get update
RUN apt-get -y install openjdk-8-jdk ssh emacs vim
CMD ["java", "-jar", "/app/target/app.jar"]
Order matters for caching
FROM debian
COPY . /app
RUN apt-get update
RUN apt-get -y install openjdk-8-jdk ssh vim
COPY . /app
CMD ["java", "-jar", "/app/target/app.jar"]
Order matters for caching
FROM debian
RUN apt-get update
RUN apt-get -y install openjdk-8-jdk ssh vim
COPY . /app
CMD ["java", "-jar", "/app/target/app.jar"]
More specific COPY to limit cache bust
FROM debian
RUN apt-get update
RUN apt-get -y install openjdk-8-jdk ssh vim
COPY . /app
COPY target/app.jar /app
CMD ["java", "-jar", "/app/target/app.jar"]
More specific COPY to limit cache bust
FROM debian
RUN apt-get update
RUN apt-get -y install openjdk-8-jdk ssh vim
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Pro Tip! Use COPY, not ADD for local files
More specific COPY to limit cache bust
FROM debian
RUN apt-get update
RUN apt-get -y install openjdk-8-jdk ssh vim
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Identify cacheable "units"
FROM debian
RUN apt-get update
RUN apt-get -y install openjdk-8-jdk ssh vim
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Line buddies: apt-get update & install
FROM debian
RUN apt-get update
RUN apt-get -y install openjdk-8-jdk ssh vim
RUN apt-get update && apt-get -y install 
openjdk-8-jdk ssh vim
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Line buddies: apt-get update & install
FROM debian
RUN apt-get update && apt-get -y install 
openjdk-8-jdk ssh vim
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Remove unnecessary dependencies
FROM debian
RUN apt-get update && apt-get -y install 
openjdk-8-jdk ssh vim
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Remove unnecessary dependencies
FROM debian
RUN apt-get update && apt-get -y install 
openjdk-8-jdk
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Use --no-install-recommends
FROM debian
RUN apt-get update && 
apt-get -y install --no-install-recommends 
openjdk-8-jdk
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Remove package manager cache
FROM debian
RUN apt-get update && 
apt-get -y install --no-install-recommends 
openjdk-8-jdk 
&& rm -rf /var/lib/apt/lists/*
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Remove package manager cache
FROM debian
RUN apt-get update && 
apt-get -y install --no-install-recommends 
openjdk-8-jdk 
&& rm -rf /var/lib/apt/lists/*
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Reuse official images when possible
FROM debian
RUN apt-get update && 
apt-get -y install --no-install-recommends 
openjdk-8-jdk
&& rm -rf /var/lib/apt/lists/*
FROM openjdk
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Reuse official images when possible
- Reduce time spent on maintenance
(frequently updated with fixes)
- Reduce size (shared layers between images)
- Pre-configured for container use
- Built by smart people
- Bonus: scanned for vulnerabilities on Docker Hub
Reuse official images when possible
FROM openjdk
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Use more specific tags
FROM openjdk:latest
FROM openjdk:8
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Use more specific tags
FROM openjdk:8
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Use more specific tags
Read the image's documentation on
Docker Hub
https://hub.docker.com/_/openjdk
Use more specific tags
FROM openjdk:8-jre
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Use more specific tags
FROM openjdk:8-jre
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Look for minimal flavors
FROM openjdk:8-jre-slim
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Look for minimal flavors
FROM openjdk:8-jre-slim
FROM openjdk:8-jre-alpine
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Look for minimal flavors
REPOSITORY TAG SIZE
openjdk 8 624MB
openjdk 8-jre 443MB
openjdk 8-jre-slim 204MB
openjdk 8-jre-alpine 83MB
Look for minimal flavors
FROM openjdk:8-jre-alpine
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Look for reproducibility
FROM openjdk:8-jre-alpine
COPY target/app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Build from source in a consistent environment
- Build environment is described in the Dockerfile
- Correct versions of build tools installed
- Prevent inconsistencies between environments
- There may be system dependencies
- The "source of truth" is the source code not the build artifact
Build from source in a consistent environment
FROM openjdk:8-jre-alpine
FROM maven:3.6-jdk-8-alpine
COPY app.jar /app
COPY pom.xml /app/
COPY src /app/src
RUN cd /app && mvn -e -B package
CMD ["java", "-jar", "/app/app.jar"]
Build from source in a consistent environment
FROM maven:3.6-jdk-8-alpine
COPY pom.xml /app/
COPY src /app/src
RUN cd /app && mvn -e -B package
CMD ["java", "-jar", "/app/app.jar"]
Build from source in a consistent environment
FROM maven:3.6-jdk-8-alpine
WORKDIR /app
COPY pom.xml /app/.
COPY src /app./src
RUN cd /app && mvn -e -B package
CMD ["java", "-jar", "/app/app.jar"]
Build from source in a consistent environment
FROM maven:3.6-jdk-8-alpine
WORKDIR /app
COPY pom.xml .
COPY src ./src
RUN mvn -e -B package
CMD ["java", "-jar", "/app/app.jar"]
Cache dependencies
FROM maven:3.6-jdk-8-alpine
WORKDIR /app
COPY pom.xml .
RUN mvn -e -B dependency:resolve
COPY src ./src
RUN mvn -e -B package
CMD ["java", "-jar", "/app/app.jar"]
Cache dependencies
FROM maven:3.6-jdk-8-alpine
WORKDIR /app
COPY pom.xml .
RUN mvn -e -B dependency:resolve
COPY src ./src
RUN mvn -e -B package
CMD ["java", "-jar", "/app/app.jar"]
Identify build dependencies
FROM maven:3.6-jdk-8-alpine
WORKDIR /app
COPY pom.xml .
RUN mvn -e -B dependency:resolve
COPY src ./src
RUN mvn -e -B package
CMD ["java", "-jar", "/app/app.jar"]
Multi-stage builds to remove build deps
FROM maven:3.6-jdk-8-alpine
WORKDIR /app
COPY pom.xml .
RUN mvn -e -B dependency:resolve
COPY src ./src
RUN mvn -e -B package
FROM maven:3.6-jdk-8-alpine AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn -e -B dependency:resolve
COPY src ./src
RUN mvn -e -B package
CMD ["java", "-jar", "/app/app.jar"]
FROM openjdk:8-jre-alpine
COPY --from=builder /app/target/app.jar /
CMD ["java", "-jar", "/app.jar"]
Multi-stage builds to remove build deps
FROM maven:3.6-jdk-8-alpine AS builder
WORKDIR /app
COPY pom.xml .
RUN mvn -e -B dependency:resolve
COPY src ./src
RUN mvn -e -B package
FROM openjdk:8-jre-alpine
COPY --from=builder /app/target/app.jar /
CMD ["java", "-jar", "/app.jar"]
Multi-stage builds to remove build deps
- Moby: 16 stages
https://github.com/moby/moby/blob/master/Dockerfile
- BuildKit: 44 stages
https://github.com/moby/buildkit/blob/master/hack/do
ckerfiles/test.buildkit.Dockerfile
Projects with many stages
- Separate build from runtime environment
(shrinking image size)
- Slight variations on images
- DRY (Don’t Repeat Yourself)
- Build/dev/test/lint environments
- Concurrent stages
- Platform-specific stages
Multi-stage usecases
FROM maven:3.6-jdk-8-alpine AS builder
...
FROM openjdk:8-jre-jessie AS release-jessie
COPY --from=builder /app/target/app.jar /
CMD ["java", "-jar", "/app.jar"]
FROM openjdk:8-jre-alpine AS release-alpine
COPY --from=builder /app/target/app.jar /
CMD ["java", "-jar", "/app.jar"]
docker build --target X
FROM maven:3.6-jdk-8-alpine AS builder
...
FROM openjdk:8-jre-jessie AS release-jessie
COPY --from=builder /app/target/app.jar /
CMD ["java", "-jar", "/app.jar"]
FROM openjdk:8-jre-alpine AS release-alpine
COPY --from=builder /app/target/app.jar /
CMD ["java", "-jar", "/app.jar"]
docker build --target X
FROM maven:3.6-jdk-8-alpine AS builder
...
FROM openjdk:8-jre-jessie AS release-jessie
COPY --from=builder /app/app.jar /
CMD ["java", "-jar", "/app.jar"]
FROM openjdk:8-jre-alpine AS release-alpine
COPY --from=builder /app/app.jar /
CMD ["java", "-jar", "/app.jar"]
docker build --target X
ARG flavor=alpine
FROM maven:3.6-jdk-8-alpine AS builder
...
FROM openjdk:8-jre-$flavor AS release
COPY --from=builder /app/target/app.jar /
CMD ["java", "-jar", "/app.jar"]
Global ARG: docker build --build-arg K=V
FROM maven:3.6-jdk-8-alpine AS builder
...
FROM openjdk:8-jre-alpine AS lint
RUN wget https://github.com/checkstyle/checkstyle/releases/download/checkstyle-8.15/checkstyle-8.15-all.jar
COPY checks.xml .
COPY src /src
RUN java -jar checkstyle-8.15-all.jar -c checks.xml /src
Various environments: build, dev, test, lint, ...
FROM maven:3.6-jdk-8-alpine AS builder
...
FROM openjdk:8-jre-alpine AS release
COPY --from=builder /app/target/app.jar /
CMD ["java", "-jar", "/app.jar"]
FROM builder AS dev
RUN apk add --no-cache strace
ENTRYPOINT ["ash"]
Various environments: build, dev, test, lint, ...
FROM maven:3.6-jdk-8-alpine AS builder
...
RUN mvn -e -B package -DskipTests
FROM builder AS unit-test
RUN mvn -e -B test
FROM release AS integration-test
RUN apk add --no-cache curl
RUN ./test/run.sh
Various environments: build, dev, test, lint, ...
FROM maven:3.6-jdk-8-alpine AS builder
...
FROM tiborvass/whalesay AS assets
RUN whalesay "¡Hola DockerCon!" > /out/assets.html
FROM openjdk:8-jre-alpine AS release
COPY --from=builder /app/app.jar /
COPY --from=assets /out /assets
CMD ["java", "-jar", "/app.jar"]
Multi-stage: build concurrently
Benchmarks
Based on github.com/moby/moby Dockerfile, master branch. Smaller is better.
Time for full build from empty state
2.0x
faster
Benchmarks
Based on github.com/moby/moby Dockerfile, master branch. Smaller is better.
Repeated build with matching cache
7.2x
faster
Benchmarks
Based on github.com/moby/moby Dockerfile, master branch. Smaller is better.
Repeated build with new source code
2.5x
faster
Some new Dockerfile
features in v18.09
“Supercharged Docker Build with BuildKit”
BlackBelt session Wednesday 12pm
- What’s new
- New Dockerfile features (RUN --mount, secrets, ssh,
syntax customization)
# syntax = docker/dockerfile:1.0-experimental
# syntax=docker/dockerfile:1.0-experimental
FROM maven:3.6-jdk-8-alpine AS builder
WORKDIR /app
COPY . /app
RUN mvn -e -B package
FROM openjdk:8-jre-alpine
COPY --from=builder /app/app.jar /
CMD ["java", "-jar", "/app.jar"]
Context mounts (v18.09 only)
# syntax=docker/dockerfile:1.0-experimental
FROM maven:3.6-jdk-8-alpine AS builder
WORKDIR /app
COPY . /app
RUN --mount=target=. mvn -e -B package -DoutputDirectory=/
FROM openjdk:8-jre-alpine
COPY --from=builder /app/app.jar /
CMD ["java", "-jar", "/app.jar"]
Context mounts (v18.09 only)
# syntax=docker/dockerfile:1.0-experimental
FROM maven:3.6-jdk-8-alpine AS builder
WORKDIR /app
RUN --mount=target=. mvn -e -B package -DoutputDirectory=/
FROM openjdk:8-jre-alpine
COPY --from=builder /app.jar /
CMD ["java", "-jar", "/app.jar"]
Application cache (v18.09 only)
# syntax=docker/dockerfile:1.0-experimental
FROM maven:3.6-jdk-8-alpine AS builder
WORKDIR /app
RUN --mount=target=. --mount=type=cache,target=/root/.m2 
&& mvn package -DoutputDirectory=/
FROM openjdk:8-jre-alpine
COPY --from=builder /app.jar /
CMD ["java", "/app.jar"]
We went from:
- inconsistent build/dev/test environments
- bloated image
- slow build and incremental build times (cache busts)
To:
- consistent build/dev/test environments
- minimal image
- very fast build and incremental build times
Improvements recap
Read more on blog posts
https://medium.com/@tonistiigi/advanced-
multi-stage-build-patterns-6f741b852fae
https://medium.com/@tonistiigi/build-secrets-an
d-ssh-forwarding-in-docker-18-09-ae8161d066
• Multi-stage, multi-stage, multi-stage
• Enable BuildKit
• Supercharged Docker Build with
BuildKit in BlackBelt session on
Wednesday at 12pm
Thank you!
Take A Breakout Survey
Access your session and/or workshop surveys for the conference at any time by tapping the Sessions
link on the navigation menu or block on the home screen.
Find the session/workshop you attended and tap on it to view the session details. On this page, you will
find a link to the survey.
DCEU 18: Dockerfile Best Practices
Run as an unprivileged user
FROM openjdk:8-jre-alpine
RUN addgroup -g 50 -S appuser 
&& adduser -D -S -h /app -s /sbin/nologin 
-u 1000 -G appuser appuser
USER appuser:appuser
COPY app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
Run as an unprivileged user
FROM openjdk:8u181-jre-alpine
RUN addgroup -g 50 -S appuser 
&& adduser -D -S -h /app -s /sbin/nologin 
-u 1000 -G appuser appuser
USER appuser:appuser
COPY app.jar /app
CMD ["java", "-jar", "/app/app.jar"]
# syntax=docker/dockerfile:1.0-experimental
FROM ...
RUN --mount=type=secret,id=mysecret,required ...
$ docker build --secret id=mysecret,src=/local/secret .
Build secrets
# syntax=docker/dockerfile:1.0-experimental
FROM ...
RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git
$ docker build --ssh default
SSH
Docker Product / Feature Icons
Container Image Registry Control Plane
Product symbols:
• OK to change size (proportionally)
• OK to change color
• NO changes to shapes, direction, or design
• (ok to change ”service” design)
Service (swarm)
Pod (kubernetes)
Group of
containers
or
Icons
Computer, PC, terminal, laptop, device
Mobile watch
Server, data center
Storage
database
NetworkGlobe, location Layer, vm
VM
Edge DeviceDevelop dev
Cloud
Repair tune
CI /
CD
Metrics, alert, dashboard Monitor, logging,
operations configure
Relationship,
hierarchy, process, integration, arrows,
cycle
Check
Calendar,
date
CI /
CD
Clocks,
speed, time
Security, secure, Scan, key, sign, encrypt
firewall
Process, relationship, hierarchy, cycle
integrate
Chain, brokentrust
People MiscPeople
executive
architect
practitioner
developer
Generic
male
Operator, support
Hands - Shake
Agreement - button
group
Generic
female
Generic
speaker
• 20+ Websites for Incredible Free Stock Photos
− https://mymodernmet.com/best-free-stock-photography-websites/
− Includes sites focusing on food, nature, places, vintage, humorous/whimsical as well as
general photo sites
• 21 Amazing Sites With Breathtaking Free Stock Photos
− https://blog.snappa.com/free-stock-photos/
Generic Block Diagrams
Calls to Action
Summary Groups   
DCEU 18: Dockerfile Best Practices

More Related Content

PDF
DCSF19 Dockerfile Best Practices
PDF
Docker Best Practices Workshop
PPTX
Multi Stage Docker Build
PDF
Introduction to Docker storage, volume and image
PPTX
Docker 101 - Nov 2016
PDF
Optimizing Docker Images
PPTX
Docker Tutorial For Beginners | What Is Docker And How It Works? | Docker Tut...
PPTX
Docker: From Zero to Hero
DCSF19 Dockerfile Best Practices
Docker Best Practices Workshop
Multi Stage Docker Build
Introduction to Docker storage, volume and image
Docker 101 - Nov 2016
Optimizing Docker Images
Docker Tutorial For Beginners | What Is Docker And How It Works? | Docker Tut...
Docker: From Zero to Hero

What's hot (20)

PPTX
Docker Basics
PDF
Docker vs VM | | Containerization or Virtualization - The Differences | DevOp...
PPTX
Introduction to Docker - 2017
PPTX
Build, Publish, Deploy and Test Docker images and containers with Jenkins Wor...
PDF
Introduction to Docker Compose
PDF
Introduction to Docker
PPTX
Jenkins tutorial
PDF
Virtual Machines and Docker
PPT
Docker introduction
PDF
Dockerfile
PDF
Jenkins
PPTX
Docker Compose | Docker Compose Tutorial | Docker Tutorial For Beginners | De...
PDF
Docker Birthday #3 - Intro to Docker Slides
PPTX
Introduction to docker
PDF
docker installation and basics
PDF
Introduction to container based virtualization with docker
PDF
Docker in real life
PDF
Docker Swarm 0.2.0
PDF
Intro To Docker
PDF
Docker compose
Docker Basics
Docker vs VM | | Containerization or Virtualization - The Differences | DevOp...
Introduction to Docker - 2017
Build, Publish, Deploy and Test Docker images and containers with Jenkins Wor...
Introduction to Docker Compose
Introduction to Docker
Jenkins tutorial
Virtual Machines and Docker
Docker introduction
Dockerfile
Jenkins
Docker Compose | Docker Compose Tutorial | Docker Tutorial For Beginners | De...
Docker Birthday #3 - Intro to Docker Slides
Introduction to docker
docker installation and basics
Introduction to container based virtualization with docker
Docker in real life
Docker Swarm 0.2.0
Intro To Docker
Docker compose
Ad

Similar to DCEU 18: Dockerfile Best Practices (20)

PDF
Docker for developers on mac and windows
PPTX
Optimizing Spring Boot apps for Docker
PDF
PuppetConf 2016: The Challenges with Container Configuration – David Lutterko...
PDF
Challenges of container configuration
PPTX
PPTX
Pluralsight Webinar: Simplify Your Project Builds with Docker
PPTX
Docker best practices
PPTX
Running Docker in Development & Production (DevSum 2015)
PDF
Streamline your development environment with docker
PDF
Gdg cloud taipei ddt meetup #53 buildpack
PDF
The Dockerfile Explosion and the Need for Higher Level Tools by Gareth Rushgrove
PDF
Docker for Ruby Developers
PPTX
tips for generating docker containers complaints with the devsecops
PDF
Vagrant or docker for java dev environment
PDF
Fargate 를 이용한 ECS with VPC 1부
PDF
Deployment Automation with Docker
PPTX
Into to Docker (Central PA Java User Group - 8/14/2017)
PPTX
Environment
PDF
Deep Dive Java 17 Devoxx UK
PDF
Infrastructure = code - 1 year later
Docker for developers on mac and windows
Optimizing Spring Boot apps for Docker
PuppetConf 2016: The Challenges with Container Configuration – David Lutterko...
Challenges of container configuration
Pluralsight Webinar: Simplify Your Project Builds with Docker
Docker best practices
Running Docker in Development & Production (DevSum 2015)
Streamline your development environment with docker
Gdg cloud taipei ddt meetup #53 buildpack
The Dockerfile Explosion and the Need for Higher Level Tools by Gareth Rushgrove
Docker for Ruby Developers
tips for generating docker containers complaints with the devsecops
Vagrant or docker for java dev environment
Fargate 를 이용한 ECS with VPC 1부
Deployment Automation with Docker
Into to Docker (Central PA Java User Group - 8/14/2017)
Environment
Deep Dive Java 17 Devoxx UK
Infrastructure = code - 1 year later
Ad

More from Docker, Inc. (20)

PDF
Containerize Your Game Server for the Best Multiplayer Experience
PDF
How to Improve Your Image Builds Using Advance Docker Build
PDF
Build & Deploy Multi-Container Applications to AWS
PDF
Securing Your Containerized Applications with NGINX
PDF
How To Build and Run Node Apps with Docker and Compose
PDF
Hands-on Helm
PDF
Distributed Deep Learning with Docker at Salesforce
PDF
The First 10M Pulls: Building The Official Curl Image for Docker Hub
PDF
Monitoring in a Microservices World
PDF
COVID-19 in Italy: How Docker is Helping the Biggest Italian IT Company Conti...
PDF
Predicting Space Weather with Docker
PDF
Become a Docker Power User With Microsoft Visual Studio Code
PDF
How to Use Mirroring and Caching to Optimize your Container Registry
PDF
Monolithic to Microservices + Docker = SDLC on Steroids!
PDF
Kubernetes at Datadog Scale
PDF
Labels, Labels, Labels
PDF
Using Docker Hub at Scale to Support Micro Focus' Delivery and Deployment Model
PDF
Build & Deploy Multi-Container Applications to AWS
PDF
From Fortran on the Desktop to Kubernetes in the Cloud: A Windows Migration S...
PDF
Developing with Docker for the Arm Architecture
Containerize Your Game Server for the Best Multiplayer Experience
How to Improve Your Image Builds Using Advance Docker Build
Build & Deploy Multi-Container Applications to AWS
Securing Your Containerized Applications with NGINX
How To Build and Run Node Apps with Docker and Compose
Hands-on Helm
Distributed Deep Learning with Docker at Salesforce
The First 10M Pulls: Building The Official Curl Image for Docker Hub
Monitoring in a Microservices World
COVID-19 in Italy: How Docker is Helping the Biggest Italian IT Company Conti...
Predicting Space Weather with Docker
Become a Docker Power User With Microsoft Visual Studio Code
How to Use Mirroring and Caching to Optimize your Container Registry
Monolithic to Microservices + Docker = SDLC on Steroids!
Kubernetes at Datadog Scale
Labels, Labels, Labels
Using Docker Hub at Scale to Support Micro Focus' Delivery and Deployment Model
Build & Deploy Multi-Container Applications to AWS
From Fortran on the Desktop to Kubernetes in the Cloud: A Windows Migration S...
Developing with Docker for the Arm Architecture

Recently uploaded (20)

PDF
Modernizing your data center with Dell and AMD
PDF
Approach and Philosophy of On baking technology
PDF
[발표본] 너의 과제는 클라우드에 있어_KTDS_김동현_20250524.pdf
PDF
Per capita expenditure prediction using model stacking based on satellite ima...
PDF
Diabetes mellitus diagnosis method based random forest with bat algorithm
PDF
Dropbox Q2 2025 Financial Results & Investor Presentation
PDF
NewMind AI Monthly Chronicles - July 2025
DOCX
The AUB Centre for AI in Media Proposal.docx
PPTX
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
PDF
Chapter 3 Spatial Domain Image Processing.pdf
PDF
cuic standard and advanced reporting.pdf
PPTX
20250228 LYD VKU AI Blended-Learning.pptx
PDF
Network Security Unit 5.pdf for BCA BBA.
PDF
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
PDF
Advanced IT Governance
PDF
Machine learning based COVID-19 study performance prediction
PDF
The Rise and Fall of 3GPP – Time for a Sabbatical?
PDF
KodekX | Application Modernization Development
PDF
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
PDF
Bridging biosciences and deep learning for revolutionary discoveries: a compr...
Modernizing your data center with Dell and AMD
Approach and Philosophy of On baking technology
[발표본] 너의 과제는 클라우드에 있어_KTDS_김동현_20250524.pdf
Per capita expenditure prediction using model stacking based on satellite ima...
Diabetes mellitus diagnosis method based random forest with bat algorithm
Dropbox Q2 2025 Financial Results & Investor Presentation
NewMind AI Monthly Chronicles - July 2025
The AUB Centre for AI in Media Proposal.docx
PA Analog/Digital System: The Backbone of Modern Surveillance and Communication
Chapter 3 Spatial Domain Image Processing.pdf
cuic standard and advanced reporting.pdf
20250228 LYD VKU AI Blended-Learning.pptx
Network Security Unit 5.pdf for BCA BBA.
7 ChatGPT Prompts to Help You Define Your Ideal Customer Profile.pdf
Advanced IT Governance
Machine learning based COVID-19 study performance prediction
The Rise and Fall of 3GPP – Time for a Sabbatical?
KodekX | Application Modernization Development
How UI/UX Design Impacts User Retention in Mobile Apps.pdf
Bridging biosciences and deep learning for revolutionary discoveries: a compr...

DCEU 18: Dockerfile Best Practices

  • 1. Tibor Vass Docker, Inc. Dockerfile Best Practices Sebastiaan van Stijn Docker, Inc. @tiborvass @thaJeztah
  • 2. Dockerfile A blueprint to build Docker images Popular: 1+ million Dockerfiles on GitHub
  • 4. Use latest Docker, enable BuildKit today! Docker client: export DOCKER_BUILDKIT=1 Docker daemon config: { "features": {"buildkit": true} } Windows support coming soon
  • 6. image: template to instantiate running containers. References list of filesystem layers layer: a list of changes to a rootfs copy-on-write filesystem: allows smaller disk usage Quick refresher on Images
  • 7. Quick refresher on Build Parse Dockerfile and get build steps to perform build caching: no need to perform build steps where files or RUN line have not changed, reuse cached layers build context: local files that can be copied to the image
  • 9. - Consistency/Repeatability - (Incremental) build time - Image size - Maintainability Areas of improvements
  • 10. -rw-r--r-- 1 656 Dec 4 12:20 Dockerfile drwxr-xr-x 2 6.1M Dec 4 09:44 docs/ -rw-r--r-- 1 1.7K Dec 3 09:48 pom.xml -rw-r--r-- 1 1.0K Dec 4 10:12 README.md drwxr-xr-x 4 44K Dec 3 09:48 src/ drwxr-xr-x 2 17M Dec 4 09:50 target/ Basic Java Spring Hello world web app Example project
  • 11. FROM debian COPY . /app RUN apt-get update RUN apt-get -y install openjdk-8-jdk ssh emacs CMD ["java", "-jar", "/app/target/app.jar"] Let’s improve this Dockerfile
  • 12. Let’s improve this Dockerfile FROM debian COPY . /app RUN apt-get update RUN apt-get -y install openjdk-8-jdk ssh emacs vim CMD ["java", "-jar", "/app/target/app.jar"]
  • 13. Order matters for caching FROM debian COPY . /app RUN apt-get update RUN apt-get -y install openjdk-8-jdk ssh vim COPY . /app CMD ["java", "-jar", "/app/target/app.jar"]
  • 14. Order matters for caching FROM debian RUN apt-get update RUN apt-get -y install openjdk-8-jdk ssh vim COPY . /app CMD ["java", "-jar", "/app/target/app.jar"]
  • 15. More specific COPY to limit cache bust FROM debian RUN apt-get update RUN apt-get -y install openjdk-8-jdk ssh vim COPY . /app COPY target/app.jar /app CMD ["java", "-jar", "/app/target/app.jar"]
  • 16. More specific COPY to limit cache bust FROM debian RUN apt-get update RUN apt-get -y install openjdk-8-jdk ssh vim COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"] Pro Tip! Use COPY, not ADD for local files
  • 17. More specific COPY to limit cache bust FROM debian RUN apt-get update RUN apt-get -y install openjdk-8-jdk ssh vim COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 18. Identify cacheable "units" FROM debian RUN apt-get update RUN apt-get -y install openjdk-8-jdk ssh vim COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 19. Line buddies: apt-get update & install FROM debian RUN apt-get update RUN apt-get -y install openjdk-8-jdk ssh vim RUN apt-get update && apt-get -y install openjdk-8-jdk ssh vim COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 20. Line buddies: apt-get update & install FROM debian RUN apt-get update && apt-get -y install openjdk-8-jdk ssh vim COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 21. Remove unnecessary dependencies FROM debian RUN apt-get update && apt-get -y install openjdk-8-jdk ssh vim COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 22. Remove unnecessary dependencies FROM debian RUN apt-get update && apt-get -y install openjdk-8-jdk COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 23. Use --no-install-recommends FROM debian RUN apt-get update && apt-get -y install --no-install-recommends openjdk-8-jdk COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 24. Remove package manager cache FROM debian RUN apt-get update && apt-get -y install --no-install-recommends openjdk-8-jdk && rm -rf /var/lib/apt/lists/* COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 25. Remove package manager cache FROM debian RUN apt-get update && apt-get -y install --no-install-recommends openjdk-8-jdk && rm -rf /var/lib/apt/lists/* COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 26. Reuse official images when possible FROM debian RUN apt-get update && apt-get -y install --no-install-recommends openjdk-8-jdk && rm -rf /var/lib/apt/lists/* FROM openjdk COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 27. Reuse official images when possible - Reduce time spent on maintenance (frequently updated with fixes) - Reduce size (shared layers between images) - Pre-configured for container use - Built by smart people - Bonus: scanned for vulnerabilities on Docker Hub
  • 28. Reuse official images when possible FROM openjdk COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 29. Use more specific tags FROM openjdk:latest FROM openjdk:8 COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 30. Use more specific tags FROM openjdk:8 COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 31. Use more specific tags Read the image's documentation on Docker Hub https://hub.docker.com/_/openjdk
  • 32. Use more specific tags FROM openjdk:8-jre COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 33. Use more specific tags FROM openjdk:8-jre COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 34. Look for minimal flavors FROM openjdk:8-jre-slim COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 35. Look for minimal flavors FROM openjdk:8-jre-slim FROM openjdk:8-jre-alpine COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 36. Look for minimal flavors REPOSITORY TAG SIZE openjdk 8 624MB openjdk 8-jre 443MB openjdk 8-jre-slim 204MB openjdk 8-jre-alpine 83MB
  • 37. Look for minimal flavors FROM openjdk:8-jre-alpine COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 38. Look for reproducibility FROM openjdk:8-jre-alpine COPY target/app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 39. Build from source in a consistent environment - Build environment is described in the Dockerfile - Correct versions of build tools installed - Prevent inconsistencies between environments - There may be system dependencies - The "source of truth" is the source code not the build artifact
  • 40. Build from source in a consistent environment FROM openjdk:8-jre-alpine FROM maven:3.6-jdk-8-alpine COPY app.jar /app COPY pom.xml /app/ COPY src /app/src RUN cd /app && mvn -e -B package CMD ["java", "-jar", "/app/app.jar"]
  • 41. Build from source in a consistent environment FROM maven:3.6-jdk-8-alpine COPY pom.xml /app/ COPY src /app/src RUN cd /app && mvn -e -B package CMD ["java", "-jar", "/app/app.jar"]
  • 42. Build from source in a consistent environment FROM maven:3.6-jdk-8-alpine WORKDIR /app COPY pom.xml /app/. COPY src /app./src RUN cd /app && mvn -e -B package CMD ["java", "-jar", "/app/app.jar"]
  • 43. Build from source in a consistent environment FROM maven:3.6-jdk-8-alpine WORKDIR /app COPY pom.xml . COPY src ./src RUN mvn -e -B package CMD ["java", "-jar", "/app/app.jar"]
  • 44. Cache dependencies FROM maven:3.6-jdk-8-alpine WORKDIR /app COPY pom.xml . RUN mvn -e -B dependency:resolve COPY src ./src RUN mvn -e -B package CMD ["java", "-jar", "/app/app.jar"]
  • 45. Cache dependencies FROM maven:3.6-jdk-8-alpine WORKDIR /app COPY pom.xml . RUN mvn -e -B dependency:resolve COPY src ./src RUN mvn -e -B package CMD ["java", "-jar", "/app/app.jar"]
  • 46. Identify build dependencies FROM maven:3.6-jdk-8-alpine WORKDIR /app COPY pom.xml . RUN mvn -e -B dependency:resolve COPY src ./src RUN mvn -e -B package CMD ["java", "-jar", "/app/app.jar"]
  • 47. Multi-stage builds to remove build deps FROM maven:3.6-jdk-8-alpine WORKDIR /app COPY pom.xml . RUN mvn -e -B dependency:resolve COPY src ./src RUN mvn -e -B package
  • 48. FROM maven:3.6-jdk-8-alpine AS builder WORKDIR /app COPY pom.xml . RUN mvn -e -B dependency:resolve COPY src ./src RUN mvn -e -B package CMD ["java", "-jar", "/app/app.jar"] FROM openjdk:8-jre-alpine COPY --from=builder /app/target/app.jar / CMD ["java", "-jar", "/app.jar"] Multi-stage builds to remove build deps
  • 49. FROM maven:3.6-jdk-8-alpine AS builder WORKDIR /app COPY pom.xml . RUN mvn -e -B dependency:resolve COPY src ./src RUN mvn -e -B package FROM openjdk:8-jre-alpine COPY --from=builder /app/target/app.jar / CMD ["java", "-jar", "/app.jar"] Multi-stage builds to remove build deps
  • 50. - Moby: 16 stages https://github.com/moby/moby/blob/master/Dockerfile - BuildKit: 44 stages https://github.com/moby/buildkit/blob/master/hack/do ckerfiles/test.buildkit.Dockerfile Projects with many stages
  • 51. - Separate build from runtime environment (shrinking image size) - Slight variations on images - DRY (Don’t Repeat Yourself) - Build/dev/test/lint environments - Concurrent stages - Platform-specific stages Multi-stage usecases
  • 52. FROM maven:3.6-jdk-8-alpine AS builder ... FROM openjdk:8-jre-jessie AS release-jessie COPY --from=builder /app/target/app.jar / CMD ["java", "-jar", "/app.jar"] FROM openjdk:8-jre-alpine AS release-alpine COPY --from=builder /app/target/app.jar / CMD ["java", "-jar", "/app.jar"] docker build --target X
  • 53. FROM maven:3.6-jdk-8-alpine AS builder ... FROM openjdk:8-jre-jessie AS release-jessie COPY --from=builder /app/target/app.jar / CMD ["java", "-jar", "/app.jar"] FROM openjdk:8-jre-alpine AS release-alpine COPY --from=builder /app/target/app.jar / CMD ["java", "-jar", "/app.jar"] docker build --target X
  • 54. FROM maven:3.6-jdk-8-alpine AS builder ... FROM openjdk:8-jre-jessie AS release-jessie COPY --from=builder /app/app.jar / CMD ["java", "-jar", "/app.jar"] FROM openjdk:8-jre-alpine AS release-alpine COPY --from=builder /app/app.jar / CMD ["java", "-jar", "/app.jar"] docker build --target X
  • 55. ARG flavor=alpine FROM maven:3.6-jdk-8-alpine AS builder ... FROM openjdk:8-jre-$flavor AS release COPY --from=builder /app/target/app.jar / CMD ["java", "-jar", "/app.jar"] Global ARG: docker build --build-arg K=V
  • 56. FROM maven:3.6-jdk-8-alpine AS builder ... FROM openjdk:8-jre-alpine AS lint RUN wget https://github.com/checkstyle/checkstyle/releases/download/checkstyle-8.15/checkstyle-8.15-all.jar COPY checks.xml . COPY src /src RUN java -jar checkstyle-8.15-all.jar -c checks.xml /src Various environments: build, dev, test, lint, ...
  • 57. FROM maven:3.6-jdk-8-alpine AS builder ... FROM openjdk:8-jre-alpine AS release COPY --from=builder /app/target/app.jar / CMD ["java", "-jar", "/app.jar"] FROM builder AS dev RUN apk add --no-cache strace ENTRYPOINT ["ash"] Various environments: build, dev, test, lint, ...
  • 58. FROM maven:3.6-jdk-8-alpine AS builder ... RUN mvn -e -B package -DskipTests FROM builder AS unit-test RUN mvn -e -B test FROM release AS integration-test RUN apk add --no-cache curl RUN ./test/run.sh Various environments: build, dev, test, lint, ...
  • 59. FROM maven:3.6-jdk-8-alpine AS builder ... FROM tiborvass/whalesay AS assets RUN whalesay "¡Hola DockerCon!" > /out/assets.html FROM openjdk:8-jre-alpine AS release COPY --from=builder /app/app.jar / COPY --from=assets /out /assets CMD ["java", "-jar", "/app.jar"] Multi-stage: build concurrently
  • 60. Benchmarks Based on github.com/moby/moby Dockerfile, master branch. Smaller is better. Time for full build from empty state 2.0x faster
  • 61. Benchmarks Based on github.com/moby/moby Dockerfile, master branch. Smaller is better. Repeated build with matching cache 7.2x faster
  • 62. Benchmarks Based on github.com/moby/moby Dockerfile, master branch. Smaller is better. Repeated build with new source code 2.5x faster
  • 64. “Supercharged Docker Build with BuildKit” BlackBelt session Wednesday 12pm - What’s new - New Dockerfile features (RUN --mount, secrets, ssh, syntax customization)
  • 65. # syntax = docker/dockerfile:1.0-experimental # syntax=docker/dockerfile:1.0-experimental FROM maven:3.6-jdk-8-alpine AS builder WORKDIR /app COPY . /app RUN mvn -e -B package FROM openjdk:8-jre-alpine COPY --from=builder /app/app.jar / CMD ["java", "-jar", "/app.jar"]
  • 66. Context mounts (v18.09 only) # syntax=docker/dockerfile:1.0-experimental FROM maven:3.6-jdk-8-alpine AS builder WORKDIR /app COPY . /app RUN --mount=target=. mvn -e -B package -DoutputDirectory=/ FROM openjdk:8-jre-alpine COPY --from=builder /app/app.jar / CMD ["java", "-jar", "/app.jar"]
  • 67. Context mounts (v18.09 only) # syntax=docker/dockerfile:1.0-experimental FROM maven:3.6-jdk-8-alpine AS builder WORKDIR /app RUN --mount=target=. mvn -e -B package -DoutputDirectory=/ FROM openjdk:8-jre-alpine COPY --from=builder /app.jar / CMD ["java", "-jar", "/app.jar"]
  • 68. Application cache (v18.09 only) # syntax=docker/dockerfile:1.0-experimental FROM maven:3.6-jdk-8-alpine AS builder WORKDIR /app RUN --mount=target=. --mount=type=cache,target=/root/.m2 && mvn package -DoutputDirectory=/ FROM openjdk:8-jre-alpine COPY --from=builder /app.jar / CMD ["java", "/app.jar"]
  • 69. We went from: - inconsistent build/dev/test environments - bloated image - slow build and incremental build times (cache busts) To: - consistent build/dev/test environments - minimal image - very fast build and incremental build times Improvements recap
  • 70. Read more on blog posts https://medium.com/@tonistiigi/advanced- multi-stage-build-patterns-6f741b852fae https://medium.com/@tonistiigi/build-secrets-an d-ssh-forwarding-in-docker-18-09-ae8161d066
  • 71. • Multi-stage, multi-stage, multi-stage • Enable BuildKit • Supercharged Docker Build with BuildKit in BlackBelt session on Wednesday at 12pm Thank you!
  • 72. Take A Breakout Survey Access your session and/or workshop surveys for the conference at any time by tapping the Sessions link on the navigation menu or block on the home screen. Find the session/workshop you attended and tap on it to view the session details. On this page, you will find a link to the survey.
  • 74. Run as an unprivileged user FROM openjdk:8-jre-alpine RUN addgroup -g 50 -S appuser && adduser -D -S -h /app -s /sbin/nologin -u 1000 -G appuser appuser USER appuser:appuser COPY app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 75. Run as an unprivileged user FROM openjdk:8u181-jre-alpine RUN addgroup -g 50 -S appuser && adduser -D -S -h /app -s /sbin/nologin -u 1000 -G appuser appuser USER appuser:appuser COPY app.jar /app CMD ["java", "-jar", "/app/app.jar"]
  • 76. # syntax=docker/dockerfile:1.0-experimental FROM ... RUN --mount=type=secret,id=mysecret,required ... $ docker build --secret id=mysecret,src=/local/secret . Build secrets
  • 77. # syntax=docker/dockerfile:1.0-experimental FROM ... RUN --mount=type=ssh git clone git@github.com:myorg/myproject.git $ docker build --ssh default SSH
  • 78. Docker Product / Feature Icons Container Image Registry Control Plane Product symbols: • OK to change size (proportionally) • OK to change color • NO changes to shapes, direction, or design • (ok to change ”service” design) Service (swarm) Pod (kubernetes) Group of containers or
  • 79. Icons
  • 80. Computer, PC, terminal, laptop, device Mobile watch Server, data center Storage database NetworkGlobe, location Layer, vm VM Edge DeviceDevelop dev Cloud
  • 81. Repair tune CI / CD Metrics, alert, dashboard Monitor, logging, operations configure Relationship, hierarchy, process, integration, arrows, cycle Check
  • 82. Calendar, date CI / CD Clocks, speed, time Security, secure, Scan, key, sign, encrypt firewall Process, relationship, hierarchy, cycle integrate Chain, brokentrust
  • 83. People MiscPeople executive architect practitioner developer Generic male Operator, support Hands - Shake Agreement - button group Generic female Generic speaker
  • 84. • 20+ Websites for Incredible Free Stock Photos − https://mymodernmet.com/best-free-stock-photography-websites/ − Includes sites focusing on food, nature, places, vintage, humorous/whimsical as well as general photo sites • 21 Amazing Sites With Breathtaking Free Stock Photos − https://blog.snappa.com/free-stock-photos/
  • 85. Generic Block Diagrams Calls to Action Summary Groups