Podman: Difference between revisions

From CSCWiki
Jump to navigation Jump to search
mNo edit summary
mNo edit summary
Line 85: Line 85:
=== Systemd in podman ===
=== Systemd in podman ===
To run systemd in podman, just create a Dockerfile like the following:
To run systemd in podman, just create a Dockerfile like the following:
<code>
<pre>
FROM ubuntu:bionic
FROM ubuntu:bionic
Line 93: Line 93:
CMD [ "/bin/systemd" ]
CMD [ "/bin/systemd" ]
</code>
</pre>
Then run:
Then run:
<code>
<pre>
podman build --privileged -t ubuntu-systemd:bionic -f ubuntu-bionic-systemd.Dockerfile
podman build --privileged -t ubuntu-systemd:bionic -f ubuntu-bionic-systemd.Dockerfile
</code>
</pre>
If you're running this as root, I suggest using the --privileged flag. I am pretty sure that there some specific capabilities you can add instead to make it work (via the --cap-add flag), but this is easier.
If you're running this as root, I suggest using the --privileged flag. I am pretty sure that there some specific capabilities you can add instead to make it work (via the --cap-add flag), but this is easier.


Then, to run a container with this image:
Then, to run a container with this image:
<pre>
podman run -it --privileged ubuntu-systemd:bionic<code>
podman run -it --privileged ubuntu-systemd:bionic
</code>
</pre>


=== Podman in systemd ===
=== Podman in systemd ===
Podman has a built-in command to generate systemd service files to start containers and pods. For example, let's say we have a pod named bbbpod. Run the following:
Podman has a built-in command to generate systemd service files to start containers and pods. For example, let's say we have a pod named bbbpod. Run the following:
<code>
<pre>
podman generate systemd --files --name bbbpod
podman generate systemd --files --name bbbpod
</code>
</pre>
This will create .service files for the pod and the containers inside it. Now you just need to enable them:
This will create .service files for the pod and the containers inside it. Now you just need to enable them:
<code>
<pre>
mv *.service /etc/systemd/system/
mv *.service /etc/systemd/system/
systemctl daemon-reload
systemctl daemon-reload
systemctl enable pod-bbbpod.service
systemctl enable pod-bbbpod.service
</code>
</pre>
If you now run <code>systemctl start pod-bbbpod</code>, the pod and its containers will start.
If you now run <code>systemctl start pod-bbbpod</code>, the pod and its containers will start.


Line 121: Line 122:


First, we create a pod in the network we previously created:
First, we create a pod in the network we previously created:
<code>
<pre>
podman pod create --network bbbnet --name bbbpod --share net
podman pod create --network bbbnet --name bbbpod --share net
</code>
</pre>
Then run a container inside the pod:
Then run a container inside the pod:
<code>
<pre>
podman run -it --name bbb --hostname bbb --pod bbbpod --privileged ubuntu-systemd:bionic
podman run -it --name bbb --hostname bbb --pod bbbpod --privileged ubuntu-systemd:bionic
</code>
</pre>
You can add more containers to the pod:
You can add more containers to the pod:
<code>
<pre>
podman run -d --name greenlight --pod bbbpod --env-file $PWD/env bigbluebutton/greenlight:v2
podman run -d --name greenlight --pod bbbpod --env-file $PWD/env bigbluebutton/greenlight:v2
</code>
</pre>
The bbb and greenlight containers can now communicate with each other over localhost.
The bbb and greenlight containers can now communicate with each other over localhost.



Revision as of 23:06, 28 October 2021

Podman is a very neat Docker-compatible container solution. Some of the advantages it has over Docker are:

  • no daemon (uses a fork-and-exec model)
  • systemd can run inside containers very easily
  • containers can become systemd services on the host
  • non-root users can run containers

Installation

As of bullseye, podman is available in the official Debian repositories. I suggest installing it from the unstable distribution, since podman 3.2 has many useful improvements over previous versions:

apt install -t unstable podman podman-docker 

The podman-docker package provides a wrapper script so that running the command 'docker' will invoke podman. Recent versions of podman also provide API compatibility with Docker, which means that docker-compose will actually work out of the box. (For non-root users, you will need to set the DOCKER_HOST environment variable to unix://$XDG_RUNTIME_DIR/podman/podman.sock).

I suggest adding the following to /etc/containers/registries.conf so that podman automatically pulls packages from docker.io instead of quay.io:

[registries.search]
registries = ['docker.io']

Networking

Podman uses CNI plugins. If a container needs to be publicly accessible, you will want to create a bridge network. Here's how I did it.

If the host already uses a bridge interface as its primary interface (e.g. 'br0'), I suggest that you do not use this for the CNI bridge. I did that once, and when I brought down the CNI network, br0 came down with it. I suggest creating a dedicated bridge for the containers which is attached to the primary bridge via a veth pair. Here's an example from xylitol's /etc/network/interfaces:

...
auto br0
iface br0 inet static
    bridge_ports eno1
    address 129.97.134.113
    netmask 255.255.255.0
    gateway 129.97.134.1

auto podbr1
iface podbr1 inet manual
    bridge_ports none
    up ip link add name podveth0 type veth peer name podveth1
    up ip link set podveth0 master br0
    up ip link set podveth1 master podbr1
    up ip link set dev podveth0 up
    up ip link set dev podveth1 up
    down ip link del podveth0

Let's say we want to create a container (or a pod) which has a public IP address 129.97.134.173. We will create a new network for it with an IP range of length 1. In the command below, I will initially create a macvlan network, then convert it into bridge; I find this easier than trying to modify the default bridge configuration which podman creates.

podman network create -d macvlan -o parent=podbr1 --subnet 129.97.134.0/24 --ip-range 129.97.134.173/32 --gateway 129.97.134.1 bbbnet

Now open /etc/cni/net.d/bbbnet.conflist and make it look like the following:

{
   "cniVersion": "0.4.0",
   "name": "bbbnet",
   "plugins": [
      {
         "type": "bridge",
         "bridge": "podbr1",
         "ipam": {
            "type": "host-local",
            "routes": [
               {
                  "dst": "0.0.0.0/0"
               }
            ],
            "ranges": [
               [
                  {
                     "subnet": "129.97.134.0/24",
                     "rangeStart": "129.97.134.173",
                     "rangeEnd": "129.97.134.173",
                     "gateway": "129.97.134.1"
                  }
               ]
            ]
         }
      }
   ]
}

If you run podman network ls, you should now see that bbbnet is a bridge network.

Systemd

Podman integrates with systemd in both directions - systemd can run in podman, and podman can run in systemd.

Systemd in podman

To run systemd in podman, just create a Dockerfile like the following:

FROM ubuntu:bionic  
    
ENV DEBIAN_FRONTEND=noninteractive    
RUN apt update && apt install -y systemd
RUN passwd -d root    
    
CMD [ "/bin/systemd" ]

Then run:

podman build --privileged -t ubuntu-systemd:bionic -f ubuntu-bionic-systemd.Dockerfile

If you're running this as root, I suggest using the --privileged flag. I am pretty sure that there some specific capabilities you can add instead to make it work (via the --cap-add flag), but this is easier.

Then, to run a container with this image:

podman run -it --privileged ubuntu-systemd:bionic

Podman in systemd

Podman has a built-in command to generate systemd service files to start containers and pods. For example, let's say we have a pod named bbbpod. Run the following:

podman generate systemd --files --name bbbpod

This will create .service files for the pod and the containers inside it. Now you just need to enable them:

mv *.service /etc/systemd/system/
systemctl daemon-reload 
systemctl enable pod-bbbpod.service

If you now run systemctl start pod-bbbpod, the pod and its containers will start.

Pods

Podman pods are similar to Kubernetes pods; they can share namespaces with each other, such as network namespaces and UTS namespaces. In this example, we will use a network namespace.

First, we create a pod in the network we previously created:

podman pod create --network bbbnet --name bbbpod --share net

Then run a container inside the pod:

podman run -it --name bbb --hostname bbb --pod bbbpod --privileged ubuntu-systemd:bionic

You can add more containers to the pod:

podman run -d --name greenlight --pod bbbpod --env-file $PWD/env bigbluebutton/greenlight:v2

The bbb and greenlight containers can now communicate with each other over localhost.

Important: Make sure to edit /etc/hostname and /etc/network/interfaces (or whichever network manager you decide to use) in each container.