Scanning Vulnerabilities in Docker images
Part of the value proposition of Containers is improved security. By running services inside containers, one can reduce the attack surface of an application.
To properly reduce the attack surface, great care must be given to the choice of base images. It’s very common to see Dockerfiles based on super-heavy base images that the application won’t need.
Multi-stage builds
Docker multi-stage builds help a lot in that matter by letting you use heavy images to build apps but prefer tiny images to actually run them. Go try Google Container Builder! It supports multi-stage builds.
Here’s a canonical example of multi-stage build for a Java application. Maven and a JDK are used to build the app. However, only the JRE is needed to run it.
FROM maven:3.5-jdk-8
WORKDIR /app
ADD . ./
RUN mvn package
FROM openjdk:8u151-jre-alpine
ADD --from=0 /app/target/app.jar .
CMD ["java", "-jar", "app.jar"]
How to choose a base image?
Choosing a base image is not easy. Beginners usually copy-paste samples at the risk of using outdated images.
Also because naming things is hard some images have misleading names on the Docker Store. Eg. for Java developers, using the java base image is tempting. PLEASE DON’T. These images are deprecated, haven’t been updated for 10 months and are full of vulnerabilities which defeats the purpose of reducing the attack surface. It’s documented but still, it requires to RTM.
Vulnerability Scanning
I ran Google Container Registry Vulnerability Scanning (currently in Alpha) on multiple Java images to compare the known vulnerabilities in each.
Here’s the top 6 vulnerabilities found on the java:latest
image:
Choosing the openjdk:latest
is safer:
Even better is choosing the openjdk:8u151-jre-alpine
flavor. Woot!
Kudos to Natanael Copa for taking such
good care of Alpine!
Common Vulnerabilities and Exposures (CVEs)
By the way, for this blog post, I compared the results of Container Registry Vulnerability Scanning and Docker’s own Security Scanning. As one would expect, the results are very similar since it’s ultimately using the same source for CVEs.
Sometimes Docker’s seems to raise vulnerabilities that are actually fixed. For
example, it raises the
CVE-2017-15874
on alpine:3.7. Looking at
the alpine packages list,
we see that alpine
3.7
is using Busybox
1.27.2-r7
that’s immune to the CVE
as the list of patches shows.
Go scan your images!