Skip to content

Commit

Permalink
added uts namespace, multistage build support, readme
Browse files Browse the repository at this point in the history
Signed-off-by: Tony Pujals <tony@subfuzion.com>
  • Loading branch information
subfuzion committed Jan 17, 2018
1 parent 01ad645 commit 3f8cb98
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 11 deletions.
7 changes: 6 additions & 1 deletion Dockerfile
@@ -1,3 +1,8 @@
FROM alpine:edge as BUILD
RUN apk update && apk add build-base
COPY nsenter1.c ./
RUN cc -Wall -static nsenter1.c -o /usr/bin/nsenter1

FROM scratch
COPY /usr/bin/nsenter1 /usr/bin/nsenter1
COPY --from=BUILD /usr/bin/nsenter1 /usr/bin/nsenter1
ENTRYPOINT ["/usr/bin/nsenter1"]
5 changes: 0 additions & 5 deletions Dockerfile.build

This file was deleted.

3 changes: 1 addition & 2 deletions Makefile
@@ -1,3 +1,2 @@
default:
docker build -t nsenter1:build -f Dockerfile.build .
docker run nsenter1:build | docker build -t justincormack/nsenter1 -
docker build -t justincormack/nsenter1 .
70 changes: 70 additions & 0 deletions README.md
@@ -0,0 +1,70 @@
# nsenter1

[![Docker Build Status](https://img.shields.io/docker/build/subfuzion/nsenter1.svg)](subfuzion/nsenter1)

Minimal image for `nsenter` to namespaces of PID 1

* mnt
* uts
* net
* ipc

To achieve the above with the basic alpine image you would enter:

$ docker run -it --rm --privileged --pid=host alpine:edge nsenter -t 1 -m -u -n -i sh
/ #

Unfortunately, however, there is an [outstanding issue](https://github.com/gliderlabs/docker-alpine/issues/359)
that prevents specifying the target pid.

With this image, you can simply run the following:

$ docker run -it --rm --privileged --pid=host subfuzion/nsenter1
/ #

## So what is this good for

`nsenter` allows you to enter a shell in a running container (technically into the namespaces that provide
a container's isolation and limited access to system resources). The crazy thing is that this image allows
you to run a privileged container that runs nsenter for the container running as pid 1. How is this useful?

Well, this is useful when you are running a container-optimized Linux distribution such as [LinuxKit](https://blog.docker.com/2017/04/introducing-linuxkit-container-os-toolkit/).
Here is one simple example: say you want to teach a few people about Docker networking and you want to
show them how to inspect the default bridge network after starting two containers using `ip addr show`;
the problem is if you are demonstrating with Docker for Mac, for example, your containers are not running on
your host directly, but are running instead inside of a minimal Linux OS virtual machine specially built for
running containers, i.e., LinuxKit. But being a lightweight environment, LinuxKit isn't running `sshd`, so
how do you get access to a shell so you can run `nsenter` to inspect the namespaces for the pid 1 container?

Well, you could run the following:

$ screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/tty

Docker for Mac does expose a screen session to attach to, but it's a bit less than ideal if you're not familiar
with screen. It's not a big deal, but it's not optimal and it's also very specific to Docker for Mac. Since
we're already running Docker the general solution is ideal in this case:

```
$ docker run -it --rm --privileged --pid=host subfuzion/nsenter1
/ # ip a
256: vethb72bfa3@if255: <BROADCAST,MULTICAST,UP,LOWER_UP,M-DOWN> mtu 1500 qdisc noqueue master docker0 state UP
link/ether 7a:41:32:02:63:7c brd ff:ff:ff:ff:ff:ff
inet6 fe80::7841:32ff:fe02:637c/64 scope link
valid_lft forever preferred_lft forever
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 brd 127.255.255.255 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP qlen 1000
link/ether 02:50:00:00:00:01 brd ff:ff:ff:ff:ff:ff
inet 192.168.65.3/24 brd 192.168.65.255 scope global eth0
valid_lft forever preferred_lft forever
inet6 fe80::49e8:1c10:4c64:c980/64 scope link
valid_lft forever preferred_lft forever
...
```

Have fun!

11 changes: 8 additions & 3 deletions nsenter1.c
Expand Up @@ -17,6 +17,7 @@ int main(int argc, char **argv) {
char *cmd = shell;
char **args = def;
int fdm = open("/proc/1/ns/mnt", O_RDONLY);
int fdu = open("/proc/1/ns/uts", O_RDONLY);
int fdn = open("/proc/1/ns/net", O_RDONLY);
int fdi = open("/proc/1/ns/ipc", O_RDONLY);
int froot = open("/proc/1/root", O_RDONLY);
Expand All @@ -27,15 +28,19 @@ int main(int argc, char **argv) {
}

if (setns(fdm, 0) == -1) {
perror("setns");
perror("setns:mnt");
exit(1);
}
if (setns(fdu, 0) == -1) {
perror("setns:uts");
exit(1);
}
if (setns(fdn, 0) == -1) {
perror("setns");
perror("setns:net");
exit(1);
}
if (setns(fdi, 0) == -1) {
perror("setns");
perror("setns:ipc");
exit(1);
}
if (fchdir(froot) == -1) {
Expand Down

0 comments on commit 3f8cb98

Please sign in to comment.