Share a network namespace between containers so they communicate via localhost.
Pods let multiple containers share a network namespace, so they can
communicate over 127.0.0.1 without any port forwarding or bridge
configuration. This is the same model used by Kubernetes pods.
See also the architecture documentation for implementation details.
sudo sdme pod new mypod
This creates an isolated network namespace with only a loopback interface. Containers that join the pod share this namespace and can reach each other on localhost.
List and remove pods:
sudo sdme pod ls
sudo sdme pod rm mypod
sudo sdme pod rm -a # remove all pods
sudo sdme pod rm -a -f # force: also stop and remove attached containers
The --pod flag puts the entire container into the pod's network
namespace. All processes inside the container share it.
Create a pod and two containers. We use the OCI nginx rootfs (from the OCI tutorial) since pod containers only have loopback and cannot download packages.
sudo sdme pod new webpod
Start an nginx server in the pod:
sudo sdme create http-server -r nginx --pod webpod --started
Start a client in the same pod and drop into a shell. The client uses a host clone which already has curl:
sudo sdme new http-client --pod webpod
Inside the client, curl the server via localhost:
curl localhost
You should see the nginx welcome page. Both containers share the same loopback interface.
You can see both containers and their pod association with:
sudo sdme ps
The POD column shows which pod each container belongs to.
Pod network namespaces start with only a loopback interface. Without external networking, containers in a pod cannot reach the internet, download packages, or communicate with anything outside the pod.
To add external connectivity, use sdme pod net attach:
sudo sdme pod net attach webpod veth
This creates a veth pair between the pod and the host. The host's systemd-networkd handles DHCP and NAT automatically. See the external connectivity section below.
Without external networking, install any software you need before joining the pod, or use pre-built OCI rootfs images.
--pod works with --userns, --hardened, and --strict. The
container is launched via nsenter --net= so the pod's network
namespace is entered before nspawn creates the user namespace.
The --oci-pod flag is for OCI application containers. Only the OCI
app service process enters the pod's network namespace; the
container's init and other services remain in their own namespace.
This works with --hardened and --strict because the network
namespace join happens inside the container's own namespace.
Create a pod and import redis:
sudo sdme pod new dbpod
sudo sdme fs import redis docker.io/redis --base-fs ubuntu
Start redis in the pod with hardened security:
sudo sdme create redis-server -r redis --oci-pod dbpod --hardened --started
Verify redis is running:
sudo sdme logs redis-server --oci
Start a client container in the same pod using the same redis
rootfs, so redis-cli is available. Both containers use
--oci-pod with --hardened:
sudo sdme create redis-client -r redis --oci-pod dbpod --hardened --started
Test the connection from the client:
sudo sdme exec redis-client --oci -- redis-cli ping
You should see PONG. Both containers share the pod's network
namespace and communicate over localhost, each running with
hardened security.
Feature --pod --oci-pod
----------------- --------------------- -------------------------
Scope Entire container OCI app service only
Container types Any OCI app rootfs required
Userns/hardened Compatible Compatible
Requires (nothing extra) --private-network or
--hardened/--strict
Use case General-purpose pods Security-hardened apps
Both flags can be used on different containers in the same pod. The pod's network namespace is shared regardless of which flag each container uses to join it.
Pods start with loopback-only networking. Use pod net attach to
give containers in a pod internet access.
Requires: iproute2 (ip), dhcpcd.
Creates a point-to-point veth between the pod and the host:
sudo sdme pod new mypod
sudo sdme new mybox --pod mypod
sudo sdme start mybox
sudo sdme pod net attach mypod veth
Test connectivity from inside the container:
sudo sdme exec mybox -- ping -c1 8.8.8.8
Detach when no longer needed:
sudo sdme pod net detach mypod
Connects the pod to a named zone bridge. Multiple pods and regular containers on the same zone can reach each other directly:
sudo sdme pod new pod1
sudo sdme pod new pod2
sudo sdme pod net attach pod1 zone myzone
sudo sdme pod net attach pod2 zone myzone
Containers in pod1 and pod2 can now communicate through the
vz-myzone bridge, and both have internet access.
The host's systemd-networkd handles everything: DHCP serving, NAT
(IPMasquerade), and IP forwarding. sdme creates the veth pair with
interface names that match nspawn conventions (ve-*, vb-*,
vz-*), so networkd's default configs apply automatically.
A host-managed systemd service (sdme-pod-net@{pod}.service) runs
dhcpcd inside the pod's netns using NetworkNamespacePath=. The
host's systemd manages the DHCP client lifecycle.
DNS servers from the DHCP lease are extracted and written to each
container's /etc/resolv.conf (for --pod) or each OCI app's
chroot resolv.conf (for --oci-pod). Running containers are
updated immediately on attach and detach.
Attach and detach are live operations: running containers see the
interface appear or disappear immediately. Both --pod and
--oci-pod containers work because they share the same netns.
After a reboot, networking is automatically restored when the first container referencing the pod starts.
sudo sdme pod ls
The table shows each pod's name, whether its netns is active,
networking mode (NET), zone name, IP addresses, and creation time.
Pods without external networking show - in the NET and ADDRESSES
columns. Use --json or --json-pretty for structured output
including DNS servers and container membership.
Pods using zone mode share the same bridge as regular containers
using --network-zone. They can reach each other directly:
sudo sdme pod new mypod
sudo sdme pod net attach mypod zone myzone
sudo sdme new mybox --pod mypod
sudo sdme new standalone -r ubuntu --network-zone=myzone
Both mybox (in the pod) and standalone (regular container) are
on the vz-myzone bridge and can communicate.
Use --attach to combine pod creation and network attachment:
sudo sdme pod new mypod --attach veth
sudo sdme pod new mypod --attach zone --zone myzone