66
Dockerfile Best Practices September 17th, 2019

DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

  • Upload
    others

  • View
    7

  • Download
    0

Embed Size (px)

Citation preview

Page 1: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

Dockerfile Best Practices

September 17th, 2019

Page 2: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Example DockerfileFROM ubuntu:18.04COPY . /appRUN make /appCMD python /app/app.py

What does each step do?• FROM creates a layer from the

ubuntu:18.04 Docker image.• COPY adds files from your Docker

image’s current directory.• RUN builds your application with

make.• CMD specifies what command to run

within the container

What is a Dockerfile?

Page 3: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

Build Context

Page 4: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Dockerfile 59bytes

example.txt 19bytes

README.md 54bytes

DockerfileFROM alpine:3.10.1COPY example.txt .CMD cat example.txt

Current Directory

Simple Build Context Example

Build Commanddocker build –t context-1 .

Page 5: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

DockerfileFROM alpine:3.10.1COPY example.txt .CMD cat example.txt

Current Directory

More Complex Build Context Example

Build Commanddocker build \–t context-2 \–f docker/Dockerfiledata-1

.git 28,995bytes

.gitignore 7bytesdata-1-->example.txt 19bytesdata-2-->additional.txt 26bytesdata-3-->retropie-4.5rpi2_rpi3.img.gz 813,960,280bytesdocker-->Dockerfile 59bytesREADME.md 79bytes

Page 6: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

.git 28,995bytes

.gitignore 7bytesdata-1-->example.txt 19bytesdata-2-->additional.txt 26bytesdata-3-->retropie-4.5rpi2_rpi3.img.gz 813,960,280bytesdocker-->Dockerfile 59bytesREADME.md 74bytes

docker build \–t context-3 \–f docker/Dockerfile.

DockerfileFROM alpine:3.10.1COPY data-1/example.txt .COPY data-2/additional.txt .CMD cat example.txt additional.txt

Current Directory

More Complex Build Context Example

Build Command

Page 7: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

DockerfileFROM alpine:3.10.1COPY data-1/example.txt .COPY data-2/additional.txt .CMD cat example.txt additional.txt

Current Directory

More Complex Build Context Example

Build Command

.git 28,995bytes

.gitignore 7bytesdata-1-->example.txt 19bytesdata-2-->additional.txt 26bytesdata-3-->retropie-4.5rpi2_rpi3.img.gz 813,960,280bytesdocker-->Dockerfile 59bytes.dockerignore 13bytesREADME.md 74bytes

docker build \–t context-4 \–f docker/Dockerfile.

Page 8: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Build Context

• Contextisthegivendirectoryanddown• Canbeaurl• CannotCOPYfilesfromoutsideofthecontext

• Typicallyit’sgoingtobethecurrentdirectory,butitcanbemodified• DoesnothavetobethesamedirectorythathastheDockerfile• Usethe-foptiontospecifytheDockerfile ifithasadifferentnameorisinadifferentdirectory

• Usea.dockerignore filetoskipunneededfilesfromgettingaddedtothecontext

Page 9: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

Image Caching

Page 10: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Dockerfile Project

• SimpleSpringBootproject• FollowstheMavenprojectstructure

• BuiltwithGradle&Docker• Takesroughly110seconds(150secondsthefirsttime)tobuildthejardocker run \

--rm \-w /home/gradle/project \-v $(pwd):/home/gradle/project \gradle:4.9.0-jdk8-alpine \gradle clean build

• .dockerignore fileignores(.git,.gradle,bin)• Needsaruntimeimage

• Preferably,somethingthatcanbebuiltduringCI

Page 11: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Dockerfile Caching Example

BuildTime(Initial) ~180SecondsBuildTime(Anyfilechange) ~150SecondsImageSize 597MB

Build Stats

Copyingineveryfile.Anychangebreaksthecache.

FROM ubuntuCOPY . /appRUN apt-get updateRUN apt-get -y install openjdk-8-jdkRUN apt-get -y install sshRUN apt-get -y install vimCMD ["java", "-jar", "/app/build/libs/docker-app-ds.jar"]

Page 12: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

PackageinstallsaregettingInvalidatedonjarchange.

BuildTime(Initial) ~180SecondsBuildTime(Anyfilechange) ~150SecondsImageSize 597MB

Build Stats

Dockerfile Caching Example

BuildTime(Initial) ~180SecondsBuildTime(JARchange) ~150SecondsImageSize 596MB

Build Stats

Onlycopyinthejar.

FROM ubuntuCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarRUN apt-get updateRUN apt-get -y install openjdk-8-jdkRUN apt-get -y install sshRUN apt-get -y install vimCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 13: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Dockerfile Caching Example

BuildTime(Initial) ~180SecondsBuildTime(JARchange) ~5SecondsImageSize 596MB

Build Stats

Movedtorightbeforeit’sneeded.

Theupdategetscachedinaseparatelayer.

BuildTime(Initial) ~180SecondsBuildTime(JARchange) ~150SecondsImageSize 596MB

Build Stats

FROM ubuntuRUN apt-get updateRUN apt-get -y install openjdk-8-jdkRUN apt-get -y install sshRUN apt-get -y install vimCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 14: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Dockerfile Caching Example

Everylinegetsitsownupdate.

FROM ubuntuRUN apt-get update && apt-get -y install openjdk-8-jdkRUN apt-get update && apt-get -y install sshRUN apt-get update && apt-get -y install vimCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 15: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Dockerfile Caching Example

Combineeverythingintoonelayer.

FROM ubuntuRUN apt-get update && \

apt-get -y install openjdk-8-jdk ssh vimCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 16: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Caching

• Changingthefileitselfwillinvalidatethatlayeranddown• Oldversionsofimagesmaystillexistinthecacheandcanbereused

• OnlyCopywhat’sneeded• Morefocusedcopieslimitthechancesofthecachebeinginvalidated• Alsocutsdownonthesizeoftheimage

• Theorderofexecutionmatters• Frequentlychangingitemsarebetteroffatthebottomofthefiles• Copyfilesinrightbeforetheyareneeded

• Bundlecommandstopreventusingoldfiles

Page 17: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

Reducing Size

Page 18: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Reducing Size

• Dumpunnecessaryfiles&dependencies• Don’tcopy/addfilesthataren’tneeded• .dockerignore canalsohelpremoveunnecessaryfiles• Removedevelopmentdependenciesfromnon-developmentimages• Canalsoreducesecurityrisk

• Cleanupafterinstallations• Removezipfilesafterunzipping• Cleanupinstall/tempfiles• Removeapplicationsonlyneededforinstallation(e.g.curl)

Page 19: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Dockerfile Sizing ExampleNotneededforproduction.

BuildTime(Initial) ~160SecondsBuildTime(JARchange) ~5SecondsImageSize 596MB

Build Stats

FROM ubuntuRUN apt-get update && \

apt-get -y install openjdk-8-jdk ssh vimCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 20: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM ubuntuRUN apt-get update && \

apt-get -y install openjdk-8-jdkCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Dockerfile Sizing Example

BuildTime(Initial) ~120SecondsBuildTime(JARchange) ~5SecondsImageSize 498MB

Build Stats

Page 21: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Dockerfile Sizing Example

BuildTime(Initial) ~120SecondsBuildTime(JARchange) ~5SecondsImageSize 498MB

Build Stats

Onlyinstallrequiredcomponents.

BuildTime(Initial) ~105SecondsBuildTime(JARchange) ~5SecondsImageSize 444MB

Build Stats

FROM ubuntuRUN apt-get update && \

apt-get -y install --no-install-recommends openjdk-8-jdk COPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 22: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Dockerfile Sizing Example

Build StatsBuildTime(Initial) ~105SecondsBuildTime(JARchange) ~5SecondsImageSize 444MB

Removetempinstallfiles.

BuildTime(Initial) ~105SecondsBuildTime(JARchange) ~5SecondsImageSize 417MB

Build Stats

FROM ubuntuRUN apt-get update && \

apt-get -y install --no-install-recommends \openjdk-8-jdk && \rm –rf /var/lib/apt/lists/*

COPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 23: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

Parent Images

Page 24: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Parent Image

• UseTrustedImages• https://arstechnica.com/information-technology/2018/06/backdoored-images-downloaded-5-million-times-finally-removed-from-docker-hub/

• Don’treinventthewheel• Makesureyouselectaversion• ‘latest’mayworktoday,butmayrequirechangestomorrow

• FindSmallestImagethatdoeswhatyouneedtodo• QuickerDownloads• LessRisks

Page 25: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM ubuntuRUN apt-get update && \

apt-get -y install --no-install-recommends \openjdk-8-jdk && \rm –rf /var/lib/apt/lists/*

COPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Dockerfile Parent Example

BuildTime(Initial) ~105SecondsBuildTime(JARchange) ~5SecondsImageSize 417MB

Build Stats

ThereisalreadyanofficialimageforOpenJDK.

Page 26: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM openjdkCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Dockerfile Parent Example

BuildTime(Initial) ~105SecondsBuildTime(JARchange) ~5SecondsImageSize 417MB

Build Stats

Usingtheofficialimage.Nomoreinstallsteps.

BuildTime(Initial) ~40SecondsBuildTime(JARchange) ~5SecondsImageSize 501MB

Build Stats

Page 27: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM openjdk:8COPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Dockerfile Parent Example

BuildTime(Initial) ~40SecondsBuildTime(JARchange) ~5SecondsImageSize 501MB

Build Stats

Useamorespecificversion.

BuildTime(Initial) ~40SecondsBuildTime(JARchange) ~5SecondsImageSize 519MB

Build Stats

Page 28: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Dockerfile Parent Example

BuildTime(Initial) ~40SecondsBuildTime(JARchange) ~5SecondsImageSize 519MB

Build Stats

UsingjusttheJREonasmallerbaseimage.

BuildTime(Initial) ~25SecondsBuildTime(JARchange) ~5SecondsImageSize 116MB

Build Stats

FROM openjdk:8-jre-alpineCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 29: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

Compiling the Code

Page 30: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Current State

GOOD NEWS• Wehaveagoodimageforaruntime• Noadditionaldependencies• Buildsfast• Smallsize

BADNEWS• Wehavenoimageforcompilation• Buildingthejarisexternaltotheimage• Can’tutilizetheDockercache

Page 31: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM openjdk:8-jre-alpineCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

docker run --rm \-w /home/gradle/project \-v $(pwd):/home/gradle/project \gradle:4.9.0-jdk8-alpine \gradle clean build

Compiling the Code Example

Newbaseimage.

Page 32: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM gradle:4.9.0-jdk8-alpineCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

docker run --rm \-w /home/gradle/project \-v $(pwd):/home/gradle/project \gradle:4.9.0-jdk8-alpine \gradle clean build

Compiling the Code Example

Newbaseimage.Needaworkdirectory.

Page 33: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Needaworkdirectory.

Compiling the Code Example

Needtocopyinthecode.

FROM gradle:4.9.0-jdk8-alpineWORKDIR /home/gradle/project COPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

docker run --rm \-w /home/gradle/project \-v $(pwd):/home/gradle/project \gradle:4.9.0-jdk8-alpine \gradle clean build

Page 34: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Runthebuild.

Compiling the Code Example

Needtocopyinthecode.

FROM gradle:4.9.0-jdk8-alpineWORKDIR /home/gradle/project COPY build.gradle .COPY src srcCMD ["java", "-jar", "/app/docker-app-ds.jar"]

docker run --rm \-w /home/gradle/project \-v $(pwd):/home/gradle/project \gradle:4.9.0-jdk8-alpine \gradle clean build

Page 35: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Runthebuild.

Compiling the Code Example

Adjustthejarlocation.

FROM gradle:4.9.0-jdk8-alpineWORKDIR /home/gradle/project COPY build.gradle .COPY src srcRUN gradle build --no-daemonCMD ["java", "-jar", "build/libs/docker-app-ds.jar"]

docker run --rm \-w /home/gradle/project \-v $(pwd):/home/gradle/project \gradle:4.9.0-jdk8-alpine \gradle clean build

Page 36: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Compiling the Code Example

DOESN’TWORK!Gradlethrowsapermissionerror!

Createsthedirectoryasrootuser.FROM gradle:4.9.0-jdk8-alpine

WORKDIR /home/gradle/project COPY build.gradle .COPY src srcRUN gradle build --no-daemonCMD ["java", "-jar", "build/libs/docker-app-ds.jar"]

Page 37: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Compiling the Code ExampleMakesuregradleownseverything.FROM gradle:4.9.0-jdk8-alpine

RUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemonCMD ["java", "-jar", "build/libs/docker-app-ds.jar"]

Page 38: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM gradle:4.9.0-jdk8-alpineRUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemonCMD ["java", "-jar", "build/libs/docker-app-ds.jar"]

Compiling the Code Example

BuildTime(Initial) ~25SecondsBuildTime(JARchange) ~5SecondsImageSize 116MB

Build StatsBuildTime(Initial) ~105SecondsBuildTime(Codechange) ~75SecondsImageSize 222MB

Build Stats

Page 39: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Compiling the Code Example

PROBLEM:Theimageisbiggerthanitneedstobeandnowcontainsthesourcecodeandacompiler.

QUESTION:Howcanweaddthebuildstepswithoutincreasingthesizeoftheruntime?

ANSWER:Multi-StageBuild

Page 40: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Compiling the Code ExampleNotneededforthebuild.FROM gradle:4.9.0-jdk8-alpine

RUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemonCMD ["java", "-jar", "build/libs/docker-app-ds.jar"]

FROM openjdk:8-jre-alpineCOPY build/libs/docker-app-ds.jar /appCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 41: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Compiling the Code Example

Thisjarnolongerexists.

FROM gradle:4.9.0-jdk8-alpineRUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemon

FROM openjdk:8-jre-alpineCOPY build/libs/docker-app-ds.jar /app/docker-app-ds.jarCMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 42: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Compiling the Code Example

Copythejarfromthebuild.

FROM gradle:4.9.0-jdk8-alpine AS builderRUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemon

FROM openjdk:8-jre-alpineCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 43: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

BuildTime(Initial) ~105SecondsBuildTime(Codechange) ~75SecondsImageSize 222MB

Build Stats

FROM gradle:4.9.0-jdk8-alpine AS builderRUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemon

FROM openjdk:8-jre-alpineCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

Compiling the Code Example

BuildTime(Initial) ~120SecondsBuildTime(Codechange) ~75SecondsImageSize 116MB

Build Stats

NOCODECHANGE…NOREBUILD!

Page 44: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

Security

Page 45: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Security Example

OpenJDKrunsas“root”bydefault.

FROM gradle:4.9.0-jdk8-alpine AS builderRUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemon

FROM openjdk:8-jre-alpineCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 46: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Security Example

Createanewusertorunas.

FROM gradle:4.9.0-jdk8-alpine AS builderRUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemon

FROM openjdk:8-jre-alpineRUN addgroup -g 1001 -S appuser && adduser -u -S appuser -G appuserUSER appuserCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 47: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Security Considerations

• Runastheleastprivilegeduser• Usetrusted,minimalimagesasabase• Patchyourimagesforsecurityfixes• Containersdon’tgetpatched,imagesdo

• Don’tputsecureinformationinDockerfiles and/orENVvariables• Addadditionalsecuritycheckstoyourpipeline:• ImageScans• ImageSigning

Page 48: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

Multi-Stage Builds

Page 49: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Multi-Stage Builds

• Wearealreadyusingamultistagebuild• Mostcommonuseofmulti-stagebuild

• Youcanhavemorethantwostages• Someexamples:• Pullingartifactsfromdifferentimages• Buildingdifferentversionsofyourimage

• Differentbaseimage(differentflavorsoflinux:alpine,centos,ubuntu)• Differentimagesfordifferentuses(productionvsdevtesting)

Page 50: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM node:8.11.3-alpine AS fe-buildRUN apk add --no-cache --virtual .gyp python make g++RUN npm install –g @angular/cli && npm install –g tslint && \

npm install –g concurrently && npm installWORKDIR /app COPY docker-app-ui/ .RUN npm run build:prod

FROM microsoft/dotnet:2.1-sdk-alpine AS be-buildWORKDIR /app COPY docker-app-api/ .RUN dotnet restore && publish –c Release –o out

FROM microsoft/dotnet:2.1-aspnetcore-runtimeWORKDIR /appCOPY --from=be-build /app/out ./COPY --from=fe-build /app/dist wwwrootENTRYPOINT ["dotnet", "docker-app-api.dll"]

Multi-Stage Builds

Page 51: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM gradle:4.9.0-jdk8-alpine AS builderRUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemon

FROM ubuntu AS devRUN apt-get update && \

apt-get -y install openjdk-8-jdk ssh vimCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

FROM openjdk:8-jre-alpine AS prodRUN addgroup -g 1001 -S appuser && adduser -u -S appuser -G appuserUSER appuserCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

Multi-Stage Buildsdocker build \--target prod \-t docker-app-api:1.0 .

Determineswheretostop

Page 52: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

BuildKit

Page 53: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

BuildKit

DockerBuildenhancementsfor18.09releaseintroducesamuch-neededoverhaulofthebuildarchitecture.ByintegratingBuildKit,usersshouldseeanimprovementonperformance,storagemanagement,featurefunctionality,andsecurity.

https://docs.docker.com/develop/develop-images/build_enhancements/

Page 54: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Enabling BuildKit

• Enableonaperbuildbasis• Useanenvironmentvariable(DOCKER_BUILDKIT)

DOCKER_BUILDKIT=1 docker build .

• Enableforallbuilds• Updatethedaemon.json orDockerDesktopSettings

{ "features": { "buildkit": true } }

Page 55: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM node:8.11.3-alpine AS fe-buildRUN apk add --no-cache --virtual .gyp python make g++RUN npm install –g @angular/cli && npm install –g tslint && \

npm install –g concurrently && npm installWORKDIR /app COPY docker-app-ui/ .RUN npm run build:prod

FROM microsoft/dotnet:2.1-sdk-alpine AS be-buildWORKDIR /app COPY docker-app-api/ .RUN dotnet restore && publish –c Release –o out

FROM microsoft/dotnet:2.1-aspnetcore-runtimeWORKDIR /appCOPY --from=be-build /app/out ./COPY --from=fe-build /app/dist wwwrootENTRYPOINT ["dotnet", "docker-app-api.dll"]

Build Concurrency

fe-build

be-build

Runtime

fe-build be-build

Runtime

Page 56: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM node:8.11.3-alpine AS fe-buildRUN apk add --no-cache --virtual .gyp python make g++RUN npm install –g @angular/cli && npm install –g tslint && \

npm install –g concurrently && npm installWORKDIR /app COPY docker-app-ui/ .RUN npm run build:prod

FROM microsoft/dotnet:2.1-sdk-alpine AS be-buildWORKDIR /app COPY docker-app-api/ .RUN dotnet restore && publish –c Release –o out

FROM microsoft/dotnet:2.1-aspnetcore-runtimeWORKDIR /appCOPY --from=be-build /app/out ./COPY --from=fe-build /app/dist wwwrootENTRYPOINT ["dotnet", "docker-app-api.dll"]

Build Concurrency

BuildTime(Initial) ~400SecondsBuildTime(Codechange) VariesImageSize 263MB

Build StatsBuildTime(Initial) ~290SecondsBuildTime(Codechange) VariesImageSize 263MB

Build Stats

Page 57: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM gradle:4.9.0-jdk8-alpine AS builderRUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemon

FROM ubuntu AS devRUN apt-get update && \

apt-get -y install openjdk-8-jdk ssh vimCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

FROM openjdk:8-jre-alpine AS prodRUN addgroup -g 1001 -S appuser && adduser -u -S appuser -G appuserUSER appuserCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

Build Concurrency

proddev

buildjar

Page 58: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

FROM gradle:4.9.0-jdk8-alpine AS builderRUN mkdir /home/gradle/projectWORKDIR /home/gradle/project COPY --chown=gradle:gradle build.gradle .COPY --chown=gradle:gradle src srcRUN gradle build --no-daemon

FROM ubuntu AS devRUN apt-get update && \

apt-get -y install openjdk-8-jdk ssh vimCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

FROM openjdk:8-jre-alpine AS prodRUN addgroup -g 1001 -S appuser && adduser -u -S appuser -G appuserUSER appuserCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

Build Concurrency

BuildTimeProd(Initial) ~370SecondsBuildTime(Codechange) ~75SecondsImageSizeProd 116MB

Build StatsBuildTimeProd(Initial) ~120SecondsBuildTime(Codechange) ~75SecondsImageSizeProd 116MB

Build Stats

Page 59: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Experimental Dockerfile Options

• Toenable,startthefilewiththis:# syntax=docker/dockerfile:experimental

• Enables:• --mountsyntax• --securitysyntax• --networksyntax

• AllexecutedviaRUNcommands

Page 60: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Security Syntax

• Allowscommandstorunininsecuremode• Equivalenttodocker run --privileged• Optionsareinsecure&sandbox• Requiresthesecurity.insecure entitlement• ExecutedPerRUN command

# syntax = docker/dockerfile:experimentalFROM ubuntu RUN --security=insecure cat /proc/self/status | grep CapEff

Page 61: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Network Syntax

• Allowscommandstorunwithdifferentnetworkoptions• Optionsarenone,host&default• Requiresthenetwork.host entitlement• ExecutedPerRUN command

# syntax = docker/dockerfile:experimentalFROM python:3.6 ADD mypackage.tgz wheels/ RUN --network=none pip install \

--find-links wheels mypackage

Page 62: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Mount Syntaxes

Numerousmountoptionsareavailable:• RUN --mount=type=bind

• Let’syoubinddirectoriesinsteadofcopying(stillneedstobeinthecontext)• RUN --mount=type=cache

• Cachedirectoriesforcompilersandpackages• RUN --mount=type=tmpfs

• Mountatemporaryfilesystem• RUN --mount=type=secret

• Mountasecretthatcanbeused,butnotstoredintheimage.• RUN --mount=type=ssh

• AccessfilesviaSSH(forinstance,logintoGitusingyourexistingSSHkey)

Page 63: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Cache Mount

BuildTimeProd(Initial) ~120SecondsBuildTime(Codechange) ~75SecondsImageSizeProd 116MB

Build Stats

Mountsasroot

BuildTimeProd(Initial) ~120SecondsBuildTime(Codechange) ~50SecondsImageSizeProd 116MB

Build Stats

# syntax = docker/dockerfile:experimentalFROM gradle:4.9.0-jdk8-alpine AS builderUSER rootWORKDIR /home/gradle/project COPY build.gradle .COPY src srcRUN --mount=type=cache,target=/home/gradle/.gradle gradle build --no-daemon

FROM openjdk:8-jre-alpine AS prodRUN addgroup -g 1001 -S appuser && adduser -u -S appuser -G appuserUSER appuserCOPY --from=builder \/home/gradle/project/build/libs/docker-app-ds.jar /app/docker-app-ds.jar

CMD ["java", "-jar", "/app/docker-app-ds.jar"]

Page 64: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

NVISIA - Confidential and Proprietary

Secret Mount

MatchedbyID

# syntax = docker/dockerfile:experimentalFROM ubuntu RUN --mount=type=secret,target=.,id=secret_script \

bash -c my_script.sh

docker build \-t secret_image--secret id=secret_script,src=my_script.sh \.

Page 65: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

Questions?

Page 66: DockerfileBest Practices - NVISIA · 2019-09-19 · NVISIA -Confidential and Proprietary Example Dockerfile FROMubuntu:18.04 COPY. /app RUNmake /app CMDpython /app/app.py What does

Nick Schultz

Principal Consultant

(920) 210-1429