Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"FROM scratch" image #310

Closed
wants to merge 3 commits into from
Closed

"FROM scratch" image #310

wants to merge 3 commits into from

Conversation

ricardbejarano
Copy link

This is a Dockerfile for a FROM scratch Docker image of NGINX.

It includes only the required files, libraries and a statically-compiled NGINX binary with built-from-source PCRE, ZLIB and OPENSSL libraries.

The overall image size as of 1.15.8 is ~18.1MB.

I hope it helps to start a discussion about moving to built-from-source dependencies and NGINX during build time.

ricardbejarano/nginx is a very similar Dockerfile, only with Brotli support included, which I removed here because you do not include it on your images.

You can try it out by running the ricardbejarano/nginx:1.15.8 Docker Hub image.

@gdzien
Copy link

gdzien commented Feb 18, 2019

I just want to point out that alpine-based NGINX image is 16 MB

@ricardbejarano
Copy link
Author

ricardbejarano commented Feb 18, 2019

It's not just about size. Attack surface is null much lower. There's no files other than the NGINX binary, NGINX conf, the only required system libraries, an entry /etc/passwd and /etc/group and a /tmp directory.

@ricardbejarano
Copy link
Author

ricardbejarano commented Feb 18, 2019

Alright!

I just fixed the aforementioned issue with name resolving, I've now commited a fully-working version (as far as I can tell) of this PR's scratch Dockerfile.

I also removed duplicated system libraries, caused by following symlinks during the Docker build process.

Summary

  • NGINX 1.15.8 image, statically compiled during build

  • pcre 8.42, zlib 1.2.11 and openssl 1.1.1a, also pulled from official sources during build

  • The whole image weights 13.7MB, with no attack surface other than NGINX itself

  • The NGINX binary includes TLS 1.3 support, thanks to OpenSSL 1.1.1a

  • The image contains an example NGINX configuration; an entry in /etc/passwd and /etc/group for a "root" user and group; the required system libraries; the NGINX binary and a /tmp folder, required by some NGINX features.

If you were to tree the root filesystem of the image it would look exactly like this:

/
├── etc
│   ├── group
│   ├── nginx
│   │   ├── html      
│   │   │   ├── 50x.html
│   │   │   └── index.html
│   │   ├── mime.types
│   │   └── nginx.conf  
│   └── passwd                  
├── lib              
│   └── x86_64-linux-gnu   
│       ├── ld-linux-x86-64.so.2
│       ├── libc.so.6     
│       ├── libnss_dns.so.2
│       ├── libnss_files.so.2
│       └── libresolv.so.2
├── nginx
└── tmp
    └── .keep

Notes

  • If I'm not wrong, having root run the daemon isn't harmful, because it's inside a container
  • If requested, I can easily add Brotli support

You can try the image at ricardbejarano/nginx:1.15.8.

@ricardbejarano ricardbejarano changed the title added FROM scratch Dockerfile "FROM scratch" image Feb 18, 2019
@KostyaEsmukov
Copy link

with no attack surface other than NGINX itself

How so? This image still contains the same set of libraries: glibc, openssl, zlib and so on, although they're now compiled statically instead of being linked as shared objects (which, perhaps, creates an illusion of zero attack surface). I personally don't see how this is different from a regular nginx image built with FROM debian.

@ricardbejarano
Copy link
Author

debian, the image you mention, contains bash, the whole set of UNIX scripting tools, a package manager and 101MB worth of other bloat we don't need in NGINX.

It's a very common issue to pack applications with full-blown operating systems in Docker images, but that is an anti-pattern. Using OS's as base images should only be done during development, just in case there's some dependency you lost track of.

I'm not saying there's zero attack surface, but if, for some reason, someone where to break out of NGINX, I'd rather not give him/her bash and the whole developer toolset.

Distroless base images exist for a reason.

If you go to https://hub.docker.com/_/nginx/scans/library/nginx/mainline (you must login, or else it'll 404 you), you will see a summary of an automatic vulnerability scan in the latest mainline NGINX image, the official one.

Based on that summary, the image contains 2 "critically" vulnerable binaries, gettext and glibc, specifically CVE-2018-18751 and CVE-2018-1000001, as well as some other "major" vulnerabilities. Just because it is based on debian:stretch-slim.

To be fair, this image compiles NGINX in debian:stretch so it uses a vulnerable glibc, but fixing it is as easy as pulling glibc from somewhere else, we don't have to wait for the Debian team to update :stretch.

@ricardbejarano
Copy link
Author

UPDATE: I built a glibc specific image at ricardbejarano/nginx:glibc and a musl specific image at ricardbejarano/nginx:musl. Therefore, the latter (if the Docker Hub's vulnerability analysis is correct) has no known vulnerabilities as of today. It's linked dynamically, as opposed to :glibc, though.

Get more information about ricardbejarano/nginx:musl at ricardbejarano/nginx.

@yosifkit
Copy link
Contributor

  1. multi-stage builds are unsupported for Official Images: Add multi-stage build support docker-library/official-images#3383

  2. We have a FAQ about CVEs in Docker's Official Images.

    And to be more specific, see the Debian DSAs below; I trust the Debian Security team more than myself to know when and when not to apply a patch. Even RHEL 7 is still "vulnerable" to CVE-2018-18751 and, as far as I can tell, they only fixed CVE-2018-1000001 because of a specific customer (see discussion on linked RedHat bug).

@thresheek
Copy link
Collaborator

@yosifkit pretty much described what I wanted to write.

Closing this PR as this is not something we will merge.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants