Containers

modern software distribution

Books

In this lecture: Containers

  • theory
  • creation & usage
  • deploy with cockpit
  • deploy in the CLI
  • Complex deployment

are containers?

Containers are groups of processes running on a Linux system that are isolated from each other.

  • Rogue processes can’t dominate system resources
  • Hostile containers are prevented from attacking other containers
  • Dependency problem is solved

How to isolate resources?

Resource constraints:

(cgroups)

  • memory
  • cpu
  • networks

Virtualization equivalent: namespaces. Examples are

  • Network namespace
  • Mount namespace
  • PID namespace

Security (Advanced)

  • drop linux CAP: limit root power
  • SELinux: unix permission on steroids(MAC)
  • Seccomp: limits syscall
  • user namespace: Translates UID/GID

more definitions

  • container orchestrator
  • container engines
  • OCI runtime

Software projects and products that orchestrate containers onto multiple different machines or nodes

  • container orchestrator
  • container engines
  • OCI runtime

used for configuring containerized applications to run on a single local node. launched by:

  • users,
  • administrators,
  • systemd,
  • kubernets
  • container orchestrator
  • container engines
  • Open Container Initiative runtime

Configure different parts of the Linux kernel and launch the containerized application.

  • runc
  • crun

Dealing with containers

venv vs VM vs Containers

pods (Advanced)

Group of one or more containres sharing Network and Storage resources

Why podman and not docker (Advanced)

  • pods are native
  • integration with systemd
  • support kubernetes
  • daemon less
  • no root needed

podman commands

commandaction
podman ps (--all)List running containers (and stopped)
podman run (-it --rm)runs a container (interactive mode, remove at the end)
podman stopstop a running container
podman startstarts a stopped container
podman rmremove a stopeed container (possible data loss)
podman imageslist available container images
podman image rmremove an image
podman exec execute a command in a pod

Interactive container demo

Stream online

Daemon container demo

Stream online

Container images

container vs container image

  • container: The running process
  • container image: the file that containes all the software and libraries needed to run your application

Creating a container image

The Dockerfile is a text-based file used to create a container image. It provides the recipy to build the environemnt for your app.

FROM python:3.12

# Install the application dependencies
WORKDIR /usr/local/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# Copy in the source code
COPY src ./src

# Setup an app user so the container doesn't run as the root user
EXPOSE 8080
RUN useradd app
USER app

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]

Dockerfile steps

  1. Determine your base image
  2. Install application dependencies
  3. Copy in any relevant source code and/or binaries
  4. Configure the final image

Determine your base image

FROM python:3.12

# Install the application dependencies
WORKDIR /usr/local/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# Copy in the source code
COPY src ./src

# Setup an app user so the container doesn't run as the root user
EXPOSE 8080
RUN useradd app
USER app

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]

Install dependencies

FROM python:3.12

# Install the application dependencies
WORKDIR /usr/local/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# Copy in the source code
COPY src ./src

# Setup an app user so the container doesn't run as the root user
EXPOSE 8080
RUN useradd app
USER app

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]

Copy source code and binaries

FROM python:3.12

# Install the application dependencies
WORKDIR /usr/local/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# Copy in the source code
COPY src ./src

# Setup an app user so the container doesn't run as the root user
EXPOSE 8080
RUN useradd app
USER app

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]

Configure the final image

FROM python:3.12

# Install the application dependencies
WORKDIR /usr/local/app
COPY requirements.txt ./
RUN pip install --no-cache-dir -r requirements.txt

# Copy in the source code
COPY src ./src

# Setup an app user so the container doesn't run as the root user
EXPOSE 8080
RUN useradd app
USER app

CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8080"]

instructions

InstructionDescription
FROMCreate a new build stage from a base image.
RUNExecute build commands.
ENVSet environment variables.
WORKDIRChange working directory.
COPYCopy files and directories.
EXPOSEDescribe which ports your application is listening on.
USERSet user and group ID.
CMDSpecify default commands.
ENTRYPOINTSpecify default executable.
CMD vs ENTRYPOINT

CMD defines the default executable of a Docker image. If you add an argument to the command, you override the CMD.

You cannot override the ENTRYPOINT instruction by adding command-line parameters to the docker run command

Layered filesystem

where do I find images?

registries!

Building a contaier form dockerfile

# build
podman build . -t mycontainer:verions
# and publish
podman push localhost/mycontainer:version somewere

pre excercise

For those of you who didn't, Check that you can connect to cockpit (last week slides)

excercise

  • create a python script that sums two numbers
  • create a docker file that incorporate the script
  • run the scirpt inside the dockerfile

The python script (main.py)

import sys

# Check if the correct number of arguments is provided
if len(sys.argv) != 3:
    print("Usage: python script.py  ")
    sys.exit(1)

# Get the arguments from the command line
try:
    num1 = float(sys.argv[1])
    num2 = float(sys.argv[2])
except ValueError:
    print("Please provide two numbers.")
    sys.exit(1)

# Calculate the sum
result = num1 + num2

# Print the result
print(f"The sum of {num1} and {num2} is: {result}")

the Dockerfile

FROM python:3.12-alpine

WORKDIR /opt
COPY main.py .

ENTRYPOINT ["python", "main.py"]
# BOTH FILES MUST BE IN THE SAME FOLDER
podman build . -t demo:v0.0.1

test the result

podman run demo:v0.0.1 1 2
# finally check
podman ps --all
# what happened?

Data Persistency

why voluems?

  • Avoiding embedding data for applications in the image
  • Be able to use the same container image in multiple environments
  • Reducing overhead
  • Sharing content available via network storage

mounting volumes

podman run -d -v ./html:/var/www/html:ro,z -p 8080:8080

the options

  • ro: read only
  • rw: read write
  • z: Selinux (advanced) don't share between container
  • Z: Selinux (advanced) Share between container

Podman named volume

  • like provisioned volume
  • can be exported via TAR to other hosts to recreate the same enviroment

A complete example

Stream online

Exercise 02

Run a service using the cockpit
  • connect to cockpit
  • configure and start the container

configure the container

configure the container

configure the container

running the container

login in the platform

Host mdmc_vm
    ProxyJump mdmc_gateway
    Hostname 172.16.0.XX
    User user00
    LocalForward 8989 localhost:8000
    LocalForward 9090 localhost:9090
    LocalForward 9091 localhost:9091
username/pwd minioadmin

use the CLI

Stream online

have a look at the minio registry on quay

Exercise 03

Using the platform
  • install mc
  • create a bucket
  • load the file in a bucket
install MinioClinet(mc)
# get the binary
curl https://dl.min.io/client/mc/release/linux-amd64/mc \
    --create-dirs \
    -o $HOME/.local/bin/mc
# make it executable
chmod +x $HOME/.local/bin/mc
# take a look at the instructions
mc --help

Create a bucket

Create a bucket

Create a bucket

Load a file in to a bucket

# check where you can load files
mc alias list
# load a file
mc cp my-file local/bucket/my-file