12 ms·
In my experience docker-slim[0] is the way to go for creating minimal and secure Docker images. I wasted a lot of time in the past trying to ship with Alpine b
by osener 5y ago
In my experience docker-slim[0] is the way to go for creating minimal and secure Docker images.
I wasted a lot of time in the past trying to ship with Alpine base images and statically compiling complicated software. All the performance, compatibility, package availability headaches this brings is not worth it when docker-slim does a better job of removing OS from your images while letting you use any base image you want.
Tradeoff is that you give up image layering to some extent and it might take a while to get dead-file-elimination exactly right if your software loads a lot of files dynamically (you can instruct docker-slim to include certain paths and probe your executable during build).
If docker-slim is not your thing, “distroless” base images [1] are also pretty good. You can do your build with the same distro and then in a multi stage docker image copy the artifacts into distroless base images.
[0] https://github.com/docker-slim/docker-slim https://github.com/docker-slim/docker-slim
[1] https://github.com/GoogleContainerTools/distroless https://github.com/GoogleContainerTools/distroless
- kylequest 5y agoLayers support in docker-slim is something that's on the todo list (exact time is tbd). The recent set of the engine enhancements reduce the need for the explicit include flags. Also new application-specific include capabilities are wip (already added a number of new flags for node.js, next.js and nuxt.js applications).
- AtNightWeCode 5y agoI have quit using Alpine. It caused to many issues in production. For some workloads in GO for instance you can use Scratch directly. But slim and distroless are my preferred base images.
- mt42or 5y agoYes we have experienced many issues with Alpine too. Ubuntu with 25MB compressed is ok.
- hericium 5y agoUntil it's not. Well working deb/apt is replaced by some self-sabotage called snap before up-to-date packages land there.
- heavyset_go 5y agoAre people actually using Snap in containers? It feels like a convenience feature for desktop users.
- ZiiS 5y agoThey don't give you the choice. Applications are only avaliable as either a snap or an deb. With many you might want to containerise (ie Chromium for CI) being snaps. I dont belive they can work in unpriviledged docker containers.
- yunohn 5y agoWhich apps are you using via Docker, that are only available as a snap?
- shaicoleman 5y agoThere are Chromium debs for Ubuntu 20.04 available from the Linux Mint repo. To get it Chromium under docker, I'm using the following params: --headless --no-sandbox --disable-gpu --window-size=1920,1080 --disable-dev-shm-usage
- heavyset_go 5y agoI understand that, it's just my impression with using Snap that it's used to ship desktop applications in a consistent way.
- bigpod 5y agoyou cannot use snap inside a docker or any other OCI container, first of all snap is a containerised package as well so it doesnt make much sense but what is more important it requires SystemD and as far as i know if systemd isnt PID 1 snap deamon wont run and its CLI will output it cant run.
- Beltalowda 5y agoWhat issues did you experience with Alpine and Go?
- unmole 5y ago> I have quit using Alpine. As I said to the author of TFA a few days ago: Alpine delenda est.
- wereHamster 5y agoWhat go build options are recommended to have go output a static binary (that can run inside a scratch image)?
- onei 5y agoIf you're using plain Go, you get static binaries for free. If you're linking against so C library you might be out of luck. You can try setting CGO_ENABLED=0 in your environment, but I've had mixed success in practice.
- dimitrios1 5y agoCGO_ENABLED=0 has always worked for me in production, but it did come with some tradeoffs, notably, network performance.
- throwaway894345 5y agoI’ve only had success with CGO_ENABLED. If you depend on a C library, then obviously it won’t work, but mercifully few ago programs depend on C libraries (not having straight C ABI compatibility is a real blessing since virtually none of the ecosystem depends on C and its jerry rigged build tooling).
- wereHamster 5y agoWell this is not what I'm seeing. I need to add -ldflags "-linkmode external -extldflags -static" to the go build command otherwise the binary doesn't run inside a scratch image.
- burnoutgal 5y agoPersonally I hate scratch images because once you lose busybox, you lose the ability to exec into containers. It's a great escape hatch for troubleshooting.
- kevin_nisbet 5y agoThere are a few options that help here. With host access, I tend to just use nsenter most of the time to do different troubleshooting. It can be a bit of a pain doing network troubleshooting though since the resolv.conf will be different without the fs namespace. And kubernetes has debug containers and the like now.
- qwertox 5y agoThanks for mentioning these. I've been using Alpine religiously for years, until the build problems became too big. Mostly long build times and removed packages on major version updates. Now I first try with Alpine and if there is the slightest hint of a problem, I move over to debian-slim. So things like Nginx are still in Alpine for me, while anything related to Python not any longer. At first I thought your mention of docker-slim was an error for debian-slim, but I've followed the link am glad to have learned something useful.
- madduci 5y agoWhile this is the go-to approach, I find really hard later to debug problems for images who don't have even an shell or a minimum set of tools to help debug a problem
- bigpod 5y agoyou can use --include-shell to inclue a shell. but my recommendation is always keep a non-slimmed image somewhere so you can refer to it and some debugging can be done in either, also that allows you to use something like slim.ai's(company behind docker-slim) web based SaaS features which allow you to see the differences between 2 images and see the file system in nice web base file tree. some bugs may stem from removing what is necessary for app to work(sometimes caused by not loading a library during "slimming" process) for those types of errors you need to know how your app runs more then anything. it a tradeoff
- madduci 5y agoThe problem is that sometimes, using commands like cp don't output the error in case of failed permissions and if there's any tool into it (e.g. ls), you can't find out why it fails
- sokoloff 5y agoRelated, is there any built-in facility that would log file system accesses that failed on the resulting image? Seems like that would give the answer in a substantial fraction of cases.
- atombender 5y agoI recommend avoiding this kind of thinking, which leads to bundling all sorts of stuff in every single container. My philosophy is that images should contain as little as possible. To debug a container, a better way is to enter the container's kernel namespaces using a tool such as nsenter [1]. Then you can use all your favourite tools, but still access the container as if you're inside it. Of course, this means accessing it on the same host that it's running. If you're on Kubernetes, debug containers [2] are currently in beta, and should be much nicer to work with, as you can do just "kubectl debug" to start working with an existing pod. [1] https://man7.org/linux/man-pages/man1/nsenter.1.html https://man7.org/linux/man-pages/man1/nsenter.1.html [2] https://kubernetes.io/docs/tasks/debug-application-cluster/debug-running-pod/ https://kubernetes.io/docs/tasks/debug-application-cluster/d...
- codethief 5y agoCould anyone ELI5 how exactly docker-slim achieves minifications of up to 30× and more? I've read the README but it still seems like black magic to me.
- bigpod 5y agobasicly what docker-slim does it basicly checks what your program is opening/ using(using simular system as strace) and what it does open/use is then copied to a new image. And how can get those kinds of numbers, basicly it removes parts of rootFS that are not required which is basicly your base images standard files like /etc /home /usr /root..., it also removes all development dependancies, source code and other cruft you might have copied in for use during build or simular.
- 28304283409234 5y agoWhile absolutely genius, it would be more awesome if we could shift this to the left. And have dpkg or apt, or something new, only fetch and place those binaries that are needed.
- kylequest 5y agoit'll be possible to do something like that in the future where docker-slim will generate a spec that describes what your system and app package managers need to install. Using the standard package managers will be tricky for partial package installs though because it's pretty common that the app doesn't need the whole package. Even now docker-slim gives you a list of files your app needs, but the info is too low level to be usable by the standard package management tools.
- bigpod 5y agowhile in theory possible it would require a whole lot of change. Also like kyle said apt and alike(all current package managers) cant generaly deal on file per file, basis package is as is all files included, so this would require a new package manager(or old one) with packages being a single file with no dependancies for specific package. This would require new base images if we used dockerfiles and you would need to know every library every binary your program needs. While on other hand leaving in all the cruft some copy in like READMEs LICENSE files and so on. Benefit of docker-slim is that it is in many ways just a line in your already predefined CI/CD pipeline, therefore its just another step likely just working with already preexisting technologies you might use in your pipeline.
- throwaway894345 5y agoTypically I just use Go in a scratch base image where possible, since it’s super easy to compile a static binary. Drop in some certs and /etc/passwd from another image and your 2.5MB image is good to go.
- cornstalks 5y agoFrom the docker-slim README: Node.js application images: from ubuntu:14.04 - 432MB => 14MB (minified by 30.85X) from debian:jessie - 406MB => 25.1MB (minified by 16.21X) from node:alpine - 66.7MB => 34.7MB (minified by 1.92X) from node:distroless - 72.7MB => 39.7MB (minified by 1.83X) Why are the minified Alpine images bigger than Ubuntu/Debian? Are a bunch of binaries using static linking and inflating the image? Or something else?
- kylequest 5y agoYou can try using the xray command that will give you clues (docker-slim isn't just minification :-)). The diff capability in the Slim web portal is even more useful (built on top of xray).