77 lines
2.4 KiB
Markdown
77 lines
2.4 KiB
Markdown
|
+++
|
||
|
title = "Getting a shell in a Docker Compose container without any shells"
|
||
|
date = 2023-03-29
|
||
|
tags = ["docker", "linux"]
|
||
|
+++
|
||
|
|
||
|
Here is a rather dumb way of entering a Docker Compose container that didn't
|
||
|
have a shell. In this specific case, I was trying to enter a Woodpecker CI
|
||
|
container without exiting it. These are my specific steps for running it, please
|
||
|
replace the paths and container names with the ones relevant to your specific
|
||
|
use-case.
|
||
|
|
||
|
At first, I tried an approach following [this][1] document. But once I got to
|
||
|
actually running commands within the namespace, I realized that this exposes the
|
||
|
exact same interface as Docker compose; if there was no shell available from the
|
||
|
Docker container entirely, then I couldn't run something from outside. I would
|
||
|
need to get some shell into the container.
|
||
|
|
||
|
[1]: https://www.redhat.com/sysadmin/container-namespaces-nsenter
|
||
|
|
||
|
Fortunately, there's a software that contains a lot of handy tools in one
|
||
|
binary: [busybox][2]. It's a GPL software that contains a small implementation
|
||
|
of a bunch of typical Unix utilities in a single static binary.
|
||
|
|
||
|
[2]: https://busybox.net/
|
||
|
|
||
|
I grabbed a copy of the busybox tool using:
|
||
|
|
||
|
```
|
||
|
$ nix build nixpkgs#pkgsStatic.busybox
|
||
|
```
|
||
|
|
||
|
(if you are not using [Nix][3], you may want to grab one of the pre-built
|
||
|
binaries from their website)
|
||
|
|
||
|
[3]: https://nixos.org/
|
||
|
|
||
|
To make sure it's statically linked (this means it doesn't depend on any
|
||
|
libraries already existing on your system, which may not be available within the
|
||
|
container), run this:
|
||
|
|
||
|
```
|
||
|
$ ldd ./result/bin/busybox
|
||
|
not a dynamic executable
|
||
|
```
|
||
|
|
||
|
If it doesn't say "not a dynamic executable" exactly, you're not using a static
|
||
|
build. If you're downloading off the website, make sure you look for something
|
||
|
that says [`musl`][4], which is a static version of libc.
|
||
|
|
||
|
[4]: https://musl.libc.org/
|
||
|
|
||
|
Now it's just a matter of getting this binary into the container.
|
||
|
|
||
|
```
|
||
|
$ docker compose cp ./result/bin/busybox woodpecker-server:/
|
||
|
```
|
||
|
|
||
|
Now, I can run a shell, using the busybox program:
|
||
|
|
||
|
```
|
||
|
$ docker compose exec woodpecker-server /busybox sh
|
||
|
/ #
|
||
|
```
|
||
|
|
||
|
If you just ran busybox without the `sh` param, then it would list all the
|
||
|
busybox utilities that were built into your static binary. At this point, I also
|
||
|
ran:
|
||
|
|
||
|
```
|
||
|
/ # /busybox --install -s /bin
|
||
|
```
|
||
|
|
||
|
within the container. This installs symlinks to busybox so it acts as each of
|
||
|
the individual programs it emulates. Now I can type `ls` instead of having to
|
||
|
run `busybox ls` every single time.
|