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
podman build -t weather -f Dockerfile.weather .
podman run --tty=true -a=stdin -a=stdout weatherBuildah
buildah bud -t weather -f Dockerfile.weather .
buildah from --name myweather weather
buildah run myweather python3 weather.pyFile: 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
- CRI-O configuration:
- A working Kubeconfig to access that cluster in
$HOME/.kube/config - A working
crictlbinary and configuration
Contents
- Basic interactions with CRI-O
- Logging and live configuration reload
- Life Cycle of a Kubernetes workload
- Port Forward
- Recovering
- Networking
- Pull Auth
- Registries
- Registry Mirrors
- 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.
-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:
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:
- Pull Image
- List Images
- Start Container
- List Containers
- Inspect Container
- Stop Container
Running the application
- Clone the repo and enter the podman_go_bindings directory.
$ git clone https://github.com/containers/Demos.git
$ cd Demos/podman_go_bindingsDownload the required packages to build from source.
Ensure podman.socket is activated
systemctl --user start podman.socket- Run the application
$ go run main.goMore 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
pip install pygame opencv-python clickSetup 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
Ensure your driving video file is available in mp4 format.
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.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.mp4On 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.
podman system service tcp:localhost:8080 --log-level=debug --time=0In 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.
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:8080matches the Podman service invocation above/v1.40.0denotes the API version we are using/libpoddenotes we expect the service to provide a libpod specific return payload- Not using this element causes the server to return a compatible payload
/infois 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.
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:
2.1.0-devThe following works from the shell:
$ curl -s 'http://localhost:8080/v1.40.0/libpod/info' | jq .version.Version
"2.1.0-dev"Listing Containers
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.
$ 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.)
#!/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.