100% found this document useful (1 vote)
2K views

Ex 188

This document provides an introduction to containers and containerization using Podman and CRI-O. It discusses container architecture, including namespaces, cgroups, and SELinux. It also covers running containers with Podman, understanding rootless containers, interacting with containers on the host OS, and providing variables when starting containers. The document includes demonstrations of running containers with Podman and interacting with them.

Uploaded by

Albert
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
100% found this document useful (1 vote)
2K views

Ex 188

This document provides an introduction to containers and containerization using Podman and CRI-O. It discusses container architecture, including namespaces, cgroups, and SELinux. It also covers running containers with Podman, understanding rootless containers, interacting with containers on the host OS, and providing variables when starting containers. The document includes demonstrations of running containers with Podman and interacting with them.

Uploaded by

Albert
Copyright
© © All Rights Reserved
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 105

Click to edit Master title style

EX188 Crash Course


Poll Question 1
Click to edit Master title style
How would you rate your own experience regaring Podman or Docker?
• 0
• 1
• 2
• 3
• 4
• 5
Poll Question 2
Click to edit Master title style
Which geographical area are you from?
• Africa
• Asia
• Australia / Pacific
• India
• Poland
• Europe
• North/central America
• South America
Click to edit Master title style

Lesson 1: Introduction to
Containers

1.1 Understanding Container


Architecture
What is a Container
Click to edit Master title style
• Containers are running instances of container images
• A container image is a standardized archive that contains all dependencies
to run an application
• Isolation is added by Linux kernel namespaces, and ensures that nothing in
a container can interfere with anything in another container
• To provide restricted access to resources, Cgroups are used
Click to edit Master title style

Lesson 1: Introduction to
Containers

1.2 Understanding Container


Architecture
Understanding Container Architecture
Click to edit Master title style
• The container engine runs the container as a process on top of the Linux
kernel
• The lowest layer is support by Linux kernel features
• Namespaces: isolation that is implemented for different parts of the kernel
• Cgroups: restrictions to resource usage
• SELinux: mandatory access control that isolates container processes
• The foundation of any running container is the container image
• Images are provided by a public or private image repository
• podman is the default tool in RHEL to run container images
Understanding Container Standardization
Click to edit Master title style
• The container revolution was initiated by Docker
• Docker has set some standards
• To guarantee these are used as standards, Docker founded the Open
Container Initiatives (OCI)
• All major players on the market of containers participate in OCI
• OCI defines standard formats and components
Click to edit Master title style

Lesson 1: Introduction to
Containers and Kubernetes

1.3 Understanding the Container


Engine
Understanding Container Engine
Click to edit Master title style
• The container engine takes a container image and turns it into a container
• It typically consists of a runtime, a CLI tool and sometimes a daemon
• Different container engines are provided
• Podman
• Systemd
• Docker
• LXC
Understanding Container Runtimes
Click to edit Master title style
• The container runtime is a specific part of the container engine, and two of
them are commonly used:
• CRI-O: Red Hat
• containerd: originates from Docker
• The container runtime is taking care of specific tasks
• Provide the mount point
• Communicate with the kernel
• Set up cgroups and more
Understanding runC
Click to edit Master title style
• runC is a lightweight universal container runtime
• Crun is an alternative to runC, written in C
• It is the default runtime defined by the Open Containers Initiative
• It is the specific part that focusses on creating containers
• As such, it's included in CRI-O as well as containerd
• Where CRI-O and containerd are adding features, like container lifecycle
management and container image management
Click to edit Master title style

Lesson 1: Introduction to
Containers and Kubernetes

1.4 Podman versus Docker


Podman versus Docker
Click to edit Master title style
• Docker started the container revolution, and has established important
standards for running containers
• In Podman, a few items have been improved
• Rootless containers are the default
• No daemon, but a fork/exec execution model
• Tight integration with systemd
Click to edit Master title style

Lesson 2: Running
Containers

2.1 Running Containers on


Podman/CRI-o
Understanding how to Run Containers
Click to edit Master title style
• Container images are configured with an entrypoint, which is the default
command to be executed
• If the container starts a service, the entrypoint is executed and the
container will continue to run in the foreground
• If the entrypoint is just a command, it is executed after which the container
stops
• System images are used as a foundation container and start an entrypoint
and next quit
• Application images start a service as an entrypoint and after that just quits
Demo: Running a container
Click to edit Master title style
• sudo podman search ubi
• sudo podman pull ubi8/ubi
• podman images #doesn't show it
• podman run ubi8
• podman ps
• podman ps -a
• podman run ubi8/ubi echo hello world
• podman run nginx; Ctrl-C
• podman run -d nginx
• podman run -it ubi8/ubi /bin/bash
Click to edit Master title style

Lesson 2: Running
Containers

2.2 Understanding Rootless


Containers
Understanding Rootless Containers
Click to edit Master title style
• A rootless container runs as an ordinary user
• Any user can start rootless containers
• After starting the container as a non-root user, within the container any
UID (including root) can be used as it is a namespaced UID that exists in the
container only
• This container internal user is mapped to a user on the host operating
system for file access
• A root container runs with root privileges and for that reason is dangerous
• Rootless containers do not get an IP address
• Rootless containers cannot bind to a privileged port
• Rootless containers have limited access to the filesystem
Demo: Running root[less] containers
Click to edit Master title style
• podman run -d nginx
• sudo ip a
• podman inspect -l -f "{{.NetworkSettings.IPAddress}}"
• sudo podman run -d nginx
• sudo ip a
• sudo podman inspect -l -f "{{.NetworkSettings.IPAddress}}"
• Note that the -l flag refers to the last container that was started and
takes away the need to specify a name
Click to edit Master title style

Lesson 2: Running
Containers

2.3 Understanding Containers and


the Host OS
Containers on the Host OS
Click to edit Master title style
• From the host OS perspective, a container is just a process
• A well restricted process though, as namespaces, cgroups and SELinux limit
what the container can do
• Use ps faux | less and look for processes that are started by conmon
• Linux kernel limitations make that the processes are restricted regarding
resource usage as well as access to other resources
Demo: Running a Busybox Image
Click to edit Master title style
• podman run -it busybox
• ls /etc
• uname -r
Click to edit Master title style

Lesson 2: Running
Containers

2.4 Providing Variables at Container


Start
Using Variables
Click to edit Master title style
• Container images normally don't contain site-specific information
• To provide site specific information, environment variables can be provided
• The most straightforward way to provide these variables is by starting the
container with the -e key=value option
• Some images refuse to start if the right variables are not provided
• To analyze if a container needs additional information while starting, use
the podman logs containername command
Demo: Running mariadb
Click to edit Master title style
• sudo podman run mariadb # will fail
• sudo podman ps -a
• sudo podman logs <containername>
• sudo podman run -d -e MYSQL_ROOT_PASSWORD=password
mariadb
Click to edit Master title style

Lesson 2: Running
Containers

Lesson 2 Lab: Running Containers


Lesson 2 Lab: Running Containers
Click to edit Master title style
• Use the appropriate command to find the ubi8 image
• Download the image without running it
• Inspect the image to find out what is used as the default entrypoint
• Open the image in an interactive shell, and find which operating system
and which kernel it uses
Click to edit Master title style

Lesson 3: Managing
Container Images

3.1 Using Registries


Using Registries
Click to edit Master title style
• Images are distributed using Registries
• An image registry is like a Git repository and provides access to images to
the intended audience
• Common public registries are available
• Quay.io: a Red Hat sponsored public registry where developers can work
directly on their images, accessible at quay.io
• Docker Hub: a public container registry, accessible at hub.docker.com
• Google Container Registry: a common registry, used in Kubernetes, accessible at
cloud.google.com/container-registry
• Private registries can be used as well
• See https://www.redhat.com/sysadmin/simple-container-registry
Red Hat Registries
Click to edit Master title style
• Red Hat provides the following registries:
• registry.access.redhat.com: requires no authentication
• registry.redhat.io: requires authentication
• catalog.redhat.com provides a web interface to these registries
Accessing Images from Registries
Click to edit Master title style
• In podman it is recommended to use fully qualified container names like
registry.access.redhat.com/ubi9/nginx-122
• Alternatively, unqualified search locations can be specified in registries.conf
• If an image name is ambiguous, you will be prompted for the exact
qualified name
Blocking Registry Access
Click to edit Master title style
• In the registries.conf, access to a registry can be blocked:
[[registry]]
location="docker.io"
blocked=true
Registry Authentication
Click to edit Master title style
• Registries may require authentication
• Use podman login [-u username] [-p password] [registry.redhat.io] to
login
• Credentials are stored in base64 encoded way in
${XDG_RUNTIME_DIR}/containers/auth.json
• After authentication, images can be accessed using podman pull or
podman run: podman pull registry.redhat.io/ubi9/nginx-122
Docker Registry Rate Limitation
Click to edit Master title style
• Docker has implemented an image pull limitation on their registry, limiting
anonymous users to no more than 100 pulls per six hours
• This limit is reached quite fast
• For multi-layer images, each layer counts as a separate pull
• Even if images are already present locally, while running a new container based
on that image the registry is contacted which counts as a pull
Dealing with Docker Rate Limitation
Click to edit Master title style
• Authenticated users have access to 200 pulls per 6 hours
• Professional users have access to virtually unlimited pulls
• A professional developer account is about $ 70 yearly
• Use podman login -u <docker-user-name> docker.io
• As an alternative, consider using alternative image locations, such as
quay.io images
• podman run bitnami/nginx will run the image from docker.io
• podman run quay.io/bitnami/nginx will run the image from quay.io
Click to edit Master title style

Lesson 3: Managing
Container Images

Using skopeo
Using skopeo
Click to edit Master title style
• In addition to the podman command, skopeo provides the following
functionality
• inspect container images without pulling them
• copy images between registries
• convert image format
• sign images with OpenPGP keys
• Inspect images using skopeo inspect
docker://registry.access.redhat.com/ubi9/nginx-122
• After logging in, copy images using skopeo copy
docker://registry.access.redhat.com/ubi9/nginx-122
docker://docker.io/myuser/nginx-122
Click to edit Master title style

Lesson 3: Managing
Container Images

3.2 Managing Images


Managing Images
Click to edit Master title style
• After using podman pull or podman run images are stored on the local
machine
• Use podman images to see which images these are
• Look up the image ID, and use sudo find / -name "<ID>*" to find the exact
image location in the filesystem
• Use podman rmi to remove images
• podman rmi -a will remove all images
• podmain image prune removes all dangling images. These are images that
have no tag and are unreferenced by other images.
Saving and Loading Images
Click to edit Master title style
• Use podman save to save an image to a .tar file: podman save
quay.io/bitnami/nginx:latest -o mysql.tar
• To load a container image from a tar file, use podman load -i mysql.tar
• This approach can be used to exchange images with other users
Click to edit Master title style

Lesson 3: Managing
Container Images

3.3 Working with Tags


Understanding Tags
Click to edit Master title style
• Tags are used to further identify images
• They are used to support multiple releases of the same image
• By default, the tag :latest is used
• Alternatively, a specific version may be specified: sudo podman pull
rhscl/mysql-57-rhel7:5.7
• To get information about available versions before pulling, use skopeo
inspect docker://...
Creating Tags
Click to edit Master title style
• Tags are used to identify version, but can also be used to identify purpose
of the image
• Use podman tag to apply a tag to an image: podman tag nginx mynginx:db
• See the result with podman images
• If an image has multiple tags, podman rmi imagename:tag will remove the
tag only and not the entire image
Click to edit Master title style

Lesson 3: Managing
Container Images

Lesson 3 Lab
Lesson 3 Lab: Managing Images
Click to edit Master title style
• Ensure you are logged in to all registries required to use podman
• Search for information about the ubi8 image
• Download the image you've found, and make a backup copy of it
• Investigate image contents
• Remove the image from the local image list
• Restore the backup you previously created
Click to edit Master title style

Lesson 4: Managing
Containers

4.1 Getting Container Status


Information
Getting Container Status Information
Click to edit Master title style
• podman run myimage starts a container with its default entrypoint
• podman run -it myimage sh runs a non-default entrypoint
• exit closes the current application and may shut down the container
• ctrl-p, ctrl-q detaches from the current application
• podman run -d myimage runs an image in detached mode
• podman ps shows information about currently running containers
• podman ps -a shows information about all containers that have been
started
Getting More Information
Click to edit Master title style
• podman inspect mycontainer shows current properties of running
containers
• podman image inspect myimage shows properties about images on the
local system
• podman logs connects to the entrypoint application STDOUT
Common Container Management Tasks
Click to edit Master title style
• podman stop stops a container gracefully
• Use podman stop -a to stop all containers
• podman restart will start a previously stopped container using container
data that is already locally available, or restart the container if it is currently
running
• podman start will start a container that is currently in stopped state
• podman kill is used to send UNIX signals to manipulate container state
• By default, SIGKILL is sent
• Use -s to specify any other signal number
• podman rm deletes a container, which also deletes its current state from
the system
Click to edit Master title style

Lesson 4: Managing
Containers

4.2 Executing Commands within


Containers
Executing Commands in Containers
Click to edit Master title style
• Each container comes with an entrypoint command
• On application containers, this is a complete application
• On system containers, this is typically a shell
• After running the entrypoint command, the container is done
• Use podman exec mycontainer mycommand to run any additional
command in an already running container
• Use podman run mycontainer mycommand to replace the entrypoint
command with the command that is provided
Click to edit Master title style

Lesson 4: Managing
Containers

4.3 Attaching Storage to Containers


Understanding Container Storage
Click to edit Master title style
• When a container is started, an ephemeral read/write storage layer is
added to the host that runs the container
• This storage guarantees that data is kept after a restart, but this data is not
guaranteed
• After a stop, the data is still available
• After using podman rm the read-writable layer is removed
• To ensure data will always be available, persistent storage must be
provided
• Stand-alone containers have limited options for working with persistent
storage, more advanced options are available when using OpenShift
Providing Persistent Storage
Click to edit Master title style
• To ensure that data is persistent, persistent storage must be configured
• To do so, a host directory is mounted inside the container
• As this ensures that data is stored externally, it guarantees the availability
of data after the container lifetime
• To secure access to the host directory, the container_file_t SELinux context
is applied
Managing SELinux Context on the Host
Click to edit Master title style
• To start with, the host directory must be writable by the container main
process
• If containers are started with a specific UID, the numeric UID can be set
• Use podman inspect image and look for User to find which user this is
• Next, use sudo chown -R <id>:<id> /hostdir
• Then set SELinux:
• sudo semanage fcontext -a -t container_file_t "/hostdir(/.*)?"
• sudo restorecon -Rv /hostdir
• And mount the storage using podman run -v /hostdir:/dir-in-container
myimage
Demo: Starting MySQL with Persistent Storage
Click to edit Master title style
• podman search mysql
• sudo podman pull registry.access.redhat.com/rhscl/mysql-57-
rhel7
• sudo podman inspect registry.access.redhat.com/rhscl/mysql-57-
rhel7
• sudo mkdir /srv/dbfiles
• sudo chown -R 27:27 /srv/dbfiles
• sudo semanage fcontext -a -t container_file_t "/srv/dbfiles(/.*)?"
• sudo restorecon -Rv /srv/dbfiles
• sudo podman run -d -v /srv/dbfiles:/var/lib/mysql -e
MYSQL_ROOT_PASSWORD=password
registry.access.redhat.com/rhscl/mysql-57-rhel7
• ls -l /srv/dbfiles should now show contents
Configuring SELinux Automatically
Click to edit Master title style
• To ensure correct SELinux labels, they can be set using semanage fcontext
and restorecon as describe before
• This works in all cases and for that reason is the preferred way
• If the user that runs the container is owner of the directory that is going to
be bind-mounted, the :Z option can be used to automatically set the
appropriate SELinux context
• This is the recommended approach while using rootless containers
• podman run -d -v /srv/dbfiles:/var/lib/mysql:Z -e
MYSQL_ROOT_PASSWORD=password
registry.access.redhat.com/rhscl/mysql-57-rhel7
Demo: Starting MySQL with Persistent Storage
Click to edit Master title style
• mkdir /home/student/dbfiles
• podman run -d -v /home/student/dbfiles:/var/lib/mysql:Z -e
MYSQL_ROOT_PASSWORD=password
registry.access.redhat.com/rhscl/mysql-57-rhel7
• ls -lZ /home/student/dbfiles
• On RHEL 8.3 this fails: for an explanation see end of lesson 4.5
• On RHEL 8.4 this works as described
Click to edit Master title style

Lesson 4: Managing
Containers

4.4 Exposing Container Workloads


Understanding Podman Networking
Click to edit Master title style
• Rootless containers don't have an IP address and are accessible through
port forwarding on the container host only
• Root containers connect to a bridge, using a container specific IP address
• Containers behind the bridge are not directly accessible
Exposing Container Applications
Click to edit Master title style
• To make container applications accessible, port forwarding is used
• sudo podman run -d -p 8088:80 nginx runs an Nginx container on port 80,
where port 8088 can be addressed on the host to access its workload
• In port forwarding, a source IP address can be specified to allow access
only if traffic comes from a specific IP address: sudo podman run -d -p
127.0.0.1:8088:80 nginx
• Use sudo podman port to find which port mapping applies to a specific
container
Click to edit Master title style

Lesson 4: Managing
Containers

4.9 Managing Rootless Containers


part 2
Understanding Rootless Containers
Click to edit Master title style
• Containers in podman can be started by the root user or by an unprivileged
user
• In both cases the container is started with its own user namespace, having
its own /etc/passwd and /etc/shadow files
• Many containers run processes inside the container as root, but that is not
recommended
• To run containers as a different UID inside the container, use the -u
username option while starting the container, or use container images that
specify which user to use
• When starting a root container processes with a different UID, on the host
the same UID will be used as the owner of the processes
Understanding Rootless Containers
Click to edit Master title style
• When using a rootless container, the container is started by a non-
privileged user, while processes within the container may still have root
privileges
• These processes however don't have any host access privileges as it is a
rootless container
• This also limits common functionality on the host, such as the option to
bind to a privileged port
• An alternative solution is to use a rootless container with a non-root user in
the container, which is the most secure option
Options to run Containers
Click to edit Master title style
• root container, running a root process in the container
• root container, running a non-root process in the container
• rootless container, running a root process in the container
• rootless container, running a non-root process in the container
Understanding UID Maps
Click to edit Master title style
• While starting a rootless container that runs a non-root process, a mapping
must be made between the user inside the container and a user on the
host
• By default, Podman uses the same UID on both
• Alternatively, a UID map file can be used and host users are generated
dynamically
Demo: root container running a root process
Click to edit Master title style
• sudo podman run -it quay.io/quay/busybox sh
• whoami
• sleep 1000 &
• ps aux | grep sleep
• Ctrl-p, Ctrl-q
• ps aux | grep sleep #will run as root on the host
Demo: rootless container running a root process
Click to edit Master title style
• podman run -it quay.io/quay/busybox sh
• whoami
• sleep 2000 &
• ps aux | grep sleep
• Ctrl-p, Ctrl-q
• ps aux | grep sleep #will run as user on the host
Demo: root container running a non-root process
Click to edit Master title style
• sudo podman run -it -u 27 quay.io/quay/busybox sh
• whoami
• sleep 3000 &
• ps aux | grep sleep
• Ctrl-p, Ctrl-q
• ps aux | grep sleep #will run as user 27 the host. Notice that if this UID
exists on the host, the container process will run as that UID on the host
Demo: rootless container running a non-root process
Click to edit Master title style
• podman run -it -u 27 quay.io/quay/busybox bash
• whoami
• sleep 3000 &
• ps aux | grep sleep
• Ctrl-p, Ctrl-q
• ps aux | grep sleep #will run as a mapped user on the host
Understanding UID mapping
Click to edit Master title style
• The /etc/subuid on the host OS contains 64K user ID's that can be used by
a user inside a container to map to a temporary user that will be created
on the host OS
• This mapping is automatically generated for each user that is created on
the host OS, but can also be manually specified
• The /proc/PID/uid_map file shows container mappings used inside the
container. The contents depends on how the container was started
0 1000 1
1 100000 65536
• 1st field shows the start of the range of UIDs in the process namespace
• 2nd field shows the start of the UID range on the host from the container view
• 3rd field shows the length of the range UIDs
Demo: showing UID mappings
Click to edit Master title style
• From a rootless container that runs a root shell
• adduser -u 2345 bob
• su - bob
• sleep 5000 &
• On the host: ps aux | grep 5000 will show UID 102344
• And use: podman top -l user huser args
Understanding File Ownership
Click to edit Master title style
• If in the former scenario, user 27 in the container would create a file, the
file will be owned by user 100026 on the host OS
• To see the file owner inside the container listed properly, use podman
unshare ls -al /volume/mount/point, which will see the UID that was used
inside the container
• This is useful to analyze file access issues while running rootless containers
Looking at an example
Click to edit Master title style
• mkdir /home/student/dbfiles
• podman run -d -v /home/student/dbfiles:/var/lib/mysql:Z -e
MYSQL_ROOT_PASSWORD=password
registry.access.redhat.com/rhscl/mysql-80-rhel7
• ls -lZ /home/student/dbfiles
Understanding Namespaces
Click to edit Master title style
• Namespaces provide isolation to different aspects of networking: files,
processes, users and more
• All non-root containers are started in the same user namespace
• User ID's exist inside that namespace only, and for access outside of the
namespace UID mappings as discussed before need to be made
• In the demo on the previous slide, the non-root container starts a mysql
process as UID 27 inside the container namespace
• The /home/student/dbfiles directory is not a part of the container
namespace, and from the container namespace, its ownership is set to
root:root
Using Podman Unshare to troubleshoot
Click to edit Master title style
• Use podman unshare to verify what stuff looks like from the podman ns:
• podman unshare ls -ld /home/student/dbfiles
• Use podman unshare to set correct ownership, and notice that from the
host OS you'll see the mapped user account
• podman unshare chown 27:27 -R dbfiles
• podman unshare ls -ld /home/student/dbfiles
• ls -ld /home/student/files
• podman top -l user huser
Click to edit Master title style

Lesson 4: Managing
Containers

Lesson 4 Lab: Managing Containers


Lesson 4 Lab: Managing Containers
Click to edit Master title style
• Run a MySQL container using persistent storage and port forwarding in
such a way that traffic sent to host port 13306 is forwarded to container
port 3306. Make sure that all required parameters are used to start a
database with the name books, which is accessible by the user linda
Click to edit Master title style

Lesson 5: Creating Custom


Images

5.1 Options for working with Custom


Container Images
Understanding Options to work with Images
Click to edit Master title style
• Commit changes to an image: not good from a perspective of
maintainability, build automation and repeatability
• Dockerfile: standard for building custom images that is easy to share
Where to Get Images
Click to edit Master title style
• Red Hat Software Collections Library (RHSCL) provides access to the latest
versions of tools that do not fit the default RHEL release schedule, and
contains Dockerfiles for many products
• Community versions of these Dockerfiles are on https://github.com/sclorg?q=-
container
• Red Hat Container Catalog (RHCC) contains Red Hat containers that have
gone through a quality-ensurance process
• Quay.io provides access to community contributed container images
• Docker Hub is a broad platform of container images that have mostly not
been tested or verified
Click to edit Master title style

Lesson 5: Creating Custom


Images

5.3 Building Custom Images with


Containerfile
About Terminology
Click to edit Master title style
• In Red Hat environments, it's common to talk about Containerfile instead
of Dockerfile
• Whenever Dockerfile is mentioned, feel free to use Containerfile as the
alternative
• Notice that podman supports Dockerfile as well as Containerfile, docker
build only works on Dockerfile
Understanding Parent/Child Images
Click to edit Master title style
• When working with Dockerfile, using Parent/Child Images is common
• A child image is an image that is created from a parent image and
incorporates everything in the parent images
• Starting from a parent image makes it easier to create a reliable image
• Alternatively, Dockerfile images can be created by modifying existing
images
Understanding the Process
Click to edit Master title style
• First, you'll create a working directory: each project should have its own
project directory
• Next, you'll write the Dockerfile: the Dockerfile contains instructions to
build the image
• Then, build the image with podman build -t myimagename .
• Notice that "." refers to the current directory, which is the directory that
contains the Dockerfile
• Finally, use podman push [registry] to upload the image to a specific
registry
Writing a Containerfile
Click to edit Master title style
• Each Containerfile starts with FROM, identifying the base image to use
• All instructions in the Containerfile are executed in that base image
• Instructions are executed in order as specified
• Each Containerfile instruction runs in an independent container, using an
intermediate image built from a previous command and resulting in an
additional layer
• The result is an image that consists of multiple layers
• To keep Containerfiles as small as possible, avoid creating too many layers
Containerfile example
Click to edit Master title style
FROM centos:7
MAINTAINER Sander <[email protected]>

# Add repo file


ADD ./sander.repo /etc/yum.repos.d/

# Install cool software


RUN yum --assumeyes update && \
yum --assumeyes install \
nmap iproute && \
yum clean all

CMD ["/usr/bin/nmap", "-sn", "172.17.0.0/24"]


Containerfile Instructions
Click to edit Master title style
• FROM identifies the base image to use
• LABEL is a key-value pair that is used for identification
• MAINTAINER is the name of the person that maintains the image
• RUN executes commands on the FROM image
• EXPOSE has metadata only information on where the image should run
• ENV defines environment variables to be used within the container
• ADD copies files from the project directory to the image
• COPY copies files from the local project directory, using ADD is preferred
• USER specifies username for RUN, CMD and ENTRYPOINT instructions
• ENTRYPOINT has the default command
• CMD contains default arguments for the ENTRYPOINT instruction
Understanding ENTRYPOINT and CMD
Click to edit Master title style
• ENTRYPOINT or CMD must be used to specify the command to be executed
by the container, in either shell form or exec form
• If ENTRYPOINT is used to specify the command, CMD must be used to
specify its arguments
• Arguments specified with CMD can be overwritten while running the
container, arguments specified with ENTRYPOINT cannot be provided as a
command line argument while running the container
Using ADD or COPY
Click to edit Master title style
• ADD and COPY are doing the same
• COPY is simpler and has less features
• ADD has specific features that make it more flexible
• ADD can directly extract the contents of a tar file into the container
• ADD can fetch files from a URL, but this is deprecated, rather use RUN wget to
fetch the file, and delete them afterwards when the file is no longer needed
Understanding Formats
Click to edit Master title style
• Options like ADD, COPY, ENTRYPOINT, CMD are used in shell form and in
exec form
• Shell form is a list of items
• ADD /my/file /mydir
• ENTRYPOINT /usr/bin/nmap -sn 172.17.0.0/24
• Exec form is a Json array of items
• ADD ["/my/file", "/mydir"]
• ENTRYPOINT ["/usr/bin/nmap", "-sn", "172.17.0.0/24"]
• Using Exec form is preferred, as shell form wraps command in a /bin/sh -c
shell, which creates a sometimes unnecessary shell process
Avoiding Multi-layer Images
Click to edit Master title style
• Each command executed by a RUN statement in a Containerfile creates a
new layer and this should be avoided
• So don't run multiple RUN commands, connect them using &&
• RUN yum --disablerepo=* --enablerepo="myrepo" && yum update -y && yum
install nmap
• To maintain readability, write the commands on different lines using && \ at the
end of each line:

RUN yum --disablerepo=* --enablerepo="rhel7-server-rpms" && \


yum update -y && \
yum install -y nginx
Building Images with Containerfile
Click to edit Master title style
• To build an image with Containerfile, use podman build
• podman build takes 2 arguments: -t name[:tag] directory
• If no tag is specified, the image is tagged as latest
• podman build -t myimage .
• Tip! Use sudo yum provides */Containerfile for examples of Containerfile
Click to edit Master title style

Lesson 5: Creating Custom


Images

5.4 Advanced Containerfile


Instructions
Using ENV and ARG
Click to edit Master title style
• ARG is used to specify variables that are used during the build process:
they are not available in the final image
• To set and use:
ARG version=1.22
RUN curl "https://my.app.io/${VERSION}
• While using ARG, a default value can be specified, which can be modified
during build creation
• Use podman build --buil-arg key-value to override
• ARG must be specified after FROM
Using ENV and ARG
Click to edit Master title style
• ENV is used to define environment files for use while building the container
image
• They can be used during image build, and overwritten while running the
containers
• Use podman-compose or --env to override
• ENV can be set to the value of an ARG variable: ENV ENV_VAR=$ARG_VAR
• ENV variables can be set through an environment file
• The environment file contains variable specifications as key=value
• The environment file is used using podman run --env-file=myfile.env -d nginx
VOLUME
Click to edit Master title style
• Use the VOLUME instruction to create a volume from within the
Containerfile
• The argument to this instruction is the mountpoint of the volume inside
the running container
• The backing volume can be shown using podman volumes ls
Multistage Builds
Click to edit Master title style
• You should always try to keep images as small as possible
• This isn't always obvious if for instance you compile an application using
RUN statements while building the image
• One solution would be to cleanup all builder tools after compiling your
application
• Another solution is the multistage build
• In a multistage build you build the application in stage one. In stage two,
you'll access the compiled application from the stage one image
• In this scenario, the stage one image is not in the final image which helps
keeping it minimal
• See multistage/Containerfile in the Git repo for an example
Click to edit Master title style

Lesson 5: Creating Custom


Images

Lesson 5 Lab: Creating Custom Images


Lesson 5 Lab
Click to edit Master title style
• Use a Containerfile to create an image that runs the Apache httpd server,
based on the ubi 8 image. While building, add the nmap software package
to the image, as well as the httpd image and ensure that no yum cache is
stored. Set the httpd service to the default process that will be started. It
should start as a foreground process. After building it, run the image.
Click to edit Master title style

Lesson 6: Using podman-


compose

Using podman-compose
Understanding podman-compose
Click to edit Master title style
• podman-compose is used to automate the creation of multi-container
applications
• It is based on docker-compose and uses a compose.yaml file to specify
containers to be created as well as their properties
• As an alternative, podman can create Kubernetes compatible podman pods
Understanding compose.yaml
Click to edit Master title style
• In the compose.yaml different containers and their properties can be
defined
• After creating the yaml file, use podman-compose up to activate the
containers defined in the yaml file
Demo: Installing podman-compose
Click to edit Master title style
• sudo dnf install python3-pip
• pip3 install podman-compose
• git clone https://github.com/sandervanvugt/ex188
• cd ex188
• podman-compose up -d
• podman ps
• podman-compose logs -n -f

You might also like