demos Documentation

Repository is a location of user demos for technologies listed on github.com/containers

84 stars Shell Shell 1 file ยท ~5,986 tokens
RAW Doc

Docker & Self-Hosted Deployment Verified OCI

Deploy demos on any server, homelab, or cloud container platform.

1-Click Terminal Command
bash (docker run)
docker run -d --name demos --restart always containers/demos:latest

File: README.md

Demos

Repository is a location of user demos for technologies listed on github.com/containers

Building directory is for Demos related to building container images.
podman_cli directory is for Demos for each of the Podman command line commands.
Running directory is for Demos related to running containers.
Security directory is for Demos related to containers security.


File: CODE-OF-CONDUCT.md

The Demos Project Community Code of Conduct

The Demos project follows the Containers Community Code of Conduct.


File: SECURITY.md

Security and Disclosure Information Policy for the Demos Project

The Demos Project follows the Security and Disclosure Information Policy for the Containers Projects.


File: building/buildah_intro/README.md

Buildah Introduction Demo

This demo demonstrates how to use the buildah command to create
container images and containers. This demo shows how to do so
using a Dockerfile and by building the container from 'scratch'.

It requires buildah 1.6, podman 1.0, docker 1.13 or newer versions.

This demo should be run as a non-root user with sudo privileges.


File: building/myweather/README.md

My Weather Demo

This demo shows how to use the 'stable' buildah image on
quay.io/buildah to create a container that can show the weather
of an inputed city.

It requires Buildah 1.8, Podman 1.3 or newer versions.

Commands

First copy the Dockerfile.weather and weather.py from this directory
to the machine where Podman or Buildah is installed.

Podman

text
podman build -t weather -f Dockerfile.weather .
podman run --tty=true -a=stdin -a=stdout weather

Buildah

text
buildah bud -t weather -f Dockerfile.weather .
buildah from --name myweather weather
buildah run myweather python3 weather.py

File: cri-o/README.md

CRI-O Demos

This repository aims to provide you the demo material for the Kubernetes
container runtime CRI-O.

Requirements

The following requirements needs to be fulfilled to run the demos inside this

  • A running Kubernetes cluster (via systemd units) with CRI-O as configured
    container runtime
    • CRI-O configuration:
      toml
      cgroup_manager = "systemd"
      conmon_cgroup = "system.slice"
    • Kubelet should be started with: -v=2 --cgroup-driver=systemd
  • A working Kubeconfig to access that cluster in $HOME/.kube/config
  • A working crictl binary and configuration

Contents

  1. Basic interactions with CRI-O
  2. Logging and live configuration reload
  3. Life Cycle of a Kubernetes workload
  4. Port Forward
  5. Recovering
  6. Networking
  7. Pull Auth
  8. Registries
  9. Registry Mirrors
  10. Storage

How to use

Each demo can be selected via its appropriate command line argument, whereas
multiple demos can be selected too. It is also possible to continuously run
the demos, avoid the manual [ENTER] input and disable the typewriter effect.

text
-1, --interaction             this demo shows basic interactions with CRI-O,
                              the kubelet and between both of them

-2, --logging                 this demo shows how to configure CRI-O logging
                              and reload the configuration during runtime

-3, --lifecycle               this demo shows how CRI-O ensures the
                              containers life-cycle in conjunction with the
                              kubelet

-4, --port-forward            this demo shows how port forwaring works in
                              CRI-O

-5, --recovering              this demo shows what happens if a workload
                              unexpectedly stops

-6, --networking              this demo shows how the basic networking works
                              in CRI-O

-7, --pull-auth               this demo shows how registry authentication
                              works in CRI-O

-8, --registries              this demo shows how to configure registries
                              with CRI-O

-9, --registry-mirrors        this demo shows how to configure registries
                              mirrors in CRI-O

--10, --storage               this demo shows how container storage can be
                              configured

--all                         run all demos

--auto, -a                    run the demo in automatic mode, where every
                              step gets executed automatically

--auto-timeout auto, -t auto  the timeout to be waited when auto is enabled
                              (default: 3s)

--continuously, -c            run the demos continuously without any end

--immediate, -i               immediately output without the typewriter
                              animation

--skip-steps value, -s value  skip the amount of initial steps within the
                              demo (default: 0)

How it works

Each demo contains a series of intermediate steps, whereas each step can
contain a description and a command to be executed.

In source code, it would look like this:

go
package runs

import (
	. "github.com/containers/Demos/cri-o"
	"github.com/urfave/cli"
)

func Example(ctx *cli.Context) error {
	d := New(
		"Title",
		"Some additional",
		"multiline description",
	)

	d.Step(S(
		"This is a possible",
		"description of the command",
		"to be executed",
	), S(
		"echo hello world",
	))

	// Commands to not need to have a description
	d.Step(nil, S(
		"echo without description",
	))

	// It is also not needed to provide a command
	d.Step(S(
		"Just a description without a command",
	), nil)

	return d.Run(ctx)
}

A full working demo would look like this:


File: podman_cli/README.md

Demos - podman_cli

Podman Command Demo Scripts

This directory is the home of the Demo scripts for the Podman CLI commands.
It is expected that these scripts will be used for demonstration purposes, and most
specifically as links on the commands.md
file in the libpod GitHub project. The scripts in this directory
should be run and recorded using asciinema. The casts from
that recording should be captured and stored on the podman.io site under the asciinema
top level directory. This page documents how the casts should be recorded and the
files that need to be created or modified to display them.

Script creation

Create a script to be put into the containers/Demos project in the containers/Demos/podman_cli directory. Name it podman_{command}.sh. For example podman_images.sh for the podman images command. Make sure it shows as many features of the command as possible and is well documented. Use the podman_images.sh file in this directory as a base example. The script should targeted for use by someone with little Podman knowledge.

Once you are satisfied with your script, do a standard Git add/commit/push cycle to create a PR for the script.

VM setup

Create a new Fedora Virtual Machine (vm) and dnf -y install asciinema to install asciinema.
Install the latest Podman with dnf -y install podman --enablerepo updates-testing.

Login to the vm with a 24 rows X 132 columns terminal as a non-root user, copy your script there and ensure that you can run the script.

Demo recording

Before running the script, start asciinema with asciinema rec. Then run your script making sure to
pause long enough for each command so that a first time viewer can read all of the output.

When your script has completed, turn off the recording with <ctrl>d <ctrl>c. Then copy the /tmp/*.cast file that was created by the recording to ./podman_{command}.cast

Store cast in podman.io

Create a PR in https://github.com/containers/podman.io

In the asciinema directory, create a directory under the podman directory that's the same name as the command you're demoing. Copy your podman_{command}.cast file to this directory. For instance asciinema/podman/images/podman_images.cast for the podman images recording.

Copy the index.html from asciinema/podman/images/index.html to your new directory. Update the index.html changing the name of the file inside of index.html to the podman_{command}.cast file that you recorded.

Do a standard Git add/commit/push cycle to create a PR for these changes.

Update commands.md in libpod

After the PR's for the script and recording are merged, create a PR in libpod on GitHub to update https://github.com/containers/libpod/commands.md, adding links to the script and the podman.io asciinema locations for the command that you created the script and recording of.


File: podman_go_bindings/README.md

Demos - podman_Go_bindings

Sample Application for Podman Go Bindings

This directory contains a sample application to run Podman operations in
external applications via a set of Go bindings.

There's a single Go file, which uses the Podman Go bindings to run the
following operations:

  1. Pull Image
  2. List Images
  3. Start Container
  4. List Containers
  5. Inspect Container
  6. Stop Container

Running the application

  1. Clone the repo and enter the podman_go_bindings directory.
bash
$ git clone https://github.com/containers/Demos.git
$ cd Demos/podman_go_bindings
  1. Download the required packages to build from source.

  2. Ensure podman.socket is activated

bash
systemctl --user start podman.socket
  1. Run the application
bash
$ go run main.go

More Information

Please see the README in the Podman bindings package for more documentation.


File: qm/devconf/README.md

Driving Simulation and Service Monitoring

This demo is a driving simulation application that combines video playback with
real-time service status monitoring.
It leverages modern open-source projects such as
Podman
Systemd
QM
Bluechi

The application uses Pygame for video display, OpenCV for video processing
and system commands to check service statuses.

Requirements

Install the following packages

bash
pip install pygame opencv-python click

Setup VM for Containers

First, you need to create a virtual machine (VM) to run HOST partition and
QM partitions as isolated files systems. After setting up the VM, configure
SSH access without a password. This can be achieved by generating SSH keys
on your local machine and copying the public key to the VM's authorized_keys
file.

Usage

  1. Ensure your driving video file is available in mp4 format.

  2. The IP host must contain two partitions:
    host: Runs critical processes such as tires, safety,
    brakes, and cruise control.
    QM: Runs QM non critical services such as radio, maps, store
    and stream audio (which are isolated under /usr/lib/qm/rootfs/
    file systed with its own system).
    How to setup the QM environment? It's possible to use
    qm setup
    inside VM.

  3. Run the application with the IP address of the server where the services are
    running and the path to the video file:

    bash
    ./driving-displaying-host-qm-status
        --ip IP_VM_RUNNING_BLUECHI_AND_QM_CONTAINERS
        --port VM_SSH_PORT_FORWARD
        --video .video_car_driving.mp4
  4. On a different terminal use bluechictl stop, start, restart HOST/QM services
    in the NODE and QM partitions the messages popup in the video while driving
    like a real agent.

You could also run load tests and check the status in video indicators


File: restful_api/Exploring Podman RESTful API.md

Exploring Podman RESTful API using Python and Bash

You may have heard Podman V2 has a new RESTful API. This document will demonstrate the API using code examples in Python and shell commands. Additional notes are included in the code comments. The provided code was written to be clear vs. production quality.

Requirements

  • You have Python >3.4 installed
  • You have installed the Python requests library
  • An IDE for editing Python is recommended
  • Two terminal windows: one for running the Podman service and reviewing debugging information, the second window to run scripts
  • Usage of curl and jq commands are demonstrated

Getting Started

The Service

For these examples, we are running the Podman service as a normal user and on an unsecured TCP/IP port number.

For production, the Podman service should use systemd's socket activation protocol. This allows Podman to support clients without additional daemons and secure the access endpoint.

The following command will run the Podman service on port 8080 without timing out. You will need to type ^C into this terminal window when you are finished with the tutorial.

shell
podman system service tcp:localhost:8080 --log-level=debug --time=0

In addition to the TCP socket demonstrated above the Podman service supports running under systemd's socket activation protocol and unix domain sockets (UDS).

Python Code

Info Resource

The following will show us information about the Podman service and host.

python
import json
import requests

response = requests.get("http://localhost:8080/v1.40.0/libpod/info")

Deep Dive

  • requests.get() call the requests library to pass the URL to the Podman service using the GET HTTP method
    • The requests library provides helper methods for all the popular HTTP methods
  • http://localhost:8080 matches the Podman service invocation above
  • /v1.40.0 denotes the API version we are using
  • /libpod denotes we expect the service to provide a libpod specific return payload
    • Not using this element causes the server to return a compatible payload
  • /info is the resource we are querying

Interesting to read, but without output how do we know it worked?

Getting output

Append the lines below, and you can now see the version of Podman running on the host.

python
response.raise_for_status()

info = json.loads(response.text)
print(info.version.Version)
  • raise_for_status() will raise an exception if status code is not between 200 and 399.
  • json.loads() decodes the body of the HTTP response into an object/dictionary.

When executed, the output is:

text
2.1.0-dev

The following works from the shell:

shell
$ curl -s 'http://localhost:8080/v1.40.0/libpod/info' | jq .version.Version

"2.1.0-dev"

Listing Containers

python
import json
import requests

response = requests.get("http://localhost:8080/v1.40.0/libpod/containers/json?all=true")
response.raise_for_status()

ctnrs = json.loads(response.text)
for c in ctnrs:
    print(c.Id)

json.loads() decodes the HTTP body into an array of objects/dictionaries, the program then prints each container Id.

shell
$ curl -s 'http://localhost:8080/v1.40.0/libpod/containers/json?all=true' | jq .[].Id

"81af11ef7188a826cb5883330525e44afea3ae82634980d68e4e9eefc98d6f61"

If the query parameter "all=true" had not been provided, then only the running containers would have been listed. The resource queries and parameters for the API are documented at https://docs.podman.io/en/latest/_static/api.html

Something Useful

We've looked at a couple examples but how about something a little more useful? You have finished developing the next great container, the script below will remove everything from your local storage.
(If you want to save on typing clean_storage.py.)

python
#!/usr/bin/env python
import json

import requests

# Clean up local storage by removing all containers, pods, and images.  Any error will
#   abort the process

confirm = input("Really delete all items from storage? [y/N] ")
if str(confirm).lower().strip() != 'y':
    exit(0)

# Query for all pods in storage
response = requests.get("http://localhost:8080/v1.40.0/libpod/pods/json")
response.raise_for_status()

pods = json.loads(response.text)
# Workaround for https://github.com/containers/podman/issues/7392
if pods is not None:
    for p in pods:
        # For each container: delete container and associated volumes
        response = requests.delete(f"http://localhost:8080/v1.40.0/libpod/pods/{p['Id']}?force=true")
        response.raise_for_status()
    print(f"Removed {len(pods)} pods and associated objects")
else:
    print(f"Removed 0 pods and associated objects")

# Query for all containers in storage
response = requests.get("http://localhost:8080/v1.40.0/libpod/containers/json?all=true")
response.raise_for_status()

ctnrs = json.loads(response.text)
for c in ctnrs:
    # For each container: delete container and associated volumes
    print(c.keys())
    response = requests.delete(f"http://localhost:8080/v1.40.0/libpod/containers/{c['Id']}?force=true&v=true")
    response.raise_for_status()
print(f"Removed {len(ctnrs)} containers and associated objects")

# Query for all images in storage
response = requests.get("http://localhost:8080/v1.40.0/libpod/images/json")
response.raise_for_status()

imgs = json.loads(response.text)
for i in imgs:
    # For each image: delete image and any associated containers
    response = requests.delete(f"http://localhost:8080/v1.40.0/libpod/images/{i['Id']}?force=true")
    response.raise_for_status()
print(f"Removed {len(imgs)} images and associated objects")

Summary

I hope you find this helpful. The API documentation provides you with all the resources and required methods. The input and output bodies are included as well as the status codes.

The Podman code is under heavy development and we would like your input with github issues and pull requests.


File: running/README.md

Demos for libpod (Podman)

The following subdirectories contain demos related to Podman.


File: running/BuildahInPodman/README.MD

BuildahInPodman

This script demonstrates running a Buildah container inside
of a Podman container without needing root in the Buildah
container. Buildah will be installed in both the Podman
and the Buildah containers.

You need to execute the building_ctr_wo_root.sh script in
this directory. The script will install the latest versions
of Podman and Buildah using yum.


File: running/ContainerSecurity/README.md

ReplacingDocker

This script demonstrates new security features in podman
You need to execute the podman.sh script in this directory.

  • Running ping without NET_RAW
  • Using oci-seccomp-bpf-hook to generate seccomp.json files
  • Using containers.conf
  • Using Udica
  • Using Capability lists specified inside of a container image

The script will create the buildah-ctr if it does not exist.


File: running/generatekube/README.md

Podman generate kube demo

This demo demonstrates how to use the podman generate kube command. It requires
a functioning Kubernetes environment and will use the kubectl command to create
and remove pods and containers.

Requires podman, kubctl, firefox


File: running/ReplacingDocker/README.md

ReplacingDocker

This script demonstrates running podman as a replacement for the Docker CLI.
You need to execute the podman.sh script in this directory.

The script will create the buildah-ctr if it does not exist.


File: running/restapi/docker-compose.yml

version: '3'
services:
app:
build: myapp
command: sleep 10002


File: running/SELinuxEscape/README.md

SELinuxEscape

This script demonstrates what would happen if a container was to escape confinement
You need to execute the podman.sh script in this directory.

Podman, Docker, and auctl (audit daemon) executables required.


File: security/container_demo.json

{
"metadata": {
"name": "podsandbox1-fedora"
},
"image": {
"image": "docker.io/library/fedora"
},
"args": [
"/bin/bash"
],
"working_dir": "/",
"envs": [
{
"key": "PATH",
"value": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
},
{
"key": "TERM",
"value": "xterm"
},
{
"key": "DISTTAG",
"value": "f26container"
},
{
"key": "FGC",
"value": "f26"
},
{
"key": "NAME",
"value": "redis"
},
{
"key": "VERSION",
"value": "0"
},
{
"key": "RELEASE",
"value": "6"
},
{
"key": "ARCH",
"value": "x86_64"
},
{
"key": "REDIS_VERSION",
"value": "0"
},
{
"key": "HOME",
"value": "/home"
},
{
"key": "CONTAINER_SCRIPTS_PATH",
"value": "/usr/share/container-scripts/redis"
},
{
"key": "REDIS_PREFIX",
"value": "/usr"
}
],
"labels": {
"tier": "backend"
},
"annotations": {
"pod": "podsandbox1"
},
"readonly_rootfs": false,
"log_path": "",
"stdin": true,
"stdin_once": false,
"tty": true,
"linux": {
"resources": {
"memory_limit_in_bytes": 209715200,
"cpu_period": 10000,
"cpu_quota": 20000,
"cpu_shares": 512,
"oom_score_adj": 30,
"cpuset_cpus": "0",
"cpuset_mems": "0"
},
"security_context": {
"run_as_user": {
"value": 0
},
"namespace_options": {
"pid": 1
},
"capabilities": {
"add_capabilities": [
"sys_admin"
]
}
}
}
}


File: security/sandbox_config.json

{
"metadata": {
"name": "podsandbox1",
"uid": "redhat-test-crio",
"namespace": "redhat.test.crio",
"attempt": 1
},
"hostname": "crictl_host",
"log_directory": "",
"dns_config": {
"searches": [
"8.8.8.8"
]
},
"port_mappings": [],
"resources": {
"cpu": {
"limits": 3,
"requests": 2
},
"memory": {
"limits": 50000000,
"requests": 2000000
}
},
"labels": {
"group": "test"
},
"annotations": {
"owner": "hmeng",
"security.alpha.kubernetes.io/seccomp/pod": "unconfined"
},
"linux": {
"cgroup_parent": "/Burstable/pod_123-456",
"security_context": {
"namespace_options": {
"network": 0,
"pid": 1,
"ipc": 0
},
"selinux_options": {
"user": "system_u",
"role": "system_r",
"type": "svirt_lxc_net_t",
"level": "s0:c4,c5"
}
}
}
}


File: security/SELinuxUdica/README.md

SELinuxUdica

This script demonstrates creating specific SELinux security policy for example container.

You need to execute the SELinuxUdica.sh script in this directory. SELinux policy for example container "my_container.cil" will be created.