Understanding Containers

A container is a complete package to run an application, which contains all application dependencies

Containers make it easy to run different versions of application dependencies side-by-side. Since containers are isolated environments, their functions has no effect on other containers

Containers run on top of a container engine that is offered by the host operating system

The operating system kernel is not included in the container, but offered by the host

Containers use container images to initiate

Containers as Processes

The purpose of a container is to run an isolated process

To do this, container images are configured to run a standard application

Once the application is complete, the container is closed

Application containers are used to run common applications, such as scripts that has dependencies to run

System Containers are used as the foundation to build custom images, and don’t come with a standard application

Container Requirements

Containers are Linux and rely heavily on features provided by the Linux kernel:

One container per application

Multiple applications can be connected in Microservices

To manage containers at an enterprise level, orchestration is needed. RedHat offers OpenShift as its Kuburnetes distribution, which is used for orchestration

Containers on RHEL8

Available solutions are highly compatible and interchangeable because of the Open Containers initiative

RHEL8 does not offer Docker support

Available solutions:

Understanding Rootless Containers

If containers need to run a process on a privileged port, they need to run with root privileges

Rootless containers will run as a non-root user

Running containers as root is not safe

Running a Container

Ensure the container management tools are installed:

yum module install container-tools

Once installed, containers fro the Docker Registry can be ran:

podman run -d nginx

RedHat registries can be found at registry.redhat.io, and third-party products are available via registry.connect.redhat.com

RedHat registry access requires authentication using podman login, where RedHat account name and password are provided

Registries are processed in order within /etc/containers/registries.conf

To acquire a specific container, a complete name reference can be used:

podman pull registry.access.redhat.com/ubi8/ubi:latest

How to Run a Container

Use podman pull to pre-pull the image from the registry to the local system

Use podman run to pull the container and run it

By default, the container in the foreground. To avoid this, pass the -d option to run the container in detached mode

The -it option will run the container in an interactive tty mode

The --rm container will remove the container after its use

Detach from a container while in tty mode by using CTRL+p, CTRL+q

exit will exit from the primary container application using exit

podman ps will print all currently running containers

--all will print all containers still available on the system

If a system container is ran without interactive mode, it will close immeidately once /bin/bash is loaded

To attach to a running container:

podman attach [CONTAINER_NAME]

Use podman ps to acquire the container name

Managing Images

Understanding Images

The image is the read-only runnable instance of the container

Images are obtained from registries, which are specified in /etc/containers/registries.conf

Additiontal registries can be added in the [registries.search] section

Insecure registries are not protected with TLS encryption and must be listed in [registries.insecure]

Searching for Images

podman search searches all registries

podman search --no-trunc [registry.redhat.io/rhel8](<http://registry.redhat.io/rhel8>) searches specific registry on the RHEL8 string

Filters can be used on search results:

Web search is available through https://access.redhat.com/containers or https://hub.docker.io

Inspecting Images

skopeo inspects images before pulling them:

skopeo inspect docker://registry.redhat.io/ubi8/ubi

podman can be used to inspect images that are locally available:

podman images

podman inspect registry.redhat.io/ubi8/ubi

Removing Images

When new versions of images become available, the old version will be kept on the system as well

podman images will list all available images

podman rmi [PACKAGE_NAME] will remove the specified image

Advanced Image Management

buildah provides advance image management and can be used to create custom images

buildah bud will build an image based on a Dockerfile

Managing Containers

Managing Container Ports

Map a host to the container application port to make it reachable from the outside

To map host port 8000 to container port 80:

podman run -d -p 8000:80 nginx

podman port -a will show all current container port mappings

Ensure to also open any ports in the host firewall:

firewall-cmd --add-port 8000/tcp
firewall-cmd --add-pot 8000/tcp --permenant

Containers running without root privileges can only bind to a non-privileged host port

Managing Environment Variables

Some containers require environment variables to run them

If a container fails due to this requirement, use podman logs [CONTAINER_NAME], which will show the application log

Alternatively, the podman inspect command can be used and information can be found within the usage section

Use -e [VAR]=[VALUE] when starting a container to pass variable values:

podman run -d --name mydb -e MYSQL_ROOT_PASSWORD=password -e MYSQL_USER=bob -e MYSQL_PASSWORD=password -e MYSQL_DATABASE=books -p 3306:3306 mariadb

Managing Container State

podman stop [CONTAINER_NAME] stops a container gracefully by sending the SIGTERM signal

If the container isn’t stopped within 10 seconds, the container then receives the SIGKILL signal

podman kill [CONTAINER_NAME] immediately sends the SIGKILL signal to the container

podman restart [CONTAINER_NAME] restarts a container that was previously stopped

Running Commands in a Container

podman exec [CONTAINER_NAME] uname -r runs an additional process inside a running container

podman exec -it [CONTAINER_NAME] /bin/bash accesses an interactive shell

podman exec -l cat /etc/redhat-release runs the command on the last container that used in any command

Understanding Root Containers

By default, podman runs non-root containers

Non-root containers cannot bind to a privileged port and do not have an IP Address

sudo podman run -d nginx will start a root container

Root containers can only be listed by using sudo podman ps

After starting a root container, a bridge device is created on the host operating system that works like NAT to make sure the root container can access the external network

Attaching Storage to Containers

Container storage is ephemeral

Modifications are written to the container writable layer and pertain only for the container’s lifetime

Persistent storage keeps files externally

Use bind mounts to connect a directory inside the container to a directory on the host

Preparing Host Storage

Ensure that the user account used in the container has access to the host directory and set the SELinux context type to container_file_t

If the container user is owner of the host directory, the :Z option can be used:

podman run -d -v /webfiles:/webfiles:Z nginx

Mount Storage Inside the Container

First create the mount point on the host:

sudo mkdir /dbfiles

Then, apply the correct file permissions:

sudo chmod o+w /dbfiles

Ensure the the directory has the correct user ownership:

sudo chown user:user /dbfiles

Apply the required SELinux context:

sudo semanage fcontext -a -t container_file_t "/dbfiles(/.*)?"

Managing Containers as Services

Autostarting Containers

To automatically start containers in a stand-alone situation, systemd user unit files can be created for rootless containers and managed with systemctl

If Kubernetes or OpenShift is used, containers will be automatically started by default

Running Systemd Services as a User

Systemd user services start when a user session is opened, and closed when the user session is stopped

Use loginctl enable-linger to change that behavior and start user services for a specific user:

loginctl enable-linger user

loginctl show-user user

Managing Containers Using systemd Services

Create a regular user account to manage all containers

Use podman to generate a user systemd file for an existing container. The file will be generated in the current working directory:

podman generate systemd --name [CONTAINER_NAME] --files

To have systemd create the container when the service starts, and delete it again when the service stops, add --new:

podman generate systemd --name [CONTAINER_NAME] --files --new

To generate a service file for a root container, do it from /etc/systemd/system as the current directory

Create User Unit Files

Create user specific files in ~/.config/systemd/user

Manage them using systemctl --user command:

systemctl --user daemon-reload
systemctl --user enable app.service
systemctl --user start app.service

systectl --user commands only work when logging in on console or SSH and do not work in sudo and su sessions

Leave a Reply

Your email address will not be published.