Working with Images and Containers
Lab: Install Necessary Container Support
- Install the necessary software to set the foundation for completing the exercises in the remainder of the chapter.
- The standard RHEL 9.1 image includes a package called
container-tools
that consists of all the required components and commands. - Use the standard
dnf
command to install the package.
1. Install the container-tools package:
[root@server10 ~]# dnf install -y container-tools
Upgraded:
aardvark-dns-2:1.10.0-3.el9_4.x86_64
buildah-2:1.33.7-3.el9_4.x86_64
netavark-2:1.10.3-1.el9.x86_64
podman-4:4.9.4-6.el9_4.x86_64
Installed:
container-tools-1-14.el9.noarch
podman-docker-4:4.9.4-6.el9_4.noarch
podman-remote-4:4.9.4-6.el9_4.x86_64
python3-podman-3:4.9.0-1.el9.noarch
python3-pyxdg-0.27-3.el9.noarch
python3-tomli-2.0.1-5.el9.noarch
skopeo-2:1.14.3-3.el9_4.x86_64
toolbox-0.0.99.5-2.el9.x86_64
udica-0.2.8-1.el9.noarch
2. Verify the package installation:
[root@server10 ~]# dnf list container-tools
Updating Subscription Management repositories.
Last metadata expiration check: 14:53:32 ago on Wed 31 Jul 2024 05:45:56 PM MST.
Installed Packages
container-tools.noarch 1-14.el9 @rhel-9-for-x86_64-appstream-rpms
podman
Command
- Finding, inspect, retrieve, and delete images
- Run, stop, list, and delete containers.
- Used for most of these operations.
Subcommands
Image Management
build
- Builds an image using instructions delineated in a Container file
images
- Lists downloaded images from local storage
inspect
- Examines an image and displays its details
login/logout
- Logs in/out to/from a container registry. A login may be required to access private and protected registries.
pull
- Downloads an image to local storage from a registry
rmi
- Removes an image from local storage
search
- Searches for an image. The following options can be included with this subcommand:
- A partial image name in the search will produce a list of all images containing the partial name.
- The
--no-trunc
option makes the command exhibit output without truncating it. - The
--limit <number>
option limits the displayed results to the specified number.
tag
- Adds a name to an image. The default is ’latest’ to classify the image as the latest version. Older images may have specific version identifiers.
Container Management
attach
- Attaches to a running container
exec
- Runs a process in a running container
generate
- Generates a systemd unit configuration file that can be used to control the operational state of a container. The
--new
option is important and is employed in later exercises.
info
- Reveals system information, including the defined registries
inspect
- Exhibits the configuration of a container
ps
- Lists running containers (includes stopped containers with the -a option)
rm
- Removes a container
run
- Launches a new container from an image. Some options such as -d (detached), -i (interactive), and -t (terminal) are important and are employed in exercises where needed.
start/stop/restart
- Starts, stops, or restarts a container
skopeo
Command
- Utilized for interacting with local and remote images and registries.
- Has numerous subcommands available; however, you will be using only the
inspect
subcommand to examine the details of an image stored in a remote registry.
/etc/containers/registries.conf
- System-wide configuration file for image registries.
- Normal Linux users may store a customized copy of this file, if required, under the ~/.config/containers directory.
- Settings stored in the per-user file will take precedence over those stored in the system-wide file.
- Useful for running rootless containers.
- Defines searchable and blocked registries.
[root@server10 ~]# grep -Ev '^#|^$' /etc/containers/registries.conf
unqualified-search-registries = ["registry.access.redhat.com", "registry.redhat.io", "docker.io"]
short-name-mode = "enforcing"
- The output shows three registries.
- The
podman
command searches these registries for container images in the given order. - Can add additional registries to the list.
Add a private registry called registry.private.myorg.io to be added with the highest priority:
[root@server10 ~]# vim /etc/containers/registries.conf
unqualified-search-registries = \["registry.private.myorg.io",
"registry.access.redhat.com", "registry.redhat.io", "docker.io"\]
If this private registry is the only one to be used, you can take the rest of the registry entries out of the list:
unqualified-search-registries = \["registry.private.myorg.io"\]
EXAM TIP: As there is no Internet access provided during Red Hat exams, you may have to access a network-based registry to download images.
Viewing Podman Configuration and Version
- The podman command references various system runtime and configuration files and runs certain Linux commands in the background to gather and display information.
- For instance, it looks for registries and storage data in the system-wide and per-user configuration files, pulls memory information from the /proc/meminfo file, executes
uname -r
to obtain the kernel version, and so on. - podman’s
info
subcommand shows all this information.
Here is a sample when this command is executed as a normal user (user1):
[[user1@server10 root]$ podman info
ERRO[0000] XDG_RUNTIME_DIR directory "/run/user/0" is not owned by the current user](<[user1@server10 ~]$ podman info
host:
arch: amd64
buildahVersion: 1.33.8
cgroupControllers:
- memory
- pids
cgroupManager: systemd
cgroupVersion: v2
conmon:
...
-
Re-run the command as root (preceded by sudo if running as user1) and compare the values for the settings “rootless” under host and “ConfigFile” and “ImageStore” under store.
-
The differences lie between where the root and rootless (normal) users store and obtain configuration data, the number of container images they have locally available, and so on.
[root@server10 ~]# podman info
host:
arch: amd64
buildahVersion: 1.33.8
cgroupControllers:
- cpuset
- cpu
- io
- memory
- hugetlb
- pids
- rdma
- misc
...
Similarly, you can run the podman command as follows to check its version:
[root@server10 ~]# podman version
Client: Podman Engine
Version: 4.9.4-rhel
API Version: 4.9.4-rhel
Go Version: go1.21.11 (Red Hat 1.21.11-1.el9_4)
Built: Mon Jul 1 03:27:14 2024
OS/Arch: linux/amd64
Image Management
Container images
- Are available from numerous private and public registries.
- They are pre-built for a variety of use cases.
- You can search through registries to find the one that suits your needs.
- You can examine their metadata before downloading them for consumption.
- Downloaded images can be removed when no longer needed to conserve local storage.
- The same pair of commands—
podman
andskopeo
—is employed for these operations.
Lab: Search, Examine, Download, and Remove an Image
- Log in to the registry.access.redhat.com registry
- Look for an image called mysql-80 in the registry, examine its details, pull it to your system, confirm the retrieval, and finally erase it from the local storage.
1. Log in to the specified Red Hat registry:
[user1@server10 ~]$ podman login registry.redhat.io
2. Confirm a successful login:
[user1@server10 ~]$ podman login registry.redhat.io --get-login
3. Find the mysql-80 image in the specified registry. Add the
--no-trunc
option to view full output.
[user1@server10 ~]$ podman search registry.redhat.io/mysql-80 --no-trunc
NAME DESCRIPTION
registry.redhat.io/rhel8/mysql-80 This container image provides a containerized packaging of the MySQL mysqld daemon and client application. The mysqld server daemon accepts connections from clients and provides access to content from MySQL databases on behalf of the clients.
...
4. Select the second image rhel9/mysql-80 for this exercise. Inspect the image without downloading it using skopeo inspect. A long output will be generated. The command uses the docker:// mechanism to access the image.
[user1@server10 ~]$ skopeo inspect docker://registry.redhat.io/rhel9/mysql-80
{
"Name": "registry.redhat.io/rhel9/mysql-80",
"Digest": "sha256:247903d2103a3c1db9401f6340ecdcd97c6244480b7a3419e6303dda650491dc",
"RepoTags": [
"1",
"1-190",
"1-190.1655192188",
"1-190.1655192188-source",
"1-190-source",
"1-197",
"1-197-source",
"1-206",
...
Output:
-
Shows older versions under RepoTags
-
Creation time for the latest version
-
Build date of the image
-
description
-
other information.
-
It is a good practice to analyze the metadata of an image prior to downloading and consuming it.
5. Download the image by specifying the fully qualified image name using podman pull:
[user1@server10 ~]$ podman pull docker://registry.redhat.io/rhel9/mysql-80
Trying to pull registry.redhat.io/rhel9/mysql-80:latest...
Getting image source signatures
Checking if image destination supports signatures
Copying blob 846c0bdf4e30 done |
Copying blob cc296d75b612 done |
Copying blob db22e630b1c7 done |
Copying config b5782120a3 done |
Writing manifest to image destination
Storing signatures
b5782120a320e5915d86555e661c357cfa56dd8320ba4c54a58caa1e1c91925f
6. List the image to confirm the retrieval using podman images:
[user1@server10 ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
registry.redhat.io/rhel9/mysql-80 latest b5782120a320 2 weeks ago 555 MB
7. Display the image’s details using podman inspect
:
[user1@server10 ~]$ podman inspect mysql-80
[
{
"Id": "b5782120a320e5915d86555e661c357cfa56dd8320ba4c54a58caa1e1c91925f",
"Digest": "sha256:247903d2103a3c1db9401f6340ecdcd97c6244480b7a3419e6303dda650491dc",
"RepoTags": [
"registry.redhat.io/rhel9/mysql-80:latest"
],
8. Remove the mysql-80 image from local storage using podman rmi:
[user1@server10 ~]$ podman rmi mysql-80
Untagged: registry.redhat.io/rhel9/mysql-80:latest
Deleted: b5782120a320e5915d86555e661c357cfa56dd8320ba4c54a58caa1e1c91925f
- Shows the ID of the image after deletion.
9. Confirm the removal using podman images:
[user1@server10 ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
Containerfile
- Can build a custom image by outlining the steps you need to be run in a file called Containerfile.
- The podman command can then be used to read those instructions and executes them to produce a new image.
- File name containerfile is widespread; but you can use any name of your liking.
Instructions that may be utilized inside a Containerfile to perform specific functions during the build process:
CMD
- Runs a command
COPY
- Copies files to the specified location
ENV
- Defines environment variables to be used during the build process
EXPOSE
- A port number that will be opened when a container is launched using this image
FROM
- Identifies the base container image to use
RUN
- Executes the specified commands
USER
- Defines a non-root user to run the commands as
WORKDIR
- Sets the working directory. This directory is automatically created if it does not already exist.
A sample container file is presented below:
[user1@server10 ~]$ vim containerfile
# Use RHEL9 base image
FROM registry.redhat.io/ubi9/ubi
# Install Apache web server software
RUN dnf -y install httpd
# Copy the website
COPY ./index.html /var/www/html/
# Expose Port 80/tcp
EXPOSE 80
# Start Apache web server
CMD ["httpd"]
- The index.html file may contain a basic statement such as “This is a custom-built Apache web server container image based on RHEL 9”.
Lab: Use Containerfile to Build Image
- Use a containerfile to build a custom image based on the latest version of the RHEL 9 universal base image (ubi) available from a Red Hat container registry.
- Confirm the image creation.
- Use the podman command for these activities.
1. Log in to the specified Red Hat registry:
[user1@server10 ~]$ podman login registry.redhat.io
Authenticating with existing credentials for registry.redhat.io
Existing credentials are valid. Already logged in to registry.redhat.io
2. Confirm a successful login:
[user1@server10 ~]$ podman login registry.redhat.io --get-login
3. Create a file called containerfile with the following code:
[user1@server10 ~]$ vim containerfile2
# Use RHEL9 base image
FROM registry.redhat.io/ubi9/ubi
# Count the number of characters
CMD echo "RHCSA exam is hands-on." | wc
# Copy a local file to /tmp
COPY ./testfile /tmp
4. Create a file called testfile with some random text in it and place it in the same directory as the containerfile.
[user1@server10 ~]$ echo "boo bee doo bee doo" >> testfile
[user1@server10 ~]$ cat testfile
boo bee doo bee doo
5. Build an image by specifying the containerfile name (-f
) and an image tag (-t
) such as ubi9-simple-image
. The period character at the end represents the current directory and this is where both containerfile and testfile are located.
[user1@server10 ~]$ podman image build -f containerfile2 -t ubi9-simple-image .
STEP 1/3: FROM registry.redhat.io/ubi9/ubi
Trying to pull registry.redhat.io/ubi9/ubi:latest...
Getting image source signatures
Checking if image destination supports signatures
Copying blob cc296d75b612 done |
Copying config 159a1e6731 done |
Writing manifest to image destination
Storing signatures
STEP 2/3: CMD echo "RHCSA exam is hands-on." | wc
--> 4c005bfd0b34
STEP 3/3: COPY ./testfile /tmp
COMMIT ubi9-simple-image
--> a2797b06a129
Successfully tagged localhost/ubi9-simple-image:latest
a2797b06a1294ed06edab2ba1c21d2bddde3eb3af1d8ed286781837f62992622
6. Confirm image creation:
[user1@server10 ~]$ podman image ls
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/ubi9-simple-image latest a2797b06a129 2 minutes ago 220 MB
registry.redhat.io/ubi9/ubi latest 159a1e67312e 2 weeks ago 220 MB
Output:
-
downloaded image
-
new custom image along with their image IDs, creation time, and size.
-
Do not remove the custom image yet as you will be using it to launch a container in the next section.
Basic Container Management
- Starting, stopping, listing, viewing information about, and deleting them.
- Depending on the use case, containers can be launched in different ways.
- They can:
- have a name assigned or be nameless
- have a terminal session opened for interaction
- execute an entry point command (the command specified at the launch time) and be auto-terminated right after
- etc.
- Running containers can be stopped and restarted, or discarded if no longer needed.
- The podman command is utilized to start containers and manage their lifecycle.
- This command is also employed to list stopped and running containers, and view their details.
Lab: Run, Interact with, and Remove a Named Container
- Run a container based on the latest version of the RHEL 8 ubi available in the Red Hat container registry.
- Assign this container a name and run a few native Linux commands in a terminal window interactively.
- Exit out of the container to mark the completion of the exercise.
1. Launch a container using ubi8 (RHEL 8). Name this container rhel8-base-os and open a terminal session (-t
) for interaction (-i
). Use the podman run
command.
[user1@server10 ~]$ podman run -ti --name rhel8-base-os ubi8
Resolved "ubi8" as an alias (/etc/containers/registries.conf.d/001-rhel-shortnames.conf)
Trying to pull registry.access.redhat.com/ubi8:latest...
Getting image source signatures
Checking if image destination supports signatures
Copying blob 8694db102e5b done |
Copying config 269749ad51 done |
Writing manifest to image destination
Storing signatures
[root@30c7cccd8490 /]#
-
Downloaded the latest version of the specified image automatically even though no FQIN was provided.
- This is because it searched through the registries listed in the /etc/containers/registries.conf file and retrieved the image from wherever it found it first (registry.access.redhat.com).
-
Opened a terminal session inside the container as the root user to interact with the containerized RHEL 8 OS.
-
The container ID is reflected as the hostname in the container’s command prompt (last line in the output). This is an auto-generated ID.
-
If you encounter any permission issues, delete the /etc/docker directory (if it exists) and try again.
2. Run a few basic commands such as pwd, ls, cat, and date inside the container for verification:
[root@30c7cccd8490 /]# pwd
/
[root@30c7cccd8490 /]# ls
bin dev home lib64 media opt root sbin sys usr
boot etc lib lost+found mnt proc run srv tmp var
[root@30c7cccd8490 /]# cat /etc/redhat-release
Red Hat Enterprise Linux release 8.10 (Ootpa)
[root@30c7cccd8490 /]# date
Thu Aug 1 21:09:13 UTC 2024
3. Close the terminal session when done:
[root@30c7cccd8490 /]# exit
exit
[user1@server10 ~]$
4. Delete the container using podman rm:
[user1@server10 ~]$ podman rm rhel8-base-os
rhel8-base-os
Confirm the removal with podman ps.
[user1@server10 ~]$ podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Lab: Run a Nameless Container and Auto-Remove it After Entry Point Command Execution
- Launch a container based on the latest version of RHEL 7 ubi available in a Red Hat container registry.
- This image provides the base operating system layer to deploy containerized applications.
- Enter a Linux command at the command line for execution inside the container as an entry point command and the container should be automatically deleted right after that.
1. Start a container using ubi7 (RHEL 7) and run ls as an entry point command. Use podman run
with the --rm
option to remove the container as soon as the entry point command has finished running.
[user1@server10 ~]$ podman run --rm ubi7 ls
Resolved "ubi7" as an alias (/etc/containers/registries.conf.d/001-rhel-shortnames.conf)
Trying to pull registry.access.redhat.com/ubi7:latest...
Getting image source signatures
Checking if image destination supports signatures
Copying blob 7f2c2c4492b6 done |
Copying config a084eb42a5 done |
Writing manifest to image destination
Storing signatures
bin
boot
dev
etc
home
...
2. Confirm the container removal with podman ps:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES