Dockerfile Dos & Do nOts There are many ways to skin a cat… but SHOULD you??? Melissa McKay Developer Advocate JFrog

About Melissa McKay… Developer Advocate @JFrog Java Champion Docker Captain TWITTER: @melissajmckay LINKEDIN: linkedin.com/in/melissajmckay

Buzz BEE

The Dockerfile FROM ADD COPY RUN USER CMD https://docs.docker.com/engine/reference/builder/ ENV ARG WORKDIR LABEL EXPOSE VOLUME STOPSIGNAL ONBUILD SHELL HEALTHCHECK ENTRYPOINT

8 DO NOTS

  1. IGNORING .dockerignore

FROM ubuntu WORKDIR /myapp COPY . /myapp WHY USE .DOCKERIGNORE? Avoid wasted time and invalidating cache by sending EVERYTHING to the Docker daemon EXPOSE 8080 ENTRYPOINT [“start.sh”] Avoid sending test or user specific files Avoid sending secrets!

DO # Ignore these files in my project **/*.md DO NOT 404 !README.md passwords.txt .git logs/ */temp **/test/ File: .dockerignore File: .dockerignore

  1. USING UNTRUSTED BASE IMAGES

FROM evilimage WORKDIR /myapp COPY . /myapp ENTRYPOINT [“start.sh”] WHY USE TRUSTED BASE IMAGES? Evaluate the image for your use case - KNOW WHAT’S IN IT! Avoid malicious packages Get latest updates Start with Docker Official Images - mitigate your risk

  1. NEVER UPDATING

FROM baseimage:2-years-ago WHY UPDATE? WORKDIR /myapp Security updates are important! COPY . /myapp ENTRYPOINT [“start.sh”] Security updates are really important! Security updates are really, REALLY important!

  1. NOT DEFINING VERSIONS

FROM mybaseimage WHY DEFINE VERSIONS? RUN apt-get update \ && install -y \ mypackage anotherpackage yetanotherpackage Have a bill of materials for your build - know what version of EVERYTHING is installed WORKDIR /myapp COPY . /myapp EXPOSE 8080 ENTRYPOINT [“/start.sh”] Save yourself troubleshooting time by explicitly controlling version updates

  1. INCLUDING BUILD TOOLS

FROM maven:3.6.3-jdk-8 WORKDIR /myapp WHY NOT INCLUDE YOUR BUILD TOOL? COPY . /myapp RUN mvn clean package The size of your image will be bigger than it needs to be ENTRYPOINT [“start.sh”] Minimize your attack surface area by ONLY including what you need for your application to run in production You can use a multi-stage build instead!

  1. USING EXTERNAL RESOURCES

RUN apt-get update \ && install -y curl WHY NOT USE EXTERNAL RESOURCES? RUN curl -sL \ https://somewhere.com/script.sh \ | bash - If an external resource goes away… what do you do??? FROM ubuntu WORKDIR /myapp COPY . /myapp ENTRYPOINT [“start.sh”] Not reviewing external scripts before they are used in your production environment is an excellent opening for a supply chain attack.

  1. Hardcoding Secrets OR config

FROM mybaseimage RUN apt-get update WHY AVOID HARDCODED SECRETS OR CONFIG? RUN rm -rf secrets WORKDIR /myapp COPY . /myapp EXPOSE 8080 ENTRYPOINT [“/start.sh”] It’s never a good idea to advertise sensitive information in artifacts that will be moved around, possibly replicated, and deployed into production (or anywhere else) Providing configuration at runtime allows for images to be environment agnostic

  1. Doing Too MUCH!

FROM mybaseimage:1.0.0 RUN sudo apt-get purge \ —auto-remove oldpackage WHY KEEP IT SIMPLE? RUN apt-get update \ && apt-get install -y \ newpackage Dockerfile should describe the build WORKDIR /myapp If the base image needs modified - modify it! COPY . /myapp RUN /cleanupdatabase.sh RUN /run_unit_tests.sh ENTRYPOINT [“start.sh”] Dockerfiles should contain idempotent operations only - in order to provide repeatable builds

RESOURCES DOCKERFILE DOCUMENTATION https://docs.docker.com/engine/reference/builder/ OFFICIAL IMAGES https://docs.docker.com/docker-hub/official_images/ MULTI-STAGE BUILDS https://docs.docker.com/develop/develop-images/multistage-build/ STORING YOUR IMAGES https://dzone.com/refcardz/getting-started-with-container-registries

THANK YOU! Q&A