Part 2 of the EX180 series.
The Plan
We are going to have a look at the EX180 exam objectives for Podman, review commands for Dockerfile and perform 4 hands-on tasks to get familiar with an image creation process.
Pre-requisites
A Red Hat account is required in order to access Red Hat Developer portal and Red Hat Quay image repository.
Exam Objectives: Podman
These are official EX180 objectives related to Podman (we will not cover any OpenShift objectives in this article).
You should be able to implement images using Podman:
- Understand and use FROM (the concept of a base image) instruction.
- Understand and use RUN instruction.
- Understand and use ADD instruction.
- Understand and use COPY instruction.
- Understand the difference between ADD and COPY instructions.
- Understand and use WORKDIR and USER instructions.
- Understand security-related topics.
- Understand the differences and applicability of CMD vs. ENTRYPOINT instructions.
- Understand ENTRYPOINT instruction with param.
- Understand when and how to expose ports from a Docker file.
- Understand and use environment variables inside images.
- Understand ENV instruction.
- Understand container volume.
- Mount a host directory as a data volume.
- Understand security and permissions requirements related to this approach.
- Understand lifecycle and cleanup requirements of this approach.
You should be able to manage container images:
- Understand private registry security.
- Interact with many different registries.
- Understand and use image tags.
- Push and pull images from and to registries.
- Back up an image with its layers and meta data vs. backup a container state.
You should be able to run containers locally using Podman:
- Get container logs.
- Listen to container events on the container host.
- Use Podman inspect.
In order to get started, let’s see what a Dockerfile is, and perform a couple of tasks that would cover the Podman objectives.
What is a Dockerfile?
In order to implement images using Podman, you need to be able to write a Dockerfile.
A Dockerfile is a text document that contains all the commands to build an image. We will discuss several important commands here, however, we are not going to cover all available commands that one could use in a Dockerfile. For that, please take a look at this brilliant Dockerfile reference https://docs.docker.com/engine/reference/builder/.
When writing a Dockerfile, the first non-comment instruction must be a FROM instruction to specify the base image.
ADD instruction copies files or folders from a local or remote source and adds them to the container’s file system. If you are copying local files, the files must be in the working directory. If you are copying local compressed .tar files, these files will be unpacked to the destination image directory.
COPY copies files from the local source (working directory) and adds them to the container’s file system (similar to ADD). It does not however copy remote files nor unpack .tar files.
EXPOSE indicates that the container listens on the specified TCP port at runtime (unless you specify UDP), however, it does not publish the port and it does not make the port accessible from the host.
WORKDIR instruction sets the working directory for any RUN, CMD, ENTRYPOINT, COPY and ADD instructions that follow it.
USER instruction sets the user name (or UID) to use as the default user for the remainder of the current stage. The specified user is used for RUN instructions and at runtime, runs the relevant ENTRYPOINT and CMD commands. You should never run as root but use a dedicated user for your containers instead.
Important: both instructions ADD and COPY copy source files with root as the owner, even if the USER instruction is specified. What that means is that all new files and directories are created with a UID and GID of 0 by default.
ENTRYPOINT instruction allows you to configure a container that will run as an executable. ENTRYPOINT can define both the command to be executed and the parameters.
CMD instruction provides defaults for an executing container.
There should be at most one ENTRYPOINT and one CMD instruction.
Now that we are somewhat familiar with Dockerfile commands, let us containerise a simple Java application.
Podman Task 1: Containerise a JBoss Application
Write a Dockerfile to containerise a JBoss EAP 7.4 application to meet all of the following requirements (listed in no particular order):
- Use the latest version of Red Hat Universal Base Image 8 ubi8 from the registry registry.access.redhat.com as a base.
- Install the java-1.8.0-openjdk-devel package.
- Create a system group for jboss with a GID of 1100.
- Create a system user for jboss with a UID 1100.
- Set the jboss user’s home directory to
/opt/jboss
. - Set the working directory to jboss user’s home directory.
- Recursively change the ownership of the jboss user’s home directory to jboss:jboss.
- Expose port 8080.
- Make the container run as the jboss user.
- Unpack the jboss-eap-7.4.0.zip file to the
/opt/jboss
directory. - Set the environment variable JBOSS_HOME to
/opt/jboss/jboss-eap-7.4
. - Start container with the following executable:
/opt/jboss/jboss-eap-7.4/bin/standalone.sh -b 0.0.0.0 -c standalone-full-ha.xml
.
Before you start, log in to Red Hat Developer portal and download the jboss-eap-7.4.0.zip file to your working directory. See the weblink below (which requires a Red Hat account):
https://developers.redhat.com/content-gateway/file/jboss-eap-7.4.0.zip
Solution to Podman Task 1
This is how the Dockerfile should look like. Comments are provided for references.
# Use base image FROM registry.access.redhat.com/ubi8:latest # Install the java-1.8.0-openjdk-devel package # We also need the unzip package to unpack the JBoss .zip archive RUN yum install -y java-1.8.0-openjdk-devel unzip && yum clean all # Create a system user and group for jboss, they both have a UID and GID of 1100 # Set the jboss user's home directory to /opt/jboss RUN groupadd -r -g 1100 jboss && useradd -u 1100 -r -m -g jboss -d /opt/jboss -s /sbin/nologin jboss # Set the environment variable JBOSS_HOME to /opt/jboss/jboss-eap-7.4.0 ENV JBOSS_HOME="/opt/jboss/jboss-eap-7.4" # Set the working directory to jboss' user home directory WORKDIR /opt/jboss # Unpack the jboss-eap-7.4.0.zip file to the /opt/jboss directory ADD ./jboss-eap-7.4.0.zip /opt/jboss RUN unzip /opt/jboss/jboss-eap-7.4.0.zip # Recursively change the ownership of the jboss user's home directory to jbosis:jboss # Make sure to RUN the chown after the ADD command and and before it, as ADD will # create new files and directories with a UID and GID of 0 by default RUN chown -R jboss:jboss /opt/jboss # Make the container run as the jboss user USER jboss # Expose JBoss port EXPOSE 8080 # Start JBoss, use the exec form which is the preferred form ENTRYPOINT ["/opt/jboss/jboss-eap-7.4/bin/standalone.sh", "-b", "0.0.0.0", "-c", "standalone-full-ha.xml"]
The task is complete.
Podman Task 2: Build a JBoss Container Image and Run a Container
Use podman
command to build a container image using the Dockerfile from task 1 and create a new container from the image to meet all of the following requirements:
- Tag the container image as jboss-eap:7.4.0.
- Create a new container in detached mode.
- Name the container jboss-from-dockerfile.
- Port forward from host port 38080 to container port 8080.
- Inspect the running container to determine its arguments (Args). You can use the following JSON format:
'{{.Args}}'
. - Retrieve the last 15 lines of the running container logs.
Solution to Podman Task 2
Make sure that the file jboss-eap-7.4.0.zip has been downloaded and is in the working directory:
$ ls -1 Dockerfile jboss-eap-7.4.0.zip
Build the image:
$ podman build -t jboss-eap:7.4.0 .
View all local images:
$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/jboss-eap 7.4.0 04522ac82423 2 minutes ago 1.45 GB registry.access.redhat.com/ubi8 latest 16fb1f57c5af 2 weeks ago 214 MB
Run a new container using the image:
$ podman run -d --name jboss-from-dockerfile -p 38080:8080 jboss-eap:7.4.0
Verify that the container is running:
$ podman ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES a3e1f164097e localhost/jboss-eap:7.4.0 37 seconds ago Up 37 seconds ago 0.0.0.0:38080->8080/tcp jboss-from-dockerfile
Inspect the running container:
$ podman inspect --format '{{.Args}}' jboss-from-dockerfile [-b 0.0.0.0 -c standalone-full-ha.xml]
Retrieve the last 15 lines of the running container logs:
$ podman logs --tail=5 jboss-from-dockerfile
The task is complete.
Podman Task 3: Save Container Image
Perform all of the following tasks:
- Save the jboss-eap:7.4.0 container image to the jboss-eap-7.4.0-backup.tar file.
- Update the running jboss-from-dockerfile container and replace the content of the
/opt/jboss/jboss-eap-7.4/welcome-content/index.html
file with a single word JBOSS. - Stop the running jboss-from-dockerfile container and commit your changes to create a new container image.
- The new container image should be called jboss-eap and have a tag of 7.4.0-dev.
- Author name of the new container image should be set to “Home Lab”.
Solution to Podman Task 3
Save the image to a file:
$ podman save -o jboss-eap-7.4.0-backup.tar jboss-eap:7.4.0 Copying blob 33204bfe17ee done Copying blob ca59617ea9ea done Copying blob cf12abd501e1 done Copying blob 8b490fc98797 done Copying blob f3f0bffa6c8c done Copying blob 8c9ee159685e done Copying config 04522ac824 done Writing manifest to image destination Storing signatures
Verify that the backup file has been created:
$ ls -1 Dockerfile jboss-eap-7.4.0-backup.tar jboss-eap-7.4.0.zip
Connect to the running jboss-from-dockerfile container and update the index file as requested:
$ podman exec -it jboss-from-dockerfile /bin/bash [jboss@a3e1f164097e ~]$ echo JBOSS > /opt/jboss/jboss-eap-7.4/welcome-content/index.html [jboss@a3e1f164097e ~]$ cat /opt/jboss/jboss-eap-7.4/welcome-content/index.html JBOSS [jboss@a3e1f164097e ~]$ exit
Optionally, verify with curl
:
$ curl http://127.0.0.1:38080 JBOSS
Stop the running jboss-from-dockerfile container image:
$ podman stop jboss-from-dockerfile
Commit the changes to a new jboss-eap:7.4.0-dev container image:
$ podman commit --author "Home Lab" jboss-from-dockerfile jboss-eap:7.4.0-dev Getting image source signatures Copying blob 33204bfe17ee skipped: already exists Copying blob ca59617ea9ea skipped: already exists Copying blob cf12abd501e1 skipped: already exists Copying blob 8b490fc98797 skipped: already exists Copying blob f3f0bffa6c8c skipped: already exists Copying blob 8c9ee159685e skipped: already exists Copying blob 0a00603d8194 done Copying config ec66f8b31b done Writing manifest to image destination Storing signatures ec66f8b31b6854285f7e5718e80df73d935da59d43afa7fa7eeda9adcbf5a1dc
Verify to make sure that the new image has been created:
$ podman images REPOSITORY TAG IMAGE ID CREATED SIZE localhost/jboss-eap 7.4.0-dev ec66f8b31b68 11 seconds ago 1.47 GB localhost/jboss-eap 7.4.0 04522ac82423 32 minutes ago 1.45 GB registry.access.redhat.com/ubi8 latest 16fb1f57c5af 2 weeks ago 214 MB
The task is complete.
Podman Task 4: Push and Pull Images from Registries
For this task you are going to need to have a free account on Red Hat’s quay.io repository so that you can push a container image to it. If you don’t have one, feel free to use any other container image registry that you may have an account with (e.g. Docker Hub, AWS ECR etc).
Perform all of the following tasks:
- Use
podman
command to search and locate the docker.io/httpd official container image. - Pull the latest version of the httpd container image from docker.io Docker Hub image repository.
- Use
podman
command to login to a Red Hat’s quay.io image repository. - Tag the httpd image as quay.io/$USERNAME/httpd:1.0-test, where $USERNAME is your quay.io username.
- Push the tagged container image to Red Hat’s quay.io repository.
Solution to Podman Task 4
Search for the official httpd image:
$ podman search --filter=is-official docker.io/httpd NAME DESCRIPTION docker.io/library/httpd The Apache HTTP Server Project
Pull the latest version of the httpd image from Docker Hub:
$ podman pull docker.io/httpd:latest Trying to pull docker.io/library/httpd:latest... Getting image source signatures Copying blob b1c114085b25 done Copying blob 4691bd33efec done Copying blob 9df1012343c7 done Copying blob ff7b0b8c417a done Copying blob a603fa5e3b41 done Copying config 8653efc8c7 done Writing manifest to image destination Storing signatures 8653efc8c72daee8c359a37a1dded6270ecd1aede2066cbecd5be7f21c916770
Login to quay.io container image repository:
$ podman login quay.io Username: Password: Login Succeeded!
Tag the httpd:latest image:
$ podman tag httpd:latest quay.io/lisenet/httpd:1.0-test
Push the image to quay.io image repository:
$ podman push quay.io/lisenet/httpd:1.0-test Getting image source signatures Copying blob 7603afd8f9aa done Copying blob ec4a38999118 done Copying blob a4a57da7ddfc done Copying blob a0b242781abd done Copying blob 29657939e55a done Copying config 8653efc8c7 done Writing manifest to image destination Storing signatures
The task is complete.
What’s Next?
We will look into deploying a multi-container application with Podman.
Thx a lot for your materials for this exam! Just passed my ex188 with 282 score result! Thx!