Exposing services in/out Podman containers
Published:
Updated:
Some more tips for interacting with the namespaces of Podman containers.
Table of content
Exposing container services to the host
Get the PID of the target container:
pid=$(podman inspect "$container" -f '{{.State.Pid}}')
Expose a container TCP port as a host TCP port:
systemd-socket-activate -l 127.0.0.1:8080 --inetd -a \
nsenter -t "$pid" -U -n \
nc 127.0.0.1 8080
Expose a container Unix socket port as a host TCP port:
systemd-socket-activate -l 127.0.0.1:8080 --inetd -a \
nsenter -t "$pid" -U -m \
nc -U /run/service.sock
Expose a container Unix abstract socket port as a host TCP port:
systemd-socket-activate -l 127.0.0.1:8080 --inetd -a \
nsenter -t $pid -U -n \
nc -U @/run/service.sock
Expose as host Unix socket:
systemd-socket-activate -l /tmp/service.sock --inetd -a -- \
...
Exposing host services to the container
Using some small scripts I wrote
(socket-activate
and socket-listen-inetd
),
we can expose host services to the container.
Expose a host TCP port as a container TCP port:
socket-activate --socket family=INET listen=50 type=STREAM proto=tcp bind=127.0.0.1:25 \
userns=/proc/$pid/ns/user netns=/proc/$pid/ns/net -- \
socket-listen-inetd nc 127.0.0.1 25
Expose a host TCP port as a container Unix socket:
socket-activate --socket family=INET listen=50 type=STREAM proto=tcp bind=127.0.0.1:25 \
userns=/proc/$pid/ns/user netns=/proc/$pid/ns/net -- \
socket-listen-inetd nc 127.0.0.1 25
Socket activation and Podman
As described in Podman's socket activation documentation, we can pass sockets to Podman:
systemd-socket-activate -l 8080 podman run --rm --network=none localhost/socket-activate-httpd
where localhost/socket-activate-httpd
is a container
which spawns a daemon using socket activation.
Note: LISTEN_PID
when using socket activation with Podman
The socket activation protocol uses a LISTEN_PID
environmenrt variable
which is expected to contain the PID
of the process.
However, when passing sockets to Podman, the LISTEN_PID
value
would be wrong as the container main process is PID 1 in the container.
Podman actually
fixes LISTEN_PID
automatically:
$ LISTEN_PID=90 podman run --rm --network=none docker.io/library/alpine env
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
container=podman
HOME=/root
HOSTNAME=2cc06377537d
LISTEN_PID=1
$ systemd-socket-activate -l 8080 env podman run --rm --network=none docker.io/library/alpine env
Listening on [::]:8080 as 3.
Communication attempt on fd 3.
Execing env (env podman run --rm --network=none docker.io/library/alpine env)
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
container=podman
HOME=/root
HOSTNAME=3992bece44fa
LISTEN_PID=1
LISTEN_FDS=1