问题
Using multi-stage builds, I want to downsize an image at the end of Dockerfile, something like this:
FROM ubuntu AS ubuntu_build
RUN # do a lot of build things
FROM alpine
COPY --from=ubuntu_build /app /app
ENTRYPOINT whatever
the alpine image is small, and in theory only the /app stuff will get copied from the ubuntu image, is this the best trick in the book, or is there some other way to minimize the size of the final image?
回答1:
Distroless
Google provides instructions and tools to help make distroless images.
"Distroless" images contain only your application and its runtime dependencies. They do not contain package managers, shells or any other programs you would expect to find in a standard Linux distribution.
Why should I use distroless images?
Restricting what's in your runtime container to precisely what's necessary for your app is a best practice employed by Google and other tech giants that have used containers in production for many years. It improves the signal to noise of scanners (e.g. CVE) and reduces the burden of establishing provenance to just what you need.
If your app is a compiled binary then you could get away with a single binary plus the shared libraries it links against. If you limit the libraries you link against you might only need a couple. Here, for instance, is what a minimal C program compiled with gcc links against on my machine:
$ ldd basic-program
linux-vdso.so.1 (0x00007fffd3fa2000)
libc.so.6 => /lib/x86_64-linux-gnu/libc.so.6 (0x00007f2e4611b000)
/lib64/ld-linux-x86-64.so.2 (0x00007f2e4670e000)
Heck, you could even statically link the entire program and have no dependencies at all.
Google provides a set of base images targeted at different languages:
- gcr.io/distroless/static (Go, Rust, D)
- gcr.io/distroless/base (C, C++)
- gcr.io/distroless/java (Java)
- gcr.io/distroless/cc (Rust, D)
They have only some bare essential files, far less than what even a minimal distro like alpine pulls in, since it still has the apk
package manager, userspace utilities, etc. You use them the same way you describe in your question: as the last stage in a multi-stage build.
FROM gcr.io/distroless/base
COPY --from=build /go/bin/app /
CMD ["/app"]
FROM scratch
You can also go the full raw-food-living-in-the-woods route and build your final image FROM scratch
. It doesn't get any purer than that. There's absolutely nothing that you didn't put there yourself. This is the route traefik chose, for instance.
FROM scratch
COPY certs/ca-certificates.crt /etc/ssl/certs/
COPY traefik /
EXPOSE 80
VOLUME ["/tmp"]
ENTRYPOINT ["/traefik"]
回答2:
Besides use multi-stage
, another typical way is use docker-slim
to reduce the size of final built out image, like next:
docker-slim build --http-probe your-name/your-app
Detail refers to this guide
Add other common thoughts excerpt from "Five Ways to Slim Your Docker Images" in case you needed:
- Think Carefully About Your Application’s Needs
- Just install what you really needed in dockerfile.
- Use a Small Base Image
- Could use Alpine Linux or even directly from scratch, see how to create-the-smallest-possible-docker-container
- Use as Few Layers As Possible
- Combine run together, more run more layers, more layers more size
- Use .dockerignore files
- This avoid copy all things to images if use
COPY . /
, more, if not use.gitignore
, you then need to avoid to useCOPY . /
which may copy some necessary things to image.
- This avoid copy all things to images if use
- Squash Docker Images
- The idea here is that after your image is created, you then flatten it as much as possible, using a tool such as docker-squash.
来源:https://stackoverflow.com/questions/56861002/dummy-downsize-after-docker-build