I expect someone will leave a comment saying "But you shouldn't be entering containers, you should be using Ansible/Kubernetes". Yes, that is how I manage changes but sometimes you just have to log in and see what is going on with htop/etc
docker exec -it --augment=ubuntu my_container bash
Would start bash in the container, but also layer into the filesystem all the rest of a standard ubuntu image only for my tools, but not affecting the application in the running container.I'm pretty sure that's possible with current linux kernel mount namespace/overlayfs infrastructure used by docker - all that's needed is the command line tool to support it.
(1) If it's the bash version from the standard ubuntu image, you will need to specify where to mount your application's filesystem inside the ubuntu filesystem.
(2) If it's the bash version from your application, then it's the other way around: you will need to specify where to mount the ubuntu filesystem inside your container.
Option (1) seems more practical. My point is that you will need to specify a mountpoint either way, and your commands will need to take this mountpoint into account.
For docker and k8s, there are two helpful tools which implement what I said with simple and intuitive UI:
* https://github.com/zeromake/docker-debug
* https://github.com/aylei/kubectl-debug
Edit: Add links for the helper tools.
[0] https://github.com/docker-slim/docker-slim#debugging-minifie...
One common workaround floating around the internets is to use --cap-add SYS_PTRACE. This has the side effect of permitting the ptrace syscall, but it also gives you the ability to ptrace processes owned by other users etc. That's more than you need and it's kind of dangerous in a production-ish container.
(One can still attach after everything's running, but that's not always good enough.)
For simple shell access, use the :debug variant of distroless images which include a shell.
For more complex troubleshooting, I think other people has recommended many ways. I haven't had the need to do such troubleshooting but if I need to I would mount an image with necessary binaries into the container. This is where distroless becomes handy: I can mount a Debian image and don't worry about ABI compatibility.
https://github.com/docker-slim/docker-slim#debugging-minifie...
Generally you build a special debug image that has busybox or whatever. In case of distroless, debug image has busybox and everything that comes with it.
Also, what are you trying to see with top/htop? In ideal world you will see a single process pid 1 that is your entry point. There shouldn't be more than one process running in it.
You can get resource consumption of a container without logging into the container just like you can get running processes without getting into container.
There is nothing else you can do without dragging wholelot of dependencies:
- Anything java related will require a JDK
- Debugging any native code will require a whole debugger
- Debugging python/ruby will either work or will require dev dependencies
Sidenote: Who the fuck uses ansible to debug containers?
I just wish there was a way to do the basics:
1. Look at files within my running container (maybe even modify them, without needing vim or nano installed inside it).
2. Ping/ICMP something from within the container (again, without ping being in the container itself)
3. DNS lookups from within the container
4. Connect to a port on an IP or DNS name from within the container
5. Inspect the contents of a dead container that won't start without having to commit it first.
I did a post a while back on how I feel about debuggin within containers, and I should probably write another one because I don't think I cover those 5 things:https://battlepenguin.com/tech/my-love-hate-relationship-wit...
You obviously won’t get the same operational state but if you want to poke around a container you’ve built and see what’s in it, you can just extend it.
My rule of thumb is: as soon as I have to `docker exec` into a running container because something's wrong, this container needs to be stopped and a VM should be used instead.
Curious to know what the benefit conferred by it being 'glibc-based' is exactly?
[1] Example- https://www.redhat.com/security/data/oval/
[2] This is the closest you can get- https://github.com/alpinelinux/alpine-secdb
It works well until it doesn't. And screws up your whole deployment pipeline.
In my limited experience, some things don't compile targetting musl. If everything works alpine is sup. Else, it may be fairly difficult (and mostly unjustified) to fix.
this: https://github.com/grpc/grpc/issues/18150#issuecomment-47999...
And this: https://github.com/pypa/manylinux/issues/37
I use Python. Anytime you need to compile the source to build a pip package and that the upstream package developer decided that they don't support Alpine's libc implementation (aka musl) then you will have a big problem, unless you can control your dependencies and include as few pip packages that requires compilation or find binary builds.
For example:
from python2.7:distroless - 60.7MB => 18.3MB (minified by 3.32X)
FROM scratchscratch < distroless ~= alpine < debian-slim
Distroless nodejs images is...10mb bigger than the same on alpine.
Main purpose of distroless is less attack surface rather than size. Without package manager mutating container is PITA. Not having `ps` or `cat` makes it hard to read secrets that you injected into container one way or another.
It's a base image with binaries from Debian deb package, and with necessary stuff like ca-certificates, and absolutely nothing else, while still glibc-based (unlike Alpine base images).
Example images I built with the base image - C binary, <10MB https://hub.docker.com/r/yegle/stubby-dns
- Python binary, <50MB https://hub.docker.com/r/yegle/fava
- Go binary, 5MB https://hub.docker.com/r/yegle/dns-over-https
Another trick I use is to use https://github.com/wagoodman/dive to find the deltas between layers and manually remove it in my Dockerfile.