openSUSE MicroOS workshop featuring Podman, Skopeo, Buildah and other topics such as Linux namespaces. This workshop was carried at the Faculty of Technology, Udayana University, Bali, Indonesia during the openSUSE Asia Summit 2019.
Managing Pods & Containers
I work for La Sentinelle Ltd
Linux & OSS Advocate
I hangout during local
meetups to talk about
I blog at hacklog.in.
I am currently in the
I install openSUSE on as
many machines as I can.
What is openSUSE MicroOS?
openSUSE MicroOS is a modern single service Linux
operating system, designed for container hosts and
optimized for large deployments.
It inherits the openSUSE Tumbleweed and SUSE Linux
Enterprise knowledge while redeﬁning the operating
system into a small, eﬃcient and reliable distribution.
It is available as a separate distribution from:
MicroOS Container Host System Role
During installation select the “container
host” system role.
MicroOS comes with a minimal set of
packages by default. The container host
system role installs Podman as container
A complete installation of the MicroOS
Container host is about 1.3GiB.
Note: Container tools such as Skopeo & Buildah are
not installed. Those are not intended for server use.
Why not use Tumbleweed server directly?
Read-only root ﬁle system
Podman/runc as default container runtime
What are containers?
Shared Linux kernel
Resource and process isolation
Lighter than virtual machines
Portable across diﬀerent environments
Overview of Linux namespaces
A namespace wraps a global system resource in an
abstraction that makes it appear to the processes
within the namespace that they have their own
isolated instance of the global resource. Changes
to the global resource are visible to other
processes that are members of the namespace,
but are invisible to other processes. One use of
namespaces is to implement containers.
$ man namespaces
$ sudo unshare -u /bin/bash
Cgroup Cgroup root directory
IPC System V IPC, Posix Message queues
Network Network devices, stacks, ports, etc.
Mount Mount points
PID Process IDs
User User and group IDs
UTS Hostname and NIS domain name
Container runtimes can be categorized as being
low-level or high-level.
Low-level container runtimes would usually focus
on just running containers, e.g runc.
High-level container runtimes provide additional
features, e.g manage images and containers.
Nevertheless, running a container is often all that is
required to call “something” a container runtime.
● Kata Containers
(Mentioned in alphabetical order)
Listing Linux namespaces
The command lsns lists information about all the
currently accessible namespaces or about the
NS Namespace identiﬁer (inode number)
TYPE Kind of namespace
PATH Path to the namespace
NPROCS Number of processes in the
PID Process ID
PPID Parent Process ID
USER Username of the PID
COMMAND Command line of the PID
What is a container composed of?
Skopeo is a command line utility used to interact with
local and remote container images and container image
Skopeo can copy container images between various
containers image stores, converting them as necessary.
$ skopeo inspect docker://opensuse/leap
$ mkdir nginx
$ skopeo copy docker://nginx:latest dir:nginx
$ tree nginx
Peeking further into the container image
The container image contains several ﬁles among which are compressed layers containing ﬁles that
provide the necessary environment for a running container. Not clear enough?
Okay, ﬁne. Let’s decompress one layer to see what it contains.
$ mkdir b8f2
$ tar -C b8f2 -xf b8f262c62ec67f02536f49654de586c022043652bbb6bbf76a8dab1542627a8d
$ ls -lh b8f2
Container Image Registries
Before we experiment further with containers we need to understand a few basic things about registries.
What happened when we ran the below command earlier?
$ podman run --rm -d -p 8080:80 nginx
Podman ﬁrst checks whether there is a local image tagged “nginx” to spin a container from. If it is not
present on the system it will look for it in some “remote location”, pull the image and then run the
container. The action of pulling a container can be independent of running a container, e.g:
$ podman pull nextcloud
The remote location which we referred to is called a container registry.
Local images can be listed by executing:
$ podman images
Podman (Pod Manager) is a fully featured container
engine that is a simple daemonless tool. Podman
provides a Docker-CLI comparable command line that
eases the transition from other container engines and
allows the management of pods, containers and images.
Podman uses Buildah internally to create container
images. Both tools share image (not container) storage,
hence each can use or manipulate images (but not
containers) created by the other.
$ podman run --rm -d -p 8080:80 nginx
$ curl localhost:8080
Where does Podman store container information?
When running Podman as root, the default location
for storage is /var/lib/containers/storage.
Users cannot use this directory when running as
non root, so Podman creates the storage by
default in $HOME/.local/share/containers.
$ podman info
Running the above command produces an output
displaying some key information about Podman
conﬁguration including the path to container
Container Image Registries
Information about image registries is stored in /etc/containers/registries.conf. It is a system-wide
conﬁguration ﬁle for container image registries. The ﬁle format is TOML. More information about the
conﬁguration can be found in the man page.
$ man containers-registries.conf
The most important thing about this conﬁg ﬁle is the speciﬁcation of registry urls.
registries = ["docker.io"]
The above list contains urls of container registries where images will be searched and downloaded from.
If the list contains more that one url they should be comma separated.
$ podman run --rm -d --name webserver -h web \
-v /home/ish/summit2019:/usr/share/nginx/html \
-p 8080:80 nginx
We are running a container based on the nginx image, having name as webserver and hostname set to
web. It will map its port 80 to the host’s port 8080 and mount a volume to the path of the Nginx virtual
host root directory.
We can enter the container by executing the following.
$ podman exec -it webserver bash
The -it ﬂags specify that STDIN should be kept open and a pseudo-TTY attached. You can experiment
further with the diﬀerent ﬂags.
$ podman run --help
Printing information about containers
$ podman ps -a
Displays all containers, default shows only running containers.
$ podman ps -a -s
Displays the total ﬁle size.
$ podman ps --ns -a
Displays namespace information.
$ podman ps -a -p
Displays the pods the containers are associated with.
Display a container or image's conﬁguration
$ podman inspect container_name
This displays the low-level information on containers and images identiﬁed by name or ID. By default, this
will render all results in a JSON array.
$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/nginx latest f949e7d76d63 2 days ago 130 MB
$ podman inspect f949e7d76d63
Podman as a Systemd service
Podman wasn’t designed to manage containers
start-up order or failed containers recovery.
A Systemd unit ﬁle on the host can have the host
automatically start, stop, check the status, and
manage a container as a regular systemd service.
We create a Systemd unit ﬁle in:
We then enable the service as follows:
$ sudo systemctl enable webserver
$ sudo systemctl start webserver
ExecStart=/usr/bin/podman run --rm -d --name
webserver -h web -v
ExecStop=/usr/bin/podman stop webserver
Photo by Febiyan on Unsplash
Break time! ☕
The term pod originates from the Kubernetes project where a pod relates to a unit of deployment, i.e an
instance of an application. A pod may contain a single or multiple containers. In a multi-container pod all
the containers can communicate with each other over localhost since they share the same network
An empty pod will contain one container by default which is called the “infra container”.
$ podman pod create --name small-pod
$ podman pod ps
POD ID NAME STATUS CREATED # OF CONTAINERS INFRA ID
0173c61afadd small-pod Created About a minute ago 1 613f59088260
An infra container is a lightweight container used to coordinate the shared kernel namespace of a pod.
A quick note about conmon
Conmon is a monitoring program and
communication tool between podman and runc for
a single container.
$ podman ps -a --pod
$ ps -ef `pidof conmon`
Compare the output of the above commands to
relate one conmon process for every running
A Dockerﬁle is a text ﬁle that contains instructions
to build a container image. As the name suggests it
was introduced by Docker.
Podman supports Dockerﬁle.
$ podman build --tag myapp:1.0 -f ./Dockerfile
$ podman images
The image will be available from the local images
COPY . /app
RUN make /app
Each instruction creates one layer:
● FROM creates a layer from the golang:latest
● COPY adds ﬁles from your Docker client’s
● RUN builds your application with make.
● CMD speciﬁes what command to run within
YAML is a reverse acronym for “YAML Ain’t Markup Language”. It is
a human-readable text-based format for specifying
Kubernetes uses YAML conﬁguration ﬁles to create resources such
as pods, services and deployments.
Create a YAML conﬁg from an existing pod:
$ podman generate kube osas2019-pod > osas2019-pod.yml
Create a pods from a YAML conﬁg ﬁle:
$ podman play kube osas2019-pod.yml
More about YAML conﬁguration sets for Kubernetes Pod
resources can be found at:
- daemon off;
- containerPort: 80
Buildah is a command line tool that facilitates building
OCI container images.
What can we do with Buildah?
● Create a working container, either from scratch or
using an image as a starting point.
● Mount a working container's root ﬁlesystem for
● Unmount a working container's root ﬁlesystem.
● Use the updated contents of a container's root
ﬁlesystem as a ﬁlesystem layer to create a new
● Delete a working container or an image.
● Rename a local container.
Create a working container for your project
$ buildah from opensuse
Copy your ﬁles and set an entrypoint.
$ buildah copy opensuse-working-container app /app
$ buildah copy opensuse-working-container entrypoint.sh /opt/entrypoint.sh
$ buildah config --entrypoint “/app/entrypoint.sh” opensuse-working-container
Finally, commit your work and the container image should be available in your local image repo.
$ buildah commit opensuse-working-container myapp:1.0
$ buildah images
Feel free to send your questions to [email protected]