In the previous chapters, we discussed the history of containers, their adoption, and the various technologies that contribute to their spread, while also looking at the main differences between Docker and Podman.
Now, it’s time to start working with real examples: in this chapter, we will learn about how to get Podman up and running on your preferred Linux operating system so that we can start our first container. We will discover the various installation methods, all the prerequisites, and then start a container.
In this chapter, we’re going to cover the following main topics:
Having good technical experience in administering a Linux operating system would be preferable for understanding the key concepts provided in this chapter.
We will go through the main steps of installing new software on various Linux distributions, so having some experience as a Linux sysadmin could be helpful in troubleshooting possible issues during installation.
In addition, some of the theoretical concepts that were explained in the previous chapters could help you understand the procedures described in this chapter.
Podman is supported on different distributions and operating systems. It is very easy to install, and the various distributions now provide their own maintained packages that can be installed with their specific package managers.
In this section, we will cover the different installation steps for the most common GNU/Linux distributions, as well as on macOS and Windows, despite the focus of this book being on Linux-based environments.
As a bonus topic, we will also learn how to build Podman directly from source.
The choice between the different distributions of the GNU/Linux operating system is something that is dictated by the user’s preferences and needs, which are usually influenced by several factors that are outside the scope of this book.
Many advanced users today choose Linux distributions as their main operating systems. However, there is a large quota, especially among developers, who stick to macOS as their standard operating system. Microsoft Windows still retains the largest market share on desktop workstations and laptops.
Today, we have a huge ecosystem of Linux distributions that have evolved from a smaller subset of core, historical distributions such as Debian, Fedora, Red Hat Enterprise Linux, Gentoo, Arch, and openSUSE. Specialized websites such as DistroWatch (https://distrowatch.com) keep track of the many releases of Linux and BSD-based distributions.
Despite running a Linux kernel, the various distributions have different architectural approaches for userspace behavior, such as filesystem structure, libraries, or packaging systems used to deliver software releases.
Another significant difference is related to security and mandatory access control subsystems: for example, Fedora, CentOS, Red Hat Enterprise Linux, and all the derivates lean on SELinux as their mandatory access control subsystem. On the other hand, Debian, Ubuntu, and their derivates are based on a similar solution called AppArmor.
Podman interacts with both SELinux and AppArmor to provide better container isolation, but the underlying interfaces are different.
Important Note
All this book’s examples and source code has been written and tested using Fedora Workstation 34 as the reference OS.
Those of you who want to reproduce an environment as close as possible to the book in their lab have different options:
Running instances on public clouds is the best option for users who are not able to run virtual machines locally.
Providers such as Amazon Web Services, Google Cloud Platform, Microsoft Azure, and DigitalOcean also offer ready-to-use Fedora-based cloud instances with low monthly prices for smaller sizes.
Prices can vary in time and across tiers and keeping track of them is beyond the purpose of this book. Almost all providers offer free plans for learning or basic use, with small/micro tiers at very low prices.
Containers are Linux-based, and the different container engines and runtimes interact with the Linux kernel and libraries to operate. Windows has recently introduced support for native containers with an approach to isolation that’s quite close to the Linux namespace concepts described previously. However, only Windows-based images can run natively and not all container engines support native execution.
The same considerations are valid for macOS: its architecture is not based on Linux but on a hybrid Mach/BSD kernel called XNU. For this reason, it does not offer the Linux kernel features necessary to run containers natively.
For both Windows and macOS, a virtualization layer that abstracts the Linux machine is necessary to run native Linux containers.
Podman offers remote client functions for Windows and macOS, enabling users to connect to a local or remote Linux box.
Windows users can also benefit from an alternative approach based on the Windows Subsystem for Linux (WSL) 2.0, a compatibility layer that runs a lightweight VM to expose Linux kernel interfaces along with Linux userspace binaries, thanks to Hyper-V virtualization support.
The following sections will cover the necessary steps for installing Podman on the most popular Linux distributions, as well as macOS and Windows.
Fedora packages are maintained by its wide community and managed with the DNF package manager. To install Podman, run the following command from a terminal:
# dnf install –y podman
This command installs Podman and configures the environment with config files (covered in the next section). It also installs systemd units to provide additional features such as REST API services or container auto-updates.
Podman can be installed on CentOS 7, CentOS 8, and CentOS Stream (https://www.centos.org/). Users installing on CentOS 7 must have the Extras repository enabled, while users installing on CentOS 8 and Stream must have the Podman package available from the already enabled AppStream repository.
To install Podman, run the following command from a terminal:
# yum install –y podman
Like in Fedora, this command installs Podman and all its dependencies, including config files and systemd unit files.
To install Podman on Red Hat Enterprise Linux (RHEL) (https://www.redhat.com/en/technologies/linux-platforms/enterprise-linux), users should follow two different procedures on RHEL 7 and RHEL 8.
On RHEL 7, users must enable the extra channel and then install the Podman package:
# subscription-manager repos
--enable=rhel-7-server-extras-rpms
# yum -y install podman
On RHEL 8, the Podman package is available on a dedicated module called container-tools. Modules are custom sets of RPM packages that can be organized in streams with independent release cycles:
# yum module enable -y container-tools:rhel8
# yum module install -y container-tools:rhel8
The container-tools module installs, along with Podman, two useful tools, both of which will be covered later in this book:
The title of this subsection is a bit of a joke. The reality is that Podman is already installed on both distributions and is a crucial tool for running containerized workloads.
The Fedora CoreOS and Fedora SilverBlue distributions are immutable, atomic operating systems aimed to be used on server/cloud and desktop environments, respectively.
Fedora CoreOS (https://getfedora.org/en/coreos/) is the upstream of Red Hat CoreOS, the operating system used to run Red Hat OpenShift and the base OS of OpenShift Kubernetes Distribution (OKD), the community-based Kubernetes distribution used as the upstream of Red Hat OpenShift.
Fedora Silverblue (https://silverblue.fedoraproject.org/) is a desktop-focused immutable operating system that aims to provide a stable and comfortable desktop user experience, especially for developers working with containers.
So, on both Fedora CoreOS and Fedora Silverblue, just open a terminal and run Podman.
The Podman package is available on Debian (https://www.debian.org/) since version 11, codename Bullseye (named after the famous toy horse from the Toy Story 2 and 3 movies).
Debian uses the apt-get package handling utility to install and upgrade system packages.
To install Podman on a Debian system, run the following command from the terminal:
# apt-get –y install podman
The preceding command installs the Podman binary and its dependencies, along with its config files, systemd units, and man pages.
Being built on Debian, Ubuntu (https://ubuntu.com/) behaves in an analogous way for package management. To install Podman on Ubuntu 20.10 or later, run the following commands:
# apt-get -y update
# apt-get -y install podman
These two commands update the system packages and then install the Podman binaries and related dependencies.
The openSUSE distribution (https://www.opensuse.org/) is backed by SUSE and is available in two different flavors – the rolling release known as Tumbleweed, and the LTS distribution known as Leap. Podman is available in the openSUSE repositories and can be installed with the following command:
# zypper install podman
The Zypper package manager will download and install all the necessary packages and dependencies.
Gentoo (https://www.gentoo.org/) is a clever distribution that is characterized by building installed packages directly on the target machine with the optional extra user customizations. To achieve this, it uses the Portage package manager, inspired by FreeBSD ports.
To install Podman on Gentoo, run the following command:
# emerge app-emulation/podman
The emerge utility will download and automatically build the Podman sources on the system.
Arch Linux (https://archlinux.org/) is a rolling Linux distribution that shines for being highly customizable. It uses the pacman package manager to install and update packages from official and users' custom repositories.
To install Podman on Arch Linux and derivate distributions, run the following command from the terminal:
# pacman –S podman
By default, Podman’s installation on Arch Linux does not permit rootless containers. To enable them, follow the official Arch wiki instructions: https://wiki.archlinux.org/title/Podman#Rootless_Podman.
The famous Raspberry Pi single-board computer has achieved enormous success among developers, makers, and hobbyists.
It runs the Raspberry Pi OS (https://www.raspberrypi.org/software/operating-systems/#raspberry-pi-os-32-bit), which is based on Debian.
Podman’s arm64 build is available and can be installed by following the same steps described previously for the Debian distribution.
Apple users who develop and run Linux containers can install and use Podman as a remote client, while the containers are executed on a remote Linux box. The Linux machine can also be a VM that’s executed on macOS and directly managed by Podman.
To install Podman using the Homebrew package manager, run the following command from the terminal:
$ brew install podman
To initialize the VM running the Linux box, run the following commands:
$ podman machine init
$ podman machine start
Alternatively, users can create and connect to an external Linux host.
Another valid approach on macOS to creating fast, lightweight VMs for development use is Vagrant. When the Vagrant machine is created, users can manually or automatically provision additional software such as Podman and start using the customized instance using the remote client.
To run Podman as a remote client, simply download and install the latest release from the GitHub releases page (https://github.com/containers/podman/releases/). Extract the archive in a suitable location and edit the TOML-encoded containers.conf file to configure a remote URI for the Linux machine or pass additional options.
The following code snippet shows an example configuration:
[engine]
remote_uri= " ssh://[email protected]:22/run/podman/podman.sock"
The remote Linux machine exposes Podman on a UNIX socket managed by a systemd unit. We will cover this topic in greater detail later in this book.
To run Podman on WSL 2.0, users must first install a Linux distribution from the Microsoft Store on their Windows host. There is a variety of available distributions under the Microsoft catalog.
The following example is based on Ubuntu 20.10:
# apt-get –y install podman
# mkdir -p /etc/containers
# echo -e "[registries.search] registries =
[‘docker.io’, ‘quay.io’]" | tee /etc/containers/registries.conf
The preceding commands install the latest Podman stable release and configure the /etc/containers/registries.conf file to provide a registries whitelist.
After its installation, some minor customizations are necessary to adapt it to the WSL 2.0 environment:
# cp /usr/share/containers/libpod.conf /etc/containers
# sed –i ‘s/ cgroup_manager = "systemd"/ cgroup_manager = "cgroupfs"/g’ /etc/containers/libpod.conf
# sed –i ‘s/ events_logger = "journald"/ events_logger = "file"/g’ /etc/containers/libpod.conf
The preceding command configures logging and CGroup management to successfully run rootful containers in the subsystem.
Building an application from source has many advantages: users can inspect and customize code before building, cross-compile for different architectures, or selectively build only a subset of binaries. It is also a great learning opportunity to get into the project’s structure and understand its evolution. Last but not least, building from source lets the users get the latest development versions with cool new features, bugs included.
The following steps assume that the building machine is a Fedora distribution. First, we must install the necessary dependencies needed to compile Podman:
# dnf install -y
btrfs-progs-devel
conmon
containernetworking-plugins
containers-common
crun
device-mapper-devel
git
glib2-devel
glibc-devel
glibc-static
go
golang-github-cpuguy83-md2man
gpgme-devel
iptables
libassuan-devel
libgpg-error-devel
libseccomp-devel
libselinux-devel
make
pkgconfig
This command will take a while to install all the packages and their cascading dependencies.
When the installation is complete, choose a working directory and clone the Podman repository using the git command:
$ git clone https://github.com/containers/podman.git
This command will clone the entire repository in the working directory.
Change to the project directory and start the build:
$ cd podman
$ make package-install
The make package-install command compiles the source code, builds the RPM files, and installs the packages locally. Remember that the RPM format is associated with Fedora/CentOS/RHEL distributions and managed by the dnf and yum package managers.
The build process will take a few minutes to complete. To test the successful installation of the packages, simply run the following code:
$ podman version
Version: 4.0.0-dev
API Version: 4.0.0-dev
Go Version: go1.16.6
Git Commit: cffc747fccf38a91be5cd106d2e507afaaa23e14
Built: Sat Aug 4 00:00:00 2018
OS/Arch: linux/amd64
Sometimes, it is useful to build the binaries on a dedicated build host and then deploy them on other machines, using either package managers or simple archives. To only build the binaries, run the following command:
$ make
At the end of the build, the binaries will be available under the bin/ folder. To install the compiled binaries and config files locally by simply copying them into the target directories defined in the Makefile, run the following command:
$ make install
To create a binary release similar to the .tar.gz archive, which is available on the GitHub release page, run the following command:
$ make podman-release.tar.gz
Bonus tip: Building a different version is very easy – just switch to the tag of the target release using the git command. For example, to build v3.3.1, use the following command:
$ git checkout v3.3.1
In this section, we learned how to install binary releases of Podman on different distributions using their respective package managers. We also learned how to install the Podman remote client on macOS and Windows, along with Windows WSL 2.0 mode. We closed this section by showing you how to build from source.
In the next section, we will learn how to configure Podman for the first run by preparing the system environment.
Once the Podman packages have been installed, Podman is ready to be used out of the box. However, some minor customizations can be useful to provide better interoperability with external registries or to customize runtime behaviors.
Podman searches for and downloads images from a list of trusted container registries. The /etc/containers/registries.conf file is a TOML config file that can be used to customize whitelisted registries that are allowed to be searched and used as image sources, as well as registry mirroring and insecure registries without TLS termination.
In this config file, the unqualified-search-registries key is populated with an array of unqualified registries with no specification regarding images repositories and tags.
On a Fedora system, with a new installation of Podman, this key has the following content:
unqualified-search-registries = ["registry.fedoraproject.org", "registry.access.redhat.com", "docker.io", "quay.io"]
Users can add or remove registries from this array to let Podman search and pull from them.
Important Note
Be very cautious when adding registries and use only trusted registries to avoid pulling images containing malicious code.
The default list is adequate to search for and run all the book examples. Those of you who are already running private registries can try to add them to the unqualified search registries array.
Since registries are both private and public, please keep in mind that private registries usually require additional authentication to be accessed. This can be accomplished with the podman login command, which will be covered later in this book.
If the $HOME/.config/containers/registries.conf file is found in the user home, it overrides the /etc/containers/registries.conf file. In this way, different users on the same system will be able to run Podman with their custom registry whitelists and mirrors.
This is an optional step and, in the absence of specific needs, this section’s contents can be safely skipped.
As we mentioned previously, Podman is a daemonless container manager that needs no background service to run containers. However, users may need to interact with the Libpod APIs exposed by Podman, especially when migrating from a Docker-based environment.
Podman can expose its APIs using a UNIX socket (default behavior) or a TCP socket. The latter option is less secure because it makes Podman accessible from the outside world, but it is necessary in some cases, such as when it should be accessed by a Podman client on a Windows or macOS workstation.
Important Note
Be careful when running the API service using a TCP endpoint on a machine exposed to the internet since the service will be globally accessible.
The following command exposes the Podman APIs on a UNIX socket:
$ sudo podman system service --time=0
unix:///run/podman/podman.sock
After running this command, users can connect to the API service.
Having to run this command on a terminal window is not a handy approach. Instead, the best approach is to use a systemd socket (see man systemd.socket).
Socket units in systemd are special kinds of service activators: when a request reaches the pre-defined endpoint of the socket, systemd immediately spawns the homonymous service.
When Podman is installed, the podman.socket and podman.service unit files are created. podman.socket has the following content:
# cat /usr/lib/systemd/system/podman.socket
[Unit]
Description=Podman API Socket
Documentation=man:podman-system-service(1)
[Socket]
ListenStream=%t/podman/podman.sock
SocketMode=0660
[Install]
WantedBy=sockets.target
The ListenStream key holds the relative path of the socket, which is expanded to /run/podman/podman.sock:
The podman.service has the following content:
# cat /usr/lib/systemd/system/podman.service
[Unit]
Description=Podman API Service
Requires=podman.socket
After=podman.socket
Documentation=man:podman-system-service(1)
StartLimitIntervalSec=0
[Service]
Type=exec
KillMode=process
Environment=LOGGING="--log-level=info"
ExecStart=/usr/bin/podman $LOGGING system service
[Install]
WantedBy=multi-user.target
The ExecStart= field indicates the command to be launched by the service, which is the same podman system service command we showed previously.
The Requires= field indicates that the podman.service unit needs podman.socket to be activated.
So, what happens when we enable and start the podman.socket unit? systemd handles the socket and waits for a connection to the socket endpoint. When this event happens, it immediately starts the podman.service unit. After a period of inactivity, the service is stopped again.
To enable and start the socket unit, run the following command:
# systemctl enable --now podman.socket
We can test the results with a simple curl command:
# curl --unix-socket /run/podman/podman.sock
http://d/v3.0.0/libpod/info
The printed output will be a JSON payload that contains the container engine configuration.
What happened when we hit the URL? Under the hood, the service unit was immediately started and triggered by the socket when the connection was issued. Some of you may have noticed a slight delay (in the order of a 1/10th of a second) the very first time the command was executed.
After 5 seconds of inactivity, podman.service deactivates again. This is due to the default behavior of the podman system service command, which runs for 5 seconds only by default unless the –time option is passed to provide a different timeout (a value of 0 means forever).
Podman’s default configuration works out of the box for most use cases, but its configuration is highly flexible. The following configuration files are available for customizing its behavior:
This file can be used to customize the behavior of the engine. Users can influence how the container is created and its life cycle by customizing settings such as logging, DNS resolution, environment variables, shared memory usage, Cgroup management, and many others.
For a full list of settings, check out the related man page, which was installed along with the Podman package. (man containers.conf)
The default path of this file is /usr/share/containers/storage.conf and overrides can be found or created under /etc/containers/storage.conf for system-wide customizations.
User-scoped configurations that impact rootless containers can be found under $XDG_CONFIG_HOME/containers/storage.conf or $HOME/.config/containers/storage.conf.
It can be found under /usr/share/containers/mounts.conf and overridden by a file located at /etc/containers/mounts.conf.
In rootless mode, the override file can be placed under $HOME/.config/containers/mounts.conf.
The default path for this file is /usr/share/containers/seccomp.json. The seccomp man page (man seccomp) provides an overview of how seccomp works on a Linux system.
This config file accepts three kinds of policies:
The default configuration is to accept every image (the insecureAcceptAnything policy), but it can be modified to pull only trusted images that can be verified by a signature. Users can define custom GPG keys to verify the signatures and the identity that signed them. For extra details about the possible policies and configuration examples, please refer to the related man page (man containers-policy.json).
In this section, we discussed some basic configurations of Podman that are useful to know from when Podman is first installed. In the next section, we will cover our first container execution examples.
Now, it’s time to finally run our first container.
In the previous section, we uncovered how to install Podman on our favorite Linux distribution, as well as what’s included in the base packages once installed. Now, we can start using our daemonless container engine.
Running containers in Podman is handled through the podman run command, which accepts many options for controlling the behavior of the just ran container, its isolation, its communication, its storage, and so on.
The easiest and shortest Podman command for running a brand-new container is as follows:
$ podman run <imageID>
We have to replace the imageID string with the image name/location/tag we want to run. If the image is not present in the cache or we have not downloaded it before, Podman will pull the image for us from the respective container registry.
To introduce this command and its options, let’s start simple and run the following command:
$ podman run -i -t fedora /bin/bash
Resolved "fedora" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull registry.fedoraproject.org/fedora:latest...
Getting image source signatures
Copying blob ecfb9899f4ce done
Copying config 37e5619f4a done
Writing manifest to image destination
Storing signatures
[root@ec444ad299ab /]#
Let’s see what Podman did once we executed the previous command:
The previous command prompted an interactive shell thanks to the two options that we can analyze, as follows:
As stated in the previous chapters, when a container is created, the isolated processes inside it will run on a writable root filesystem, as a result of a layered overlay.
This allows any process to write files, but don’t forget that they will last until the container is running, as containers are ephemeral by default.
Now, you can execute any command and check its output in the console we just brought up:
[root@ec444ad299ab /]# dnf install -y iputils iproute
Last metadata expiration check: 0:01:50 ago on Mon Sep 13 08:54:20 2021.
Dependencies resolved.
=============================================================================================================================================================================
Package Architecture Version Repository Size
=============================================================================================================================================================================
Installing:
iproute x86_64 5.10.0-2.fc34 fedora 679 k
iputils x86_64 20210202-2.fc34 fedora 170 k
Installing dependencies:
...
[root@ec444ad299ab /]# ip r
default via 10.0.2.2 dev tap0
10.0.2.0/24 dev tap0 proto kernel scope link src 10.0.2.100
[root@ec444ad299ab /]# ping -c2 10.0.2.2
PING 10.0.2.2 (10.0.2.2) 56(84) bytes of data.
64 bytes from 10.0.2.2: icmp_seq=1 ttl=255 time=0.030 ms
64 bytes from 10.0.2.2: icmp_seq=2 ttl=255 time=0.200 ms
--- 10.0.2.2 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1034ms
rtt min/avg/max/mdev = 0.030/0.115/0.200/0.085 ms
As you can see, in the previous example, we just installed two packages for inspecting the container’s network configuration and then executing a ping to the default router that’s assigned to the virtual networking of our running container. Again, if we stop this container, any changes will be lost.
To exit this interactive shell, we can just press Ctrl + D or execute the exit command. By doing this, the container will be terminated because the main running process we requested to execute (/bin/bash) will stop!
Now, let’s look at some other nice and useful options we can use with the podman run command.
As we learned previously, Podman gives us the chance to attach an interactive shell to our running container. However, we will soon discover that this is not the preferred way to run our containers.
Once a container has been started, we can easily detach from it, even if we start it with an interactive tty attached:
$ podman run -i -t registry.fedoraproject.org/f29/httpd
Trying to pull registry.fedoraproject.org/f29/httpd:latest...
Getting image source signatures
Copying blob aaf5ad2e1aa3 done
Copying blob 7692efc5f81c done
Copying blob d77ff9f653ce done
Copying config 25c76f9dcd done
Writing manifest to image destination
Storing signatures
=> sourcing 10-set-mpm.sh ...
=> sourcing 20-copy-config.sh ...
=> sourcing 40-ssl-certs.sh ...
AH00558: httpd: Could not reliably determine the server’s fully qualified domain name, using 10.0.2.100. Set the ‘ServerName’ directive globally to suppress this message
[Tue Sep 14 09:26:05.691906 2021] [ssl:warn] [pid 1:tid 140416655523200] AH01882: Init: this version of mod_ssl was compiled against a newer library (OpenSSL 1.1.1b FIPS 26 Feb 2019, version currently loaded is OpenSSL 1.1.1 FIPS 11 Sep 2018) - may result in undefined or erroneous behavior
[Tue Sep 14 09:26:05.692610 2021] [ssl:warn] [pid 1:tid 140416655523200] AH01909: 10.0.2.100:8443:0 server certificate does NOT include an ID which matches the server name
AH00558: httpd: Could not reliably determine the server’s fully qualified domain name, using 10.0.2.100. Set the ‘ServerName’ directive globally to suppress this message
[Tue Sep 14 09:26:05.752028 2021] [ssl:warn] [pid 1:tid 140416655523200] AH01882: Init: this version of mod_ssl was compiled against a newer library (OpenSSL 1.1.1b FIPS 26 Feb 2019, version currently loaded is OpenSSL 1.1.1 FIPS 11 Sep 2018) - may result in undefined or erroneous behavior
[Tue Sep 14 09:26:05.752806 2021] [ssl:warn] [pid 1:tid 140416655523200] AH01909: 10.0.2.100:8443:0 server certificate does NOT include an ID which matches the server name
[Tue Sep 14 09:26:05.752933 2021] [lbmethod_heartbeat:notice] [pid 1:tid 140416655523200] AH02282: No slotmem from mod_heartmonitor
[Tue Sep 14 09:26:05.755334 2021] [mpm_event:notice] [pid 1:tid 140416655523200] AH00489: Apache/2.4.39 (Fedora) OpenSSL/1.1.1 configured -- resuming normal operations
[Tue Sep 14 09:26:05.755346 2021] [core:notice] [pid 1:tid 140416655523200] AH00094: Command line: ‘httpd -D FOREGROUND’
What now? To detach from our running container, we just need to press these special keyboard shortcuts: Ctrl + P, Ctrl + Q. With this sequence, we will return to our shell prompt while the container will keep running.
To recover our detached container’s tty, we must get the list of running containers:
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
685a339917e7 registry.fedoraproject.org/f29/httpd:latest /usr/bin/run-http... 3 minutes ago Up 3 minutes ago clever_zhukovsky
We will explore this command in more detail in the next chapter, but for the moment, just take note of Container ID and then execute the following command to re-attach to the previous tty:
$ podman attach 685a339917e7
Note that we can easily start a container in detached mode by simply adding the -d option to podman run, like this:
$ podman run -d -i -t registry.fedoraproject.org/f29/httpd
In the next section, we’ll learn how to use the detach option for special purposes.
As we mentioned in the previous chapters, Podman, like any other container engine, attaches a virtual network to a container in a running state that has been isolated from the original host network. For this reason, if we want to easily reach our container or even expose it outside our host network, we need to instruct Podman to do port mapping.
The Podman -p option publishes a container’s port to the host:
-p=ip:hostPort:containerPort
Both hostPort and containerPort could be a range of ports, and if the host IP is not set or it is set to 0.0.0.0, then the port will be bound to all the IP addresses of the host.
If we take back the command we used in the previous section, it becomes the following:
$ podman run -p 8080:8080 -d -i -t registry.fedoraproject.org/f29/httpd
Now, we can take note of what Container ID has been assigned to our running container:
$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
fc9d97642801 registry.fedoraproject.org/f29/httpd:latest /usr/bin/run-http... 10 minutes ago Up 10 minutes ago 0.0.0.0:8080->8080/tcp confident_snyder
Then, we can look at the port mapping we just defined:
$ podman port fc9d97642801
8080/tcp -> 0.0.0.0:8080
Next, we can test whether this port mapping works using curl, an easy-to-use HTTP web client. Alternatively, you can point your favorite web browser to the same URL, as follows:
$ curl –s 127.0.0.1:8080 | head
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
100 <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
4
6<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
5 <head>
0 <title>Test Page for the Apache HTTP Server on Fedora</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
1 /*<![CDATA[*/
0 body {
0 background-color: #fff;
Before concluding this chapter, let’s take a look at other interesting options that could be useful for managing configuration and container behavior at runtime.
The podman run command has tons of options for letting us configure the container behavior at runtime – we are talking about around 120 options at the time of writing this book.
For example, we have an option for changing the time zone of our running containers; that is, --tz:
$ date
Tue Sep 14 17:44:59 CEST 2021
$ podman run --tz=Asia/Shanghai fedora date
Tue Sep 14 23:45:11 CST 2021
We can change the DNS of our brand-new container with the --dns option:
$ podman run --dns=1.1.1.1 fedora cat /etc/resolv.conf
search lan
nameserver 1.1.1.1
We can also add a host to the /etc/hosts file to override a local internal address:
$ podman run --add-host=my.server.local:192.168.1.10
fedora cat /etc/hosts
127.0.0.1 localhost localhost.localdomain localhost4 localhost4.localdomain4
::1 localhost localhost.localdomain localhost6 localhost6.localdomain6
192.168.1.10 my.server.local
We can even add an HTTP proxy to let our container use a proxy for HTTP requests. The default Podman behavior is to pass many environment variables from the host, some of which are http_proxy, https_proxy, ftp_proxy, and no_proxy.
On the other hand, we can also define custom environment variables that we can pass to our container thanks to the –env option:
$ podman run --env MYENV=podman fedora printenv
PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin
TERM=xterm
container=oci
DISTTAG=f34container
FGC=f34
MYENV=podman
HOME=/root
HOSTNAME=93f2541180d2
Adding and using environment variables with our containers is a best practice for passing configuration parameters to the application and influencing the service’s behavior from the operating system host. As we saw in Chapter 1, Introduction to Container Technology, containers are immutable and ephemeral by default. So, for this reason, we should leverage environment variables, as we did in the preceding example, to configure a container at runtime.
In this chapter, we started playing around with Podman’s basic commands, we learned how to run a container by looking at the most interesting options available, and we are now ready to move on to the next level: container management. To work as a system administrator in the container world, we must understand and learn about the management commands that let us inspect and check the health of our running containerized services; that’s what we saw in this chapter.
In the next chapter, which is deeply focused on container management, we are going to learn how to manage image and container life cycles with Podman. We will learn how to inspect and extract logs from running containers and will also introduce pods, how to create them, and how to run containers within them.
For more information about the topics that were covered in this chapter, you can refer to the following resources: