DockerFile Security Best Practices 

Developer Advocate, Accurics 

Docker Community Leader 

@kubedaily

Join : discord.kubedaily.live

Github:- Sangam14

choose minimal base image

FROM alpine
WORKDIR /app
COPY package.json /app
RUN npm install
CMD [“node”,“index.js”]

Remove Cache Packages  

FROM alpine
RUN apk add nginx && rm -rf /var/cache/apt/*
COPY index.html /var/www/html/
EXPOSE 80
CMD [“nginx”,“-g”,“daemon off;”]
FROM alpine
RUN apk add –no-cache nginx
COPY index.html /var/www/html/
EXPOSE 80
CMD [“nginx”,“-g”,“daemon off;”]

avoid multilayers 

FROM alpine
RUN apk update && apk add curl nginx nginx-mod-http-geoip2-1.16.1-r6 \
rm -rf /var/cache/apt/*
COPY index.html /var/www/html/
EXPOSE 80
CMD [“nginx”,“-g”,“daemon off;”]
FROM alpine
RUN apk update
RUN apk add curl
RUN apk add nodejs
RUN apk add nginx-1.16.1-r6
RUN apk add nginx-mod-http-geoip2-1.16.1-r6
COPY index.html /var/www/html/
EXPOSE 80
CMD [“nginx”,“-g”,“daemon off;”]

Don't ignore .dockerignore

FROM node:10
WORKDIR /nodeapp
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 8888
CMD [ “node”, “index.js” ]
node_modules
.env
secrets/
*pem
*.md

choose slim variant 

cut the root

FROM node:10
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 8888
CMD [ “node”, “index.js” ]
FROM node:10
RUN user add -m nodeapp
USER nodeappuser
RUN whoami
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 8888
CMD [ “node”, “index.js” ]

remove unwanted

TAG Wisely

So No to latest Tags

Public Private Registry 

keep it single 

use linter 

Dockerfile linter, validate inline bash, written in Haskell:- https://github.com/hadolint/hadolint

Docker linter  vscode

https://marketplace.visualstudio.com/items?itemName=henriiik.docker-linter

Avoid Hard Coding

ARG VERSION
FROM node:$VERSION
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 8888
CMD [ “node”, “index.js” ]
docker build -t testimage –build-arg VERSION=10 .
docker build -t testimage –build-arg VERSION=9 .

adding metadata

FROM node:10
LABEL version=“1.0” maintainer=“Sangam Biradar <cXXXXXXo@gmail.com>”
WORKDIR /app
COPY package.json ./
RUN npm install
COPY . .
EXPOSE 8888
CMD [ “node”, “index.js” ]

using vulnerability check !

https://github.com/accurics/terrascan

OPA : Policy as code 

 

https://github.com/accurics/terrascan/tree/master/pkg/policies/opa/rego

package play


suspicious_env_keys = [
    "passwd",
    "password",
    "secret",
    "key",
    "access",
    "api_key",
    "apikey",
    "token",
]

pkg_update_commands = [
    "apk upgrade",
    "apt-get upgrade",
    "dist-upgrade",
]

image_tag_list = [
    "latest",
    "LATEST",
]



https://play.openpolicyagent.org/p/epcbtaBtSF
# Looking for suspicious environemnt variables
deny[msg] {    
    input[i].Cmd == "env"
    val := input[i].Value
    contains(lower(val[_]), suspicious_env_keys[_])
    msg = sprintf("Suspicious ENV key found: %s", [val])
}

# Looking for latest docker image used
warn[msg] {
    input[i].Cmd == "from"
    val := split(input[i].Value[0], ":")
    count(val) == 1
    msg = sprintf("Do not use latest tag with image: %s", [val])
}

# Looking for latest docker image used
warn[msg] {
    input[i].Cmd == "from"
    val := split(input[i].Value[0], ":")
    contains(val[1], image_tag_list[_])
    msg = sprintf("Do not use latest tag with image: %s", [input[i].Value])
}

# Looking for apk upgrade command used in Dockerfile
deny[msg] {
    input[i].Cmd == "run"
    val := concat(" ", input[i].Value)
    contains(val, pkg_update_commands[_])
    msg = sprintf("Do not use upgrade commands: %s", [val])
}

# Looking for ADD command instead using COPY command
deny[msg] {
    input[i].Cmd == "add"
    val := concat(" ", input[i].Value)
    msg = sprintf("Use COPY instead of ADD: %s", [val])
}

# sudo usage
deny[msg] {
    input[i].Cmd == "run"
    val := concat(" ", input[i].Value)
    contains(lower(val), "sudo")
    msg = sprintf("Avoid using 'sudo' command: %s", [val])
}

# # No Healthcheck usage
# deny[msg] {
#     input[i].Cmd == "healthcheck"
#     msg := "no healthcheck"
# }

How to Scan DockerFile with Terrascan in 2 sec ?

1. step

brew install terrascan

2. step

terrascan init

3. step

terrascan scan -i docker

Thanks 

https://runterrascan.io

DockerFile Best Practices

By Sangam Biradar

DockerFile Best Practices

Curated list of Dockerfile Best Practices

  • 747