/dev/posts/

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