├── .gitignore
├── CODE-OF-CONDUCT.md
├── Containerfile
├── LICENSE
├── README.md
├── SECURITY.md
├── autosd
└── autosd.sh
├── bootc
├── inference
│ └── podman.sh
├── lamp
│ ├── lamp
│ │ ├── Containerfile
│ │ └── var
│ │ │ └── www
│ │ │ └── html
│ │ │ └── index.php
│ └── podman.sh
├── machine
│ ├── Containerfile
│ ├── Containerfile.fcos
│ ├── etc
│ │ ├── chrony.d
│ │ │ └── 50-podman-makestep.conf
│ │ ├── containers
│ │ │ ├── containers.conf
│ │ │ └── registries.conf.d
│ │ │ │ └── 999-podman-machine.conf
│ │ ├── profile.d
│ │ │ └── docker-host.sh
│ │ ├── skel
│ │ │ └── .config
│ │ │ │ ├── containers
│ │ │ │ └── containers.conf
│ │ │ │ └── systemd
│ │ │ │ └── user
│ │ │ │ ├── default.target.wants
│ │ │ │ └── linger-example.service
│ │ │ │ └── linger-example.service
│ │ ├── subgid
│ │ ├── subuid
│ │ └── systemd
│ │ │ └── system
│ │ │ └── user@.service.d
│ │ │ └── delegate.conf
│ └── usr
│ │ └── lib
│ │ ├── sysctl.d
│ │ └── 10-inotify-instances.conf
│ │ └── tmpfiles.d
│ │ └── podman-docker.conf
└── podman_helper.sh
├── building
├── buildah_intro
│ ├── README.md
│ └── buildah_intro.sh
├── buildah_speed
│ └── buildah_speed.sh
└── myweather
│ ├── Dockerfile.weather
│ ├── README.md
│ └── weather.py
├── cri-o
├── .github
│ └── demo.svg
├── .gitignore
├── README.md
├── go.mod
├── go.sum
├── main.go
└── pkg
│ ├── demo
│ ├── demo.go
│ └── setup.go
│ └── runs
│ ├── example.go
│ ├── interaction.go
│ ├── lifecycle.go
│ ├── logging_live_reload.go
│ ├── networking.go
│ ├── portforward.go
│ ├── pull_auth.go
│ ├── recovering.go
│ ├── registries.go
│ ├── registry_mirrors.go
│ └── storage.go
├── podman_cli
├── README.md
├── podman_images.sh
├── podman_inspect.sh
└── podman_pause_unpause.sh
├── podman_go_bindings
├── README.md
├── go.mod
├── go.sum
└── main.go
├── qm
├── devconf
│ ├── README.md
│ └── driving-displaying-host-qm-status
│ │ ├── .driving.mp4
│ │ └── driving-displaying-host-qm-status
└── qm.sh
├── restful_api
├── Exploring Podman RESTful API.md
└── clean_storage.py
├── running
├── BuildahInPodman
│ ├── README.MD
│ └── building_ctr_wo_root.sh
├── ContainerSecurity
│ ├── README.md
│ ├── containers.conf
│ ├── myvol
│ │ └── Dockerfile
│ └── podman.sh
├── GenerateSeccomp
│ └── podman.sh
├── PINP
│ ├── podman-in-podman.sh
│ └── podman.sh
├── README.md
├── ReplacingDocker
│ ├── Dockerfile.buildah
│ ├── README.md
│ ├── myvol
│ │ └── Dockerfile
│ └── podman.sh
├── SELinuxEscape
│ ├── README.md
│ ├── breakout.sh
│ └── podman.sh
├── demo.sh
├── generatekube
│ ├── README.md
│ ├── kubedemo-openshift.sh
│ └── kubedemo.sh
├── generatesystemd
│ └── podman-generate-systemd.sh
└── restapi
│ ├── docker-compose.yml
│ ├── myapp
│ └── Dockerfile
│ ├── restapi.sh
│ └── tests.sh
└── security
├── SELinuxUdica
├── .gitignore
├── README.md
└── SELinuxUdica.sh
├── container_demo.json
├── sandbox_config.json
└── security_demo.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | *ai-lab-recipes*
2 | *store
3 | *manifest-ami.json
4 | *manifest-qcow2.json
5 |
--------------------------------------------------------------------------------
/CODE-OF-CONDUCT.md:
--------------------------------------------------------------------------------
1 | ## The Demos Project Community Code of Conduct
2 |
3 | The Demos project follows the [Containers Community Code of Conduct](https://github.com/containers/common/blob/master/CODE-OF-CONDUCT.md).
4 |
--------------------------------------------------------------------------------
/Containerfile:
--------------------------------------------------------------------------------
1 | # This Containerfile is used for testing builds
2 | from alpine
3 | run echo building
4 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Demos
2 | Repository is a location of user demos for technologies listed on github.com/containers
3 |
4 | `Building` directory is for Demos related to building container images.
5 | `podman_cli` directory is for Demos for each of the Podman command line commands.
6 | `Running` directory is for Demos related to running containers.
7 | `Security` directory is for Demos related to containers security.
8 |
9 |
--------------------------------------------------------------------------------
/SECURITY.md:
--------------------------------------------------------------------------------
1 | ## Security and Disclosure Information Policy for the Demos Project
2 |
3 | The Demos Project follows the [Security and Disclosure Information Policy](https://github.com/containers/common/blob/master/SECURITY.md) for the Containers Projects.
4 |
--------------------------------------------------------------------------------
/autosd/autosd.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Setting up some colors for helping read the demo output.
4 | # Comment out any of the below to turn off that color.
5 | bold=$(tput bold)
6 | cyan=$(tput setaf 6)
7 | reset=$(tput sgr0)
8 |
9 | read_color() {
10 | read -p "${bold}$1${reset}"
11 | }
12 |
13 | exec_color() {
14 | echo -n "
15 | ${bold}$ $1${reset}"
16 | read
17 | bash -c "$1"
18 | }
19 |
20 | echo_color() {
21 | echo "${cyan}$1${reset}"
22 | }
23 |
24 | init() {
25 | sudo systemctl stop qm > /dev/null
26 | sudo podman rm qm --force -t 0 > /dev/null
27 | sudo podman volume rm --force qmEtc qmVar > /dev/null
28 | sudo rm -rf /usr/lib/qm > /dev/null
29 | }
30 |
31 | install() {
32 | echo_color "Installing qm packages"
33 | exec_color "sudo dnf -y install qm; sudo dnf -y update qm"
34 | exec_color "rpm -q qm"
35 | read
36 | clear
37 | }
38 |
39 | setup() {
40 | echo_color "Executing setup"
41 | echo_color "Enable hirte on the host system"
42 | exec_color "sudo systemctl start hirte hirte-agent"
43 | echo
44 | echo_color "Install and setup /usr/lib/qm/rootfs"
45 | exec_color "sudo /usr/share/qm/setup"
46 | read
47 | clear
48 | }
49 |
50 | status() {
51 | exec_color "sudo systemctl status qm.service"
52 | clear
53 | }
54 |
55 | status() {
56 | exec_color "sudo systemctl status qm.service"
57 | clear
58 | }
59 |
60 | podman() {
61 | clear
62 | exec_color "podman run --device /dev/fuse --replace --cap-add=all --name autosd --security-opt label=disable -d quay.io/centos-sig-automotive/autosd:latest"
63 | exec_color "podman exec -ti autosd bash"
64 | exec_color "echo \"
65 | [Container]
66 | Image=registry.access.redhat.com/ubi8/httpd-24
67 | AddDevice=/dev/fuse
68 | Network=host
69 | PublishPort=8080:80
70 | [Install]
71 | WantedBy=default.target
72 | \" > ./myquadlet.container"
73 | exec_color "echo \"
74 | from quay.io/centos-sig-automotive/autosd
75 | run podman --root /usr/lib/qm/rootfs/var/lib/containers/storage pull registry.access.redhat.com/ubi8/httpd-24
76 | add myquadlet.container /usr/lib/qm/rootfs/etc/containers/systemd/
77 | \" > ./Containerfile"
78 | exec_color "podman build --cap-add sys_admin -t autosd ."
79 | exec_color "podman run --device /dev/fuse --replace --cap-add=all --network=host --name autosd --security-opt label=disable -d quay.io/centos-sig-automotive/autosd:latest"
80 | exec_color "podman exec autosd podman exec qm systemctl status myquadlet.service"
81 | exec_color "firefox localhost:8080"
82 | exec_color "podman stop autosd"
83 | }
84 |
85 | podman
86 |
87 | echo done
88 | read
89 |
--------------------------------------------------------------------------------
/bootc/inference/podman.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | export DEFAULT_APP="chatbot"
4 |
5 | . ../podman_helper.sh
6 |
7 | function clone_ai {
8 | echo_color "
9 |
10 | Clone AI and explore what is available for use with the Podman Desktop AI Studio
11 | "
12 |
13 | exec_color "git clone https://github.com/containers/ai-lab-recipes 2>/dev/null || (cd ai-lab-recipes; git pull origin main)"
14 |
15 | exec_color "podman build --build-arg MODEL_URL=https://huggingface.co/TheBloke/Mistral-7B-Instruct-v0.1-GGUF/resolve/main/mistral-7b-instruct-v0.1.Q4_K_M.gguf -t ${REGISTRY}/mymodel:1.0 ai-lab-recipes/models"
16 |
17 | exec_color "podman push ${REGISTRY}/mymodel:1.0"
18 |
19 | exec_color "podman build -t ${REGISTRY}/model_server:1.0 -f ai-lab-recipes/model_servers/llamacpp_python/base/Containerfile ai-lab-recipes/model_servers/llamacpp_python/"
20 |
21 | exec_color "podman push ${REGISTRY}/model_server:1.0"
22 |
23 | exec_color "podman build -t ${REGISTRY}/$APP:1.0 -f ai-lab-recipes/recipes/natural_language_processing/${APP}/builds/Containerfile ai-lab-recipes/recipes/natural_language_processing/${APP}"
24 |
25 | exec_color "podman push ${REGISTRY}/${APP}:1.0"
26 | }
27 |
28 | function build {
29 | XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/tmp}"
30 | if [ -f "${XDG_RUNTIME_DIR}/containers/auth.json" ]; then
31 | AUTH_JSON="${XDG_RUNTIME_DIR}/containers/auth.json"
32 | else
33 | AUTH_JSON="${HOME}/.docker/config.json"
34 | fi
35 |
36 | login registry.redhat.io
37 |
38 | exec_color "podman build --security-opt label=disable -v ${AUTH_JSON}:/run/containers/0/auth.json --cap-add SYS_ADMIN --from registry.redhat.io/rhel9-beta/rhel-bootc:9.4 --build-arg=SERVERIMAGE=${REGISTRY}/model_server:1.0 --build-arg=APPIMAGE=${REGISTRY}/${APP}:1.0 --build-arg=MODELIMAGE=${REGISTRY}/mymodel:1.0 --build-arg \"SSHPUBKEY=$(cat ~/.ssh/id_rsa.pub)\" -t ${REGISTRY}/${APP}-bootc:1.0 -f ai-lab-recipes/recipes/natural_language_processing/${APP}/bootc/Containerfile ai-lab-recipes/recipes/natural_language_processing/${APP}"
39 |
40 | exec_color "podman push ${REGISTRY}/${APP}-bootc:1.0"
41 | }
42 |
43 | function step_one {
44 | init
45 | login ${REGISTRY}
46 | clone_ai
47 | }
48 |
49 | function step_two {
50 | build
51 | export IMAGE=${REGISTRY}/${APP}-bootc:1.0
52 | oci_test
53 | }
54 |
55 | function step_three {
56 | create_disk_image "--type $TYPE"
57 | }
58 |
59 | function step_four {
60 | clone_containerfiles
61 | }
62 |
63 | case "${1:-""}" in
64 | 1)
65 | step_one
66 | ;;
67 | 2)
68 | step_two
69 | ;;
70 | 3)
71 | step_three
72 | ;;
73 | 4)
74 | step_four
75 | ;;
76 | h)
77 | echo_color "
78 | Users must specify specific sections to demonstrate 1-5 to run this demonstration.
79 |
80 | 1) Clone github.com/containers/ai-lab-recipes and podman build container images off of content. Push container images to a container registry
81 | 2) Build bootable container image with embeded AI Container images and test locally as a container. Push the bootable container image to registry
82 | 3) Convert the OCI Image to an $TYPE and test image locally.
83 | 4) Add cloud-init and nvidia libraries to make it easier to run your image in the cloud with Nvidia GPUs.
84 | "
85 | ;;
86 | *)
87 | step_one
88 | step_two
89 | step_three
90 | step_four
91 | ;;
92 |
93 | esac
94 |
--------------------------------------------------------------------------------
/bootc/lamp/lamp/Containerfile:
--------------------------------------------------------------------------------
1 | FROM quay.io/centos-bootc/centos-bootc:stream9
2 | RUN dnf -y update; dnf install -y httpd mariadb mariadb-server php-fpm php-mysqlnd && dnf clean all && rm -rf /var/cache /var/log/dnf
3 | ADD var var
4 | #RUN systemctl enable httpd mariadb php-fpm
5 | EXPOSE 80
6 |
7 | #Substitute YOUR public key for the below-private key holder for the following public key will have root access
8 | # podman build --build-arg="SSHPUBKEY=$(cat $HOME/.ssh/id_rsa.pub)" ...
9 | ARG SSHPUBKEY
10 | RUN mkdir /usr/etc-system && \
11 | echo 'AuthorizedKeysFile /usr/etc-system/%u.keys' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
12 | echo $SSHPUBKEY > /usr/etc-system/root.keys && chmod 0600 /usr/etc-system/root.keys
13 |
14 | RUN rpm --setcaps shadow-utils
15 |
--------------------------------------------------------------------------------
/bootc/lamp/lamp/var/www/html/index.php:
--------------------------------------------------------------------------------
1 |
Welcome to RHEL image mode
2 |
--------------------------------------------------------------------------------
/bootc/lamp/podman.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | export DEFAULT_APP="lamp"
4 |
5 | source ../podman_helper.sh
6 |
7 | function build {
8 | echo_color "
9 | Build bootable OCI Image"
10 | FROM=""
11 | if [ "${APP}" == "machine" ]; then
12 | podman rmi --force --ignore localhost/fcos
13 | exec_color "cat $APP/Containerfile.fcos"
14 | exec_color "podman build --arch ${ARCH} --manifest localhost/fcos -f $APP/Containerfile.fcos $APP/"
15 | FROM="--from localhost/fcos "
16 | fi
17 | exec_color "cat $APP/Containerfile"
18 |
19 | exec_color "podman manifest exists ${IMAGE} && podman manifest rm ${IMAGE} || podman rmi --force ${IMAGE}"
20 | exec_color "podman build --build-arg=\"SSHPUBKEY=$(cat "${HOME}/.ssh/id_rsa.pub")\" --arch=${ARCH} $FROM--manifest ${IMAGE} $APP/"
21 | }
22 |
23 | function test_crun_vm {
24 | if ! command -v crun-vm; then
25 | sudo bash -c "dnf -y install crun-vm"
26 | fi
27 | echo_color "
28 | Test VM using crun-vm"
29 | tmpdir=$(mktemp -d /tmp/podman.demo-XXXXX);
30 | exec_color "zstd -d ${PWD}/image/${APP}.${TYPE}.zst -o ${tmpdir}/${APP}.${TYPE}"
31 | echo_color "
32 | After starting the next command you will need to go to another terminal and run podman commands against the
33 | VM to test it.
34 |
35 | podman exec -ti -l /bin/sh
36 |
37 | Eventually
38 |
39 | podman stop -l
40 |
41 | "
42 |
43 | exec_color "podman --runtime crun-vm run -ti --rootfs ${tmpdir}"
44 | exec_color "rm -rf ${tmpdir}"
45 | }
46 |
47 | case "${1:-""}" in
48 | 1)
49 | init
50 | build
51 | oci_test
52 | ;;
53 | 2)
54 | login ${REGISTRY}
55 | push_manifest
56 | demo
57 | ;;
58 | 3)
59 | create_disk_image "--type ${TYPE} --type ami"
60 | rename "${TYPE}"
61 | rename ami
62 | test_crun_vm
63 | ;;
64 | 4)
65 | create_manifest "${TYPE}"
66 | create_manifest ami
67 | push_manifest
68 | inspect
69 | ;;
70 | 5)
71 | clone_containerfiles
72 | ;;
73 | *)
74 | echo_color "
75 | Users must specify specific sections to demonstrate 1-5 to run this demonstration.
76 |
77 | 1) Build a bootable OCI Container image and then testing it as an OCI container image
78 | 2) Push the container image to a container registry, demonstrate converting a running
79 | AMI to the bootable container image.
80 | 3) Convert the OCI Image to an $TYPE and test the image locally using crun-vm to make
81 | sure the image works proplery.
82 | 4) Convert the OCI Image to an AMI disk image, add the $TYPE and AMI diskimage to the
83 | OCI image manifest and finally push the OCI Manifest and the disk images to a
84 | container registry. Finally inspect the manifest to see how tools could pull down
85 | specific images.
86 | 5) Add cloud-init and nvidia libraries to make it easier to run your image in the cloud
87 | with Nvidia GPUs.
88 | "
89 |
90 | ;;
91 | esac
92 |
--------------------------------------------------------------------------------
/bootc/machine/Containerfile:
--------------------------------------------------------------------------------
1 | FROM quay.io/centos-bootc/centos-bootc:stream9
2 |
3 | RUN dnf -y update && \
4 | dnf -y install podman subscription-manager crun\* chrony && \
5 | dnf -y clean all && \
6 | systemctl enable podman.service && \
7 | printf "\nconfdir /etc/chrony.d\n" >> /etc/chrony.conf
8 |
9 | ADD usr usr
10 | ADD etc etc
11 |
12 | RUN systemctl enable rhsmcertd.service podman.socket
13 |
14 | RUN groupadd -g 501 core; useradd -u 501 -g 501 core
15 | USER core
16 | RUN systemctl --user enable podman.socket
17 | USER root
18 |
19 | #Substitute YOUR public key for the below-private key holder for the following public key will have root access
20 | # podman build --build-arg="SSHPUBKEY=$(cat $HOME/.ssh/id_rsa.pub)" ...
21 | ARG SSHPUBKEY
22 | RUN mkdir /usr/etc-system && \
23 | echo 'AuthorizedKeysFile /usr/etc-system/%u.keys' >> /etc/ssh/sshd_config.d/30-auth-system.conf && \
24 | echo $SSHPUBKEY > /usr/etc-system/root.keys && chmod 0600 /usr/etc-system/root.keys
25 |
26 | # The following steps should be done in the bootc image.
27 | RUN rpm --setcaps shadow-utils
28 |
--------------------------------------------------------------------------------
/bootc/machine/Containerfile.fcos:
--------------------------------------------------------------------------------
1 | FROM quay.io/fedora/fedora-coreos:testing
2 |
3 | RUN rpm-ostree install dnf; dnf -y remove moby-engine; dnf clean all
4 |
--------------------------------------------------------------------------------
/bootc/machine/etc/chrony.d/50-podman-makestep.conf:
--------------------------------------------------------------------------------
1 | makestep 1 -1
2 |
--------------------------------------------------------------------------------
/bootc/machine/etc/containers/containers.conf:
--------------------------------------------------------------------------------
1 | [engine]
2 | machine_enable=true
3 |
--------------------------------------------------------------------------------
/bootc/machine/etc/containers/registries.conf.d/999-podman-machine.conf:
--------------------------------------------------------------------------------
1 | unqualified-search-registries=["docker.io"]
2 |
--------------------------------------------------------------------------------
/bootc/machine/etc/profile.d/docker-host.sh:
--------------------------------------------------------------------------------
1 | export DOCKER_HOST="unix://$(podman info -f "{{.Host.RemoteSocket.Path}}")"
2 |
--------------------------------------------------------------------------------
/bootc/machine/etc/skel/.config/containers/containers.conf:
--------------------------------------------------------------------------------
1 | [containers]
2 | netns="bridge"
3 | pids_limit=0
4 |
--------------------------------------------------------------------------------
/bootc/machine/etc/skel/.config/systemd/user/default.target.wants/linger-example.service:
--------------------------------------------------------------------------------
1 | ../linger-example.service
--------------------------------------------------------------------------------
/bootc/machine/etc/skel/.config/systemd/user/linger-example.service:
--------------------------------------------------------------------------------
1 | [Unit]
2 | Description", "A systemd user unit demo
3 | After=network-online.target
4 | Wants=network-online.target podman.socket
5 |
6 | [Service]
7 | ExecStart=/usr/bin/sleep infinity
8 |
9 |
--------------------------------------------------------------------------------
/bootc/machine/etc/subgid:
--------------------------------------------------------------------------------
1 | core:100000:1000000
2 |
--------------------------------------------------------------------------------
/bootc/machine/etc/subuid:
--------------------------------------------------------------------------------
1 | core:100000:1000000
2 |
--------------------------------------------------------------------------------
/bootc/machine/etc/systemd/system/user@.service.d/delegate.conf:
--------------------------------------------------------------------------------
1 | [Service]
2 | Delegate=memory pids cpu io
3 |
--------------------------------------------------------------------------------
/bootc/machine/usr/lib/sysctl.d/10-inotify-instances.conf:
--------------------------------------------------------------------------------
1 | fs.inotify.max_user_instances=524288
2 |
--------------------------------------------------------------------------------
/bootc/machine/usr/lib/tmpfiles.d/podman-docker.conf:
--------------------------------------------------------------------------------
1 | L+ /run/docker.sock - - - - /run/user/501/podman/podman.sock
2 |
--------------------------------------------------------------------------------
/bootc/podman_helper.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | set -eou pipefail
4 | IFS=$'\n\t'
5 |
6 | # Setting up some colors for helping read the demo output.
7 | # Comment out any of the below to turn off that color.
8 | bold=$(tput bold)
9 | cyan=$(tput setaf 6)
10 | reset=$(tput sgr0)
11 |
12 | read_color() {
13 | read -r "${bold}$1${reset}"
14 | }
15 |
16 | exec_color() {
17 | echo -n "
18 | ${bold}$ $1${reset}"
19 | read -r
20 | bash -c "$1"
21 | }
22 |
23 | echo_color() {
24 | echo "${cyan}$1${reset}"
25 | }
26 |
27 | DEFAULT_REGISTRY="quay.io/rhatdan"
28 | DEFAULT_TYPE="qcow2"
29 | DEFAULT_ARCH=$(uname -m)
30 | DEFAULT_VARIANT=""
31 | DEFAULT_OS=$(uname)
32 |
33 | OPTSTRING=":a:hr:o:v:A:t:"
34 | function help {
35 | echo -n "
36 | Valid options:
37 |
38 | -A APP (from ai-lab-recipes, options: chatbot, rag)
39 | -a ARCH (target arch to build for, default '$(uname -m)')
40 | -o OS (default '$(uname)')
41 | -r REGISTRY (default 'quay.io/rhatdan')
42 | -t TYPE (disk image type, default 'qcow2')
43 | -v VARIANT
44 | "
45 | }
46 |
47 | while getopts ${OPTSTRING} opt; do
48 | case ${opt} in
49 | r)
50 | REGISTRY="${OPTARG}"
51 | ;;
52 | a)
53 | ARCH="${OPTARG}"
54 | ;;
55 | A)
56 | APP="${OPTARG}"
57 | ;;
58 | o)
59 | OS="${OPTARG}"
60 | ;;
61 | t)
62 | TYPE="${OPTARG}"
63 | ;;
64 | v)
65 | VARIANT="--variant ${OPTARG}"
66 | ;;
67 | h)
68 | help; exit 0
69 | ;;
70 | ?)
71 | echo "
72 | Invalid option: -${OPTARG}."
73 | help; exit 1
74 | ;;
75 | esac
76 | done
77 |
78 | # shift all the args so we can use positional args after the flags (i.e. ./podman.sh -r string -A string 1)
79 | shift $((OPTIND - 1));
80 |
81 | REGISTRY=${REGISTRY:-${DEFAULT_REGISTRY}}
82 | APP=${APP:-${DEFAULT_APP}}
83 | ARCH=${ARCH:-${DEFAULT_ARCH}}
84 | OS=${OS:-${DEFAULT_OS}}
85 | REGISTRY=${REGISTRY:-${DEFAULT_REGISTRY}}
86 | TYPE=${TYPE:-${DEFAULT_TYPE}}
87 | VARIANT=${VARIANT-${DEFAULT_VARIANT}}
88 | IMAGE=${REGISTRY}/${APP}:1.0
89 |
90 | function init {
91 | rm -rf /tmp/podman.demo*
92 | if ! command -v podman &> /dev/null; then
93 | echo "podman must be installed"
94 | exit 1
95 | fi
96 | if ! command -v git &> /dev/null; then
97 | echo "git must be installed"
98 | exit 1
99 | fi
100 | if ! command -v zstd &> /dev/null; then
101 | echo "zstd must be installed"
102 | echo "run 'dnf install zstd' or 'brew install zstd'"
103 | exit 1
104 | fi
105 | }
106 |
107 | function login {
108 | echo_color "
109 | Push generated manifest to container registry"
110 | exec_color "podman login $1"
111 | }
112 |
113 | function push {
114 | image=${1:-${IMAGE}}
115 | exec_color "podman manifest push --all ${image}"
116 | }
117 |
118 | function demo {
119 | echo_color "
120 |
121 | Time for video
122 |
123 | "
124 | read -r
125 | }
126 |
127 | function create_disk_image {
128 | storedir=$(pwd)/store
129 | sudo mkdir -p ${storedir}
130 |
131 | XDG_RUNTIME_DIR="${XDG_RUNTIME_DIR:-/tmp}"
132 | if [ -f "${XDG_RUNTIME_DIR}/containers/auth.json" ]; then
133 | AUTH_JSON="${XDG_RUNTIME_DIR}/containers/auth.json"
134 | else
135 | AUTH_JSON="${HOME}/.docker/config.json"
136 | fi
137 | echo_color "
138 | Creating disk images $1 with bootc-image-builder"
139 | exec_color "sudo podman run -v ${AUTH_JSON}:/run/containers/0/auth.json --rm -it --privileged -v $(pwd):/output -v ${storedir}:/store --pull newer quay.io/centos-bootc/bootc-image-builder $1 --chown ${UID}:${UID} ${IMAGE} "
140 | }
141 |
142 | function rename {
143 | mkdir -p image
144 | new_image="image/$(basename "${IMAGE}").${TYPE}"
145 | exec_color "mv ${TYPE}/disk.${TYPE} ${new_image} 2>/dev/null || mv image/disk.* ${new_image}"
146 | exec_color "zstd -f --rm ${new_image}"
147 | }
148 |
149 | function clone_containerfiles {
150 | echo_color "
151 | Modify OCI Image ${IMAGE} to support cloud-init"
152 | exec_color "git clone https://gitlab.com/bootc-org/examples 2>/dev/null || (cd examples; git pull origin main)"
153 | exec_color "cat examples/cloud-init/Containerfile"
154 | exec_color "podman build --arch=${ARCH} --from ${IMAGE} -t ${IMAGE}-ami examples/cloud-init"
155 | echo_color "
156 | Modify OCI Image ${IMAGE} to support nvidia"
157 | exec_color "cat examples/nvidia/Containerfile"
158 | exec_color "podman build --arch=${ARCH} --from ${IMAGE}-ami -t ${IMAGE}-nvidia examples/nvidia"
159 | }
160 |
161 | function create_manifest {
162 | echo_color "
163 | Populate OCI manifest with artifact $1"
164 | new_image="image/$(basename "${IMAGE}").${TYPE}.zst"
165 | exec_color "podman manifest add ${VARIANT} --os ${OS} --arch=${ARCH} --artifact --artifact-type application/x-qemu-disk --annotation disktype=${TYPE} ${IMAGE} ${new_image}"
166 | }
167 |
168 | function push_manifest {
169 | echo_color "
170 | Push OCI manifest and artifacts to container registry"
171 | exec_color "podman manifest push --all ${IMAGE}"
172 | }
173 |
174 | function inspect {
175 | echo_color "
176 | Inspect the OCI Manigest"
177 | exec_color "skopeo inspect --raw docker://${IMAGE}:1.1 | json_pp"
178 | }
179 |
180 | function oci_test {
181 | echo_color "
182 | Test bootable OCI image as a container"
183 | podman stop test-bootc
184 | exec_color "podman run -d --privileged --name test-bootc --rm -it ${IMAGE} /sbin/init"
185 | exec_color "podman exec -it test-bootc podman images"
186 | exec_color "podman exec -it test-bootc cat /etc/redhat-release"
187 | #exec_color "podman exec -t test-bootc systemctl status ${APP}"
188 | }
189 |
190 |
--------------------------------------------------------------------------------
/building/buildah_intro/README.md:
--------------------------------------------------------------------------------
1 | ## Buildah Introduction Demo
2 |
3 | This demo demonstrates how to use the buildah command to create
4 | container images and containers. This demo shows how to do so
5 | using a Dockerfile and by building the container from 'scratch'.
6 |
7 | It requires buildah 1.6, podman 1.0, docker 1.13 or newer versions.
8 |
9 | This demo should be run as a non-root user with sudo privileges.
10 |
11 |
--------------------------------------------------------------------------------
/building/buildah_intro/buildah_intro.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # buildah_intro.sh demo script.
4 | # This script will demonstrate at an introductory level
5 | # for Buildah basic concepts and uses. Also requires
6 | # the Docker and Podman packages to be installed.
7 |
8 |
9 | # Setting up some colors for helping read the demo output.
10 | # Comment out any of the below to turn off that color.
11 | bold=$(tput bold)
12 | cyan=$(tput setaf 6)
13 | reset=$(tput sgr0)
14 |
15 | read_color() {
16 | read -p "${bold}$1${reset}"
17 | }
18 |
19 | echo_color() {
20 | echo "${cyan}$1${reset}"
21 | }
22 |
23 | setup() {
24 | rpm -q podman >/dev/null
25 | if [[ $? != 0 ]]; then
26 | echo $0 requires the podman package to be installed
27 | exit 1
28 | fi
29 | rpm -q buildah >/dev/null
30 | if [[ $? != 0 ]]; then
31 | echo $0 requires the buildah package to be installed
32 | exit 1
33 | fi
34 | command -v docker > /dev/null
35 | if [[ $? != 0 ]]; then
36 | echo $0 requires the docker package to be installed
37 | exit 1
38 | fi
39 | sudo systemctl restart docker
40 | clear
41 | }
42 |
43 | intro() {
44 | read -p "Buildah Demos!"
45 | echo
46 | }
47 |
48 | version() {
49 | # Buildah version inside a container
50 | echo_color "Check the Buildah version"
51 | echo
52 | read_color "buildah version"
53 | echo
54 | buildah version
55 | echo
56 |
57 | # Buildah info inside a container
58 | echo
59 | echo_color "Check the Buildah info"
60 | echo
61 | read_color "buildah info"
62 | echo
63 | buildah info
64 |
65 | echo
66 | read -p "Enter to continue"
67 | clear
68 | }
69 |
70 | buildah_first_image() {
71 | echo_color "Let's create our very first container image"
72 | echo
73 | read_color "sudo buildah pull alpine"
74 | sudo buildah pull alpine
75 |
76 | echo
77 | echo_color "Let's look at the image"
78 | echo
79 | read_color "sudo buildah images"
80 | sudo buildah images
81 |
82 | echo
83 | echo_color "Create a container from the image"
84 | echo
85 | read_color "sudo buildah from docker.io/library/alpine"
86 | sudo buildah from docker.io/library/alpine
87 |
88 | echo
89 | echo_color "Look at the container"
90 | echo
91 | read_color "sudo buildah containers"
92 | sudo buildah containers
93 |
94 | echo
95 | read -p "Enter to continue"
96 | clear
97 | }
98 |
99 | buildah_using_from_scratch() {
100 |
101 | echo_color "Create an empty image from 'scratch'"
102 | echo
103 | read_color "newcontainer=\$(sudo buildah from scratch)"
104 | newcontainer=$(sudo buildah from scratch)
105 | echo
106 |
107 | echo
108 | echo_color "Now mount the container saving the mount point"
109 | echo
110 | read_color "scratchmnt=\$(sudo buildah mount \$newcontainer)"
111 | scratchmnt=$(sudo buildah mount $newcontainer)
112 |
113 | echo
114 | echo_color "Show the location of the mount point"
115 | echo
116 | read_color "echo \$scratchmnt"
117 | echo $scratchmnt
118 |
119 | echo
120 | echo_color "Show the contents of the mountpoint"
121 | echo
122 | read_color "sudo ls \$scratchmnt"
123 | sudo ls $scratchmnt
124 | read -p "Enter to continue"
125 |
126 | echo
127 | echo_color "Install Fedora 29 bash and coreutils into the container from the host."
128 | echo_color "Only bash and coreutils packages and their dependencies will be installed."
129 | echo
130 | read_color "sudo dnf install --installroot \$scratchmnt --release 29 bash coreutils --setopt install_weak_deps=false -y"
131 | sudo dnf install --installroot $scratchmnt --release 29 bash coreutils --setopt install_weak_deps=false -y
132 |
133 |
134 | echo
135 | echo_color "Show the contents of the mountpoint post install"
136 | echo
137 | read_color "sudo ls \$scratchmnt"
138 | sudo ls $scratchmnt
139 |
140 | echo
141 | echo_color "Show /usr/local/bin inside of the container"
142 | echo
143 | read_color "sudo buildah run \$newcontainer -- ls -alF /usr/local/bin"
144 | sudo buildah run $newcontainer -- ls -alF /usr/local/bin
145 |
146 | /bin/cat > ./runecho.sh <<- "EOF"
147 | #!/usr/bin/env bash
148 | for i in {1..9};
149 | do
150 | echo "This is a new container from buildahdemo [" $i "]"
151 | done
152 | EOF
153 | echo
154 | echo_color "Display contents of runecho.sh"
155 | echo
156 | read_color "cat ./runecho.sh"
157 | cat ./runecho.sh
158 | chmod +x ./runecho.sh
159 |
160 | echo
161 | echo_color "Copy the script into the container"
162 | echo
163 | read_color "sudo buildah copy \$newcontainer ./runecho.sh /usr/local/bin"
164 | sudo buildah copy $newcontainer ./runecho.sh /usr/local/bin
165 |
166 | echo
167 | echo_color "Set the cmd of the container to the script"
168 | echo
169 | read_color "sudo buildah config --cmd /usr/local/bin/runecho.sh \$newcontainer"
170 | sudo buildah config --cmd /usr/local/bin/runecho.sh $newcontainer
171 |
172 | echo
173 | echo_color "Let's run the container which will run the script"
174 | echo
175 | read_color "sudo buildah run $newcontainer /usr/local/bin/runecho.sh"
176 | sudo buildah run $newcontainer /usr/local/bin/runecho.sh
177 |
178 | echo
179 | echo_color "Configure the container added created-by then author information"
180 | echo
181 | read_color "sudo buildah config --created-by \"buildahdemo\" \$newcontainer"
182 | sudo buildah config --created-by "buildahdemo" $newcontainer
183 |
184 | echo
185 | echo
186 | read_color "sudo buildah config --author \"buildahdemo\" --label name=fedora29-bashecho \$newcontainer"
187 | sudo buildah config --author "buildahdemo at redhat.com" --label name=fedora29-bashecho $newcontainer
188 |
189 | echo
190 | echo_color "Let's inspect the container looking for our new configs"
191 | echo
192 | read_color "sudo buildah inspect \$newcontainer"
193 | sudo buildah inspect $newcontainer
194 |
195 | echo
196 | echo_color "Now unmount the container as we're done adding stuff to it"
197 | echo
198 | read_color "sudo buildah unmount \$newcontainer"
199 | sudo buildah unmount $newcontainer
200 |
201 | echo
202 | echo_color "Commit the image that we've created"
203 | echo
204 | read_color "sudo buildah commit \$newcontainer fedora-bashecho"
205 | sudo buildah commit $newcontainer fedora-bashecho
206 |
207 | echo
208 | echo_color "Check for our image"
209 | echo
210 | read_color "sudo buildah images"
211 | sudo buildah images
212 |
213 | echo
214 | echo_color "Remove the container"
215 | echo
216 | read_color "sudo buildah rm \$newcontainer"
217 | sudo buildah rm $newcontainer
218 |
219 | echo
220 | read -p "Enter to continue"
221 | clear
222 | }
223 |
224 | run_image_in_docker() {
225 | systemctl restart docker
226 |
227 | echo
228 | echo_color "Push our image to the Docker daemon"
229 | echo
230 | read_color "sudo buildah push fedora-bashecho docker-daemon:fedora-bashecho:latest"
231 | sudo buildah push fedora-bashecho docker-daemon:fedora-bashecho:latest
232 |
233 | echo
234 | echo_color "Show our image under Docker"
235 | echo
236 | read_color "sudo docker images"
237 | sudo docker images
238 |
239 | echo
240 | echo_color "Run our image under Docker"
241 | echo
242 | read_color "sudo docker run fedora-bashecho"
243 | sudo docker run fedora-bashecho
244 |
245 | echo
246 | read -p "Enter to continue"
247 | clear
248 | }
249 |
250 | buildah_from_dockerfile() {
251 |
252 | /bin/cat <<- "EOF" > ./Dockerfile.hello
253 | FROM alpine
254 | RUN apk add python3
255 | ADD HelloFromContainer.py /home
256 | WORKDIR HOME
257 | CMD ["python3","/home/HelloFromContainer.py"]
258 | EOF
259 | echo
260 | echo_color "Create image from a Dockerfile and run the container"
261 | echo_color "Let's look at our Dockerfile"
262 | echo
263 | read_color "cat ./Dockerfile.hello"
264 | cat ./Dockerfile.hello
265 |
266 | /bin/cat <<- "EOF" > ./HelloFromContainer.py
267 | #!/usr/bin/env python3
268 | #
269 | import sys
270 | def main(argv):
271 | for i in range(0,10):
272 | print ("Hello World from Container Land! Message # [%d]" % i)
273 | if __name__ == "__main__":
274 | main(sys.argv[1:])
275 | EOF
276 | echo
277 | echo_color "Let's look at our HelloFromContainer.py"
278 | echo
279 | read_color "cat ./HelloFromContainer.py"
280 | cat ./HelloFromContainer.py
281 |
282 | echo
283 | echo_color "Create the \"hello\" image from the Dockerfile"
284 | echo
285 | read_color "sudo buildah bud -t hello -f ./Dockerfile.hello ."
286 | sudo buildah bud -t hello -f ./Dockerfile.hello .
287 |
288 | echo
289 | echo_color "Create the container from the image"
290 | echo
291 | read_color "sudo buildah from hello"
292 | sudo buildah from hello
293 |
294 | echo
295 | echo_color "Run the container"
296 | echo
297 | read_color "sudo buildah run hello-working-container python3 /home/HelloFromContainer.py"
298 | sudo buildah run hello-working-container python3 /home/HelloFromContainer.py
299 |
300 | echo
301 | echo_color "Now a quick advertisement from Podman."
302 | echo_color "Let's run the container using Podman."
303 | echo
304 | read_color "sudo podman run hello"
305 | sudo podman run hello
306 |
307 |
308 | echo
309 | read -p "Enter to continue"
310 | clear
311 | }
312 |
313 | buildah_from_dockerfile_rootless() {
314 |
315 | echo
316 | echo_color "Now we are going to run buildah rootless"
317 | echo
318 | echo_color "Create image from a Dockerfile and run the container"
319 | echo_color "Let's look at our Dockerfile"
320 | echo
321 | read_color "cat ./Dockerfile.hello"
322 | cat ./Dockerfile.hello
323 |
324 | echo
325 | echo_color "Let's look at our HelloFromContainer.py"
326 | echo
327 | read_color "cat ./HelloFromContainer.py"
328 | cat ./HelloFromContainer.py
329 |
330 | echo
331 | echo_color "Create the \"hello\" image from the Dockerfile"
332 | echo
333 | read_color "buildah bud -t hello -f ./Dockerfile.hello ."
334 | buildah bud -t hello -f ./Dockerfile.hello .
335 |
336 | echo
337 | echo_color "Create the container from the image"
338 | echo
339 | read_color "buildah from hello"
340 | buildah from hello
341 |
342 | echo
343 | echo_color "Run the container"
344 | echo
345 | read_color "buildah run hello-working-container python3 /home/HelloFromContainer.py"
346 | buildah run hello-working-container python3 /home/HelloFromContainer.py
347 |
348 | echo
349 | echo_color "Now a quick advertisement from Podman."
350 | echo_color "Let's run the container using Podman."
351 | echo
352 | read_color "podman run hello"
353 | podman run hello
354 |
355 |
356 | echo
357 | read -p "Enter to continue"
358 | clear
359 | }
360 |
361 | clean_images_and_containers() {
362 |
363 | read_color "sudo buildah rm -a"
364 | sudo buildah rm -a
365 | echo
366 | read_color "sudo buildah rmi -a -f"
367 | sudo buildah rmi -a -f
368 |
369 | echo
370 | read -p "Enter to continue"
371 | clear
372 | }
373 |
374 | clean_temp_files() {
375 |
376 | rm -rf Dockerfile.hello runecho.sh HelloFromContainer.py
377 | }
378 |
379 | setup
380 |
381 | intro
382 |
383 | version
384 |
385 | buildah_first_image
386 |
387 | buildah_using_from_scratch
388 |
389 | run_image_in_docker
390 |
391 | buildah_from_dockerfile
392 |
393 | clean_images_and_containers
394 |
395 | buildah_from_dockerfile_rootless
396 |
397 | clean_images_and_containers
398 |
399 | clean_temp_files
400 |
401 | read -p "End of Demo!!!"
402 | echo
403 | echo "Thank you!"
404 |
--------------------------------------------------------------------------------
/building/buildah_speed/buildah_speed.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # buildah_speed.sh demo script.
4 | # This script will demonstrate at an speed
5 | # for Buildah command running inside of a container
6 | # the Podman packages must be installed.
7 |
8 |
9 | # Setting up some colors for helping read the demo output.
10 | # Comment out any of the below to turn off that color.
11 | bold=$(tput bold)
12 | cyan=$(tput setaf 6)
13 | reset=$(tput sgr0)
14 | export SLOWEST=/var/lib/buildah_slowest
15 | export MEDIUM=/var/lib/buildah_medium
16 | # There is no FASTEST, since we use the host storage
17 |
18 | read_color() {
19 | read -p "${bold}$1${reset}"
20 | }
21 |
22 | echo_color() {
23 | echo "${cyan}$1${reset}"
24 | }
25 |
26 | setup() {
27 | rpm -q podman >/dev/null
28 | if [[ $? != 0 ]]; then
29 | echo $0 requires the podman package to be installed
30 | exit 1
31 | fi
32 | rpm -q buildah >/dev/null
33 | if [[ $? != 0 ]]; then
34 | echo $0 requires the buildah package to be installed
35 | exit 1
36 | fi
37 | echo_color "Setting up Demo"
38 | sudo dnf -y update --downloadonly --setopt=cachedir=/var/cache/dnf/f32 2>/dev/null
39 | for image in fedora ubi8 quay.io/buildah/stable quay.io/buildah/stable quay.io/buildah/upstream; do sudo podman pull -q $image; done 2>/dev/null
40 |
41 | clear
42 | }
43 |
44 | intro() {
45 | read -p "Buildah Speed Demos!"
46 | echo
47 | }
48 |
49 | version() {
50 | # Buildah version inside a container
51 | echo_color "Check the Buildah version"
52 | echo
53 | read_color "buildah version"
54 | echo
55 | sudo buildah version
56 | echo
57 | sudo podman run quay.io/buildah/stable buildah version
58 | echo
59 |
60 | # Buildah info inside a container
61 | echo
62 | echo_color "Check the Buildah info"
63 | echo
64 | read_color "buildah info"
65 | echo
66 | sudo podman run quay.io/buildah/stable buildah info
67 |
68 | echo
69 | read -p "Enter to continue"
70 | clear
71 | }
72 |
73 | buildah_slowest() {
74 | echo
75 | echo_color "
76 | In this example, we are not leaking any information from the host into the
77 | container. The container is fully locked down, and could potentially be run
78 | with separated use namespace. Meaning the build would not be happening as root.
79 |
80 | But this is the slowest way to build containers, since the container starts with
81 | no containers/storage, and needs to pull down all image content used in the
82 | build.
83 |
84 | Pull an ubi8 image into non shared containers/storage.
85 | "
86 | echo
87 | sudo rm -rf $SLOWEST
88 | sudo mkdir -p $SLOWEST
89 | sudo chcon -t container_file_t $SLOWEST
90 | read_color " sudo podman run -v $SLOWEST:/var/lib/containers:Z quay.io/buildah/stable buildah pull ubi8"
91 | sudo /bin/time -o /tmp/buildah_slowest.txt --format "%e" podman run -v $SLOWEST:/var/lib/containers:Z quay.io/buildah/stable buildah pull ubi8
92 | echo_color "
93 | Completed in $(cat /tmp/buildah_slowest.txt) seconds
94 | "
95 |
96 | echo
97 | read -p "Enter to continue"
98 | clear
99 | }
100 |
101 | buildah_fastest() {
102 | echo
103 | echo_color "
104 | In this example, we are going to mount in the containers/storage read/write from
105 | the host into the containers as an additional store at /var/lib/containers.
106 |
107 | Note we have to disable SELinux separation to make this work, since SELinux
108 | would block this access. This gives you the best speed, since the host will see
109 | your built images instantly. But least security since the container can write
110 | to the hosts containers/storage.
111 |
112 | Pull an ubi8 image into shared read/write containers/storage.
113 | "
114 | echo
115 | read_color " sudo podman run --security-opt label=disable -v /var/lib/containers:/var/lib/containers quay.io/buildah/stable buildah pull ubi8"
116 | sudo /bin/time -o /tmp/buildah_fastest.txt --format "%e" podman run --security-opt label=disable -v /var/lib/containers:/var/lib/containers quay.io/buildah/stable buildah pull ubi8
117 | echo_color "
118 | Completed in $(cat /tmp/buildah_fastest.txt) seconds
119 | "
120 | echo
121 | read -p "Enter to continue"
122 | clear
123 | }
124 |
125 | buildah_medium() {
126 | echo
127 | echo_color "
128 | In this example, we are going to mount in the containers/storage read/only from
129 | the host into the containers as an additional store at /var/lib/shared.
130 |
131 | The container can then use the images without having to pull them into it's own
132 | local storage. This gives you excellent security, with the same performance as
133 | buildah_fast demonstration.
134 |
135 | Pull an ubi8 image into shared read/only containers storage with host
136 | "
137 | echo
138 | sudo rm -rf $MEDIUM
139 | sudo mkdir -p $MEDIUM
140 | sudo chcon -t container_file_t $MEDIUM
141 | read_color " sudo podman run -v /var/lib/containers/storage:/var/lib/shared:ro -v $MEDIUM:/var/lib/containers quay.io/buildah/stable buildah pull ubi8"
142 | sudo /bin/time -o /tmp/buildah_medium.txt --format %e podman run -v /var/lib/containers/storage:/var/lib/shared:ro -v $MEDIUM:/var/lib/containers quay.io/buildah/stable buildah pull ubi8
143 | echo
144 | echo_color "
145 | Completed in $(cat /tmp/buildah_medium.txt) seconds
146 | "
147 |
148 | echo
149 | read -p "Enter to continue"
150 | clear
151 | }
152 |
153 | buildah_medium_bud() {
154 | echo
155 | echo_color "
156 | In this example, we are going to mount in the containers/storage read/only from
157 | the host into the containers as an additional store at /var/lib/shared.
158 |
159 | The container can then use the images without having to pull them into it's own
160 | local storage. This gives you excellent security, with the same performance as
161 | buildah_fast demonstration.
162 |
163 | Build a container image with shared read/only containers/storage.
164 | "
165 | echo
166 | sudo rm -rf $MEDIUM
167 | sudo mkdir -p $MEDIUM
168 | sudo chcon -t container_file_t $MEDIUM
169 | read_color " sudo podman run --device /dev/fuse -ti -v $PWD/Dockerfile:/Dockerfile:Z -v /var/lib/containers/storage:/var/lib/shared:ro -v $MEDIUM:/var/lib/containers quay.io/buildah/stable buildah bud /"
170 | sudo /bin/time -o /tmp/buildah_medium_bud.txt --format %e podman run --device /dev/fuse -ti -v $PWD/Dockerfile:/Dockerfile:Z -v /var/lib/containers/storage:/var/lib/shared:ro -v $MEDIUM:/var/lib/containers quay.io/buildah/stable buildah bud /
171 |
172 | echo_color "
173 | Completed in $(cat /tmp/buildah_medium_bud.txt) seconds
174 | "
175 | echo
176 | read -p "Enter to continue"
177 | clear
178 | }
179 |
180 | buildah_medium_bud_with_overlay() {
181 | echo
182 | echo_color "
183 | In this example, we are going to mount in the containers/storage read/only from
184 | the host into the containers as an additional store at /var/lib/shared. We are
185 | also using an OverlayMount of /var/cache/dnf to help speed up the dnf deployment
186 | inside of the container.
187 |
188 | Build a container image with shared read/only containers/storage with overlay mount.
189 | "
190 | echo
191 | sudo rm -rf $MEDIUM
192 | sudo mkdir -p $MEDIUM
193 | sudo chcon -t container_file_t $MEDIUM
194 | read_color " sudo podman run --device /dev/fuse -ti -v /var/cache/dnf/f32:/var/cache/dnf:ro -v $PWD/Dockerfile:/Dockerfile:Z -v /var/lib/containers/storage:/var/lib/shared:ro -v $MEDIUM:/var/lib/containers quay.io/buildah/upstream buildah bud -v /var/cache/dnf:/var/cache/dnf:O /"
195 | sudo /bin/time -o /tmp/buildah_medium_bud_with_overlay.txt --format "%e" podman run -v /var/cache/dnf/f32:/var/cache/dnf:ro --device /dev/fuse -ti -v $PWD/Dockerfile:/Dockerfile:Z -v /var/lib/containers/storage:/var/lib/shared:ro -v $MEDIUM:/var/lib/containers quay.io/buildah/upstream buildah bud -v /var/cache/dnf:/var/cache/dnf:O /
196 |
197 | echo_color "
198 | Completed in $(cat /tmp/buildah_medium_bud_with_overlay.txt) seconds
199 | "
200 | echo
201 | read -p "Enter to continue"
202 | clear
203 | }
204 |
205 | speed_table() {
206 | echo "
207 | As you can see below, the slowest buildah pull to multiple times as long
208 | as the fastest, while the medium took relatively the same amount of time
209 | as the fastest.
210 |
211 | "
212 | printf " _______________________________________\n"
213 | printf " | %-10s | %-10s| %-10s |\n" "Slowest" "Medium" "Fastest"
214 | printf " | ---------- | --------- | ---------- |\n"
215 | printf " | %-10s | %-10s| %-10s |\n" $(cat /tmp/buildah_slowest.txt) $(cat /tmp/buildah_medium.txt) $(cat /tmp/buildah_fastest.txt)
216 | printf " |_____________________________________|\n"
217 | echo
218 | echo
219 | read -p "Enter to continue"
220 | clear
221 | }
222 |
223 | clean_temp_files() {
224 | sudo rm -rf /tmp/buildah*txt $SLOWEST $MEDIUM
225 | }
226 |
227 | clear
228 |
229 | setup
230 |
231 | intro
232 |
233 | buildah_slowest
234 |
235 | buildah_fastest
236 |
237 | buildah_medium
238 |
239 | echo_color "$(speed_table)"
240 |
241 | echo
242 |
243 | buildah_medium_bud
244 |
245 | buildah_medium_bud_with_overlay
246 |
247 | # clean_images_and_containers
248 |
249 | clean_temp_files
250 |
251 | read -p "End of Demo!!!"
252 | echo
253 | echo "Thank you!"
254 |
--------------------------------------------------------------------------------
/building/myweather/Dockerfile.weather:
--------------------------------------------------------------------------------
1 | FROM quay.io/buildah/stable
2 | RUN yum install -y python3 python-pip
3 | RUN pip3 install requests
4 | COPY weather.py /
5 | CMD python3 weather.py
6 |
--------------------------------------------------------------------------------
/building/myweather/README.md:
--------------------------------------------------------------------------------
1 | ## My Weather Demo
2 |
3 | This demo shows how to use the 'stable' buildah image on
4 | quay.io/buildah to create a container that can show the weather
5 | of an inputed city.
6 |
7 | It requires Buildah 1.8, Podman 1.3 or newer versions.
8 |
9 | ### Commands
10 |
11 | First copy the `Dockerfile.weather` and `weather.py` from this directory
12 | to the machine where Podman or Buildah is installed.
13 |
14 | #### Podman
15 |
16 | ```
17 | podman build -t weather -f Dockerfile.weather .
18 | podman run --tty=true -a=stdin -a=stdout weather
19 | ```
20 |
21 | #### Buildah
22 |
23 | ```
24 | buildah bud -t weather -f Dockerfile.weather .
25 | buildah from --name myweather weather
26 | buildah run myweather python3 weather.py
27 | ```
28 |
--------------------------------------------------------------------------------
/building/myweather/weather.py:
--------------------------------------------------------------------------------
1 | import requests
2 | from pprint import pprint
3 | def weather_data(query):
4 | res=requests.get('http://api.openweathermap.org/data/2.5/weather?'+query+'&APPID=b35975e18dc93725acb092f7272cc6b8&units=metric');
5 | return res.json();
6 | def print_weather(result,city):
7 | fahrenheit = (result['main']['temp'] * 1.8) + 32
8 | mph = (result['wind']['speed'] * 2.237)
9 | print("{}'s temperature: {}°F | {}°C ".format(city,round(fahrenheit, 2),round(result['main']['temp'], 2)))
10 | print("Wind speed: {} mph | {} m/s".format(round(mph, 2),round(result['wind']['speed'], 2)))
11 | print("Description: {}".format(result['weather'][0]['description']))
12 | print("Weather: {}".format(result['weather'][0]['main']))
13 | def main():
14 | city=input('Enter the city: ')
15 | print()
16 | try:
17 | query='q='+city;
18 | w_data=weather_data(query);
19 | print_weather(w_data, city)
20 | print()
21 | except:
22 | print('City name not found...')
23 | if __name__=='__main__':
24 | main()
25 |
--------------------------------------------------------------------------------
/cri-o/.gitignore:
--------------------------------------------------------------------------------
1 | crio-demos
2 |
--------------------------------------------------------------------------------
/cri-o/README.md:
--------------------------------------------------------------------------------
1 | # CRI-O Demos
2 |
3 | This repository aims to provide you the demo material for the Kubernetes
4 | container runtime [CRI-O][0].
5 |
6 | [0]: https://github.com/cri-o/cri-o
7 |
8 | ## Requirements
9 |
10 | The following requirements needs to be fulfilled to run the demos inside this
11 | repository:
12 |
13 | - A running Kubernetes cluster (via systemd units) with CRI-O as configured
14 | container runtime
15 | - CRI-O configuration:
16 | ```toml
17 | cgroup_manager = "systemd"
18 | conmon_cgroup = "system.slice"
19 | ```
20 | - Kubelet should be started with: `-v=2 --cgroup-driver=systemd`
21 | - A working Kubeconfig to access that cluster in `$HOME/.kube/config`
22 | - A working `crictl` binary and [configuration][1]
23 |
24 | [1]: https://github.com/kubernetes-sigs/cri-tools/blob/master/docs/crictl.md
25 |
26 | ## Contents
27 |
28 | 1. [Basic interactions with CRI-O](pkg/runs/interaction.go)
29 | 2. [Logging and live configuration reload](pkg/runs/logging_live_reload.go)
30 | 3. [Life Cycle of a Kubernetes workload](pkg/runs/lifecycle.go)
31 | 4. [Port Forward](pkg/runs/portforward.go)
32 | 5. [Recovering](pkg/runs/recovering.go)
33 | 6. [Networking](pkg/runs/networking.go)
34 | 7. [Pull Auth](pkg/runs/pull_auth.go)
35 | 8. [Registries](pkg/runs/registries.go)
36 | 9. [Registry Mirrors](pkg/runs/registry_mirrors.go)
37 | 10. [Storage](pkg/runs/storage.go)
38 |
39 | ## How to use
40 |
41 | Each demo can be selected via its appropriate command line argument, whereas
42 | multiple demos can be selected too. It is also possible to continuously run
43 | the demos, avoid the manual `[ENTER]` input and disable the typewriter effect.
44 |
45 | ```
46 | -1, --interaction this demo shows basic interactions with CRI-O,
47 | the kubelet and between both of them
48 |
49 | -2, --logging this demo shows how to configure CRI-O logging
50 | and reload the configuration during runtime
51 |
52 | -3, --lifecycle this demo shows how CRI-O ensures the
53 | containers life-cycle in conjunction with the
54 | kubelet
55 |
56 | -4, --port-forward this demo shows how port forwaring works in
57 | CRI-O
58 |
59 | -5, --recovering this demo shows what happens if a workload
60 | unexpectedly stops
61 |
62 | -6, --networking this demo shows how the basic networking works
63 | in CRI-O
64 |
65 | -7, --pull-auth this demo shows how registry authentication
66 | works in CRI-O
67 |
68 | -8, --registries this demo shows how to configure registries
69 | with CRI-O
70 |
71 | -9, --registry-mirrors this demo shows how to configure registries
72 | mirrors in CRI-O
73 |
74 | --10, --storage this demo shows how container storage can be
75 | configured
76 |
77 | --all run all demos
78 |
79 | --auto, -a run the demo in automatic mode, where every
80 | step gets executed automatically
81 |
82 | --auto-timeout auto, -t auto the timeout to be waited when auto is enabled
83 | (default: 3s)
84 |
85 | --continuously, -c run the demos continuously without any end
86 |
87 | --immediate, -i immediately output without the typewriter
88 | animation
89 |
90 | --skip-steps value, -s value skip the amount of initial steps within the
91 | demo (default: 0)
92 | ```
93 |
94 | ## How it works
95 |
96 | Each demo contains a series of intermediate steps, whereas each step can
97 | contain a description and a command to be executed.
98 |
99 | In source code, it would look like this:
100 |
101 | ```go
102 | package runs
103 |
104 | import (
105 | . "github.com/containers/Demos/cri-o"
106 | "github.com/urfave/cli"
107 | )
108 |
109 | func Example(ctx *cli.Context) error {
110 | d := New(
111 | "Title",
112 | "Some additional",
113 | "multiline description",
114 | )
115 |
116 | d.Step(S(
117 | "This is a possible",
118 | "description of the command",
119 | "to be executed",
120 | ), S(
121 | "echo hello world",
122 | ))
123 |
124 | // Commands to not need to have a description
125 | d.Step(nil, S(
126 | "echo without description",
127 | ))
128 |
129 | // It is also not needed to provide a command
130 | d.Step(S(
131 | "Just a description without a command",
132 | ), nil)
133 |
134 | return d.Run(ctx)
135 | }
136 | ```
137 |
138 | A full working demo would look like this:
139 | 
140 |
--------------------------------------------------------------------------------
/cri-o/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/containers/Demos/cri-o
2 |
3 | go 1.13
4 |
5 | require (
6 | github.com/gookit/color v1.2.0
7 | github.com/pkg/errors v0.8.1
8 | github.com/urfave/cli v1.22.1
9 | )
10 |
--------------------------------------------------------------------------------
/cri-o/go.sum:
--------------------------------------------------------------------------------
1 | github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
2 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d h1:U+s90UTSYgptZMwQh2aRr3LuazLJIa+Pg3Kc1ylSYVY=
3 | github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU=
4 | github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
5 | github.com/gookit/color v1.2.0 h1:lHA77Kuyi5JpBnA9ESvwkY+nanLjRZ0mHbWQXRYk2Lk=
6 | github.com/gookit/color v1.2.0/go.mod h1:AhIE+pS6D4Ql0SQWbBeXPHw7gY0/sjHoA4s/n1KB7xg=
7 | github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
8 | github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
9 | github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
10 | github.com/russross/blackfriday/v2 v2.0.1 h1:lPqVAte+HuHNfhJ/0LC98ESWRz8afy9tM/0RK8m9o+Q=
11 | github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
12 | github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
13 | github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
14 | github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
15 | github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
16 | github.com/urfave/cli v1.22.1 h1:+mkCCcOFKPnCmVYVcURKps1Xe+3zP90gSYGNfRkjoIY=
17 | github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
18 | gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
19 | gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
20 |
--------------------------------------------------------------------------------
/cri-o/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "fmt"
5 | "os"
6 | "os/signal"
7 | "time"
8 |
9 | "github.com/containers/Demos/cri-o/pkg/demo"
10 | "github.com/containers/Demos/cri-o/pkg/runs"
11 | "github.com/urfave/cli"
12 | )
13 |
14 | func main() {
15 | app := cli.NewApp()
16 | app.Name = "crio-demos"
17 | app.Usage = "CRI-O Demonstration Examples"
18 | app.Authors = []cli.Author{
19 | {Name: "Sascha Grunert", Email: "sgrunert@suse.com"},
20 | }
21 | app.HideVersion = true
22 | app.UseShortOptionHandling = true
23 | app.Before = demo.Setup
24 | app.After = demo.Cleanup
25 | app.Flags = []cli.Flag{
26 | cli.BoolFlag{
27 | Name: "1, interaction",
28 | Usage: "this demo shows basic interactions with CRI-O, the kubelet and between both of them",
29 | },
30 | cli.BoolFlag{
31 | Name: "2, logging",
32 | Usage: "this demo shows how to configure CRI-O logging and reload the configuration during runtime",
33 | },
34 | cli.BoolFlag{
35 | Name: "3, lifecycle",
36 | Usage: "this demo shows how CRI-O ensures the containers life-cycle in conjunction with the kubelet",
37 | },
38 | cli.BoolFlag{
39 | Name: "4, port-forward",
40 | Usage: "this demo shows how port forwaring works in CRI-O",
41 | },
42 | cli.BoolFlag{
43 | Name: "5, recovering",
44 | Usage: "this demo shows what happens if a workload unexpectedly stops",
45 | },
46 | cli.BoolFlag{
47 | Name: "6, networking",
48 | Usage: "this demo shows how the basic networking works in CRI-O",
49 | },
50 | cli.BoolFlag{
51 | Name: "7, pull-auth",
52 | Usage: "this demo shows how registry authentication works in CRI-O",
53 | },
54 | cli.BoolFlag{
55 | Name: "8, registries",
56 | Usage: "this demo shows how to configure registries with CRI-O",
57 | },
58 | cli.BoolFlag{
59 | Name: "9, registry-mirrors",
60 | Usage: "this demo shows how to configure registries mirrors in CRI-O",
61 | },
62 | cli.BoolFlag{
63 | Name: "10, storage",
64 | Usage: "this demo shows how container storage can be configured",
65 | },
66 | cli.BoolFlag{
67 | Name: "all, l",
68 | Usage: "run all demos",
69 | },
70 | cli.BoolFlag{
71 | Name: "auto, a",
72 | Usage: "run the demo in automatic mode, " +
73 | "where every step gets executed automatically",
74 | },
75 | cli.DurationFlag{
76 | Name: "auto-timeout, t",
77 | Usage: "the timeout to be waited when `auto` is enabled",
78 | Value: 3 * time.Second,
79 | },
80 | cli.BoolFlag{
81 | Name: "continuously, c",
82 | Usage: "run the demos continuously without any end",
83 | },
84 | cli.BoolFlag{
85 | Name: "immediate, i",
86 | Usage: "immediately output without the typewriter animation",
87 | },
88 | cli.IntFlag{
89 | Name: "skip-steps, s",
90 | Usage: "skip the amount of initial steps within the demo",
91 | },
92 | }
93 | app.Action = func(ctx *cli.Context) error {
94 | demos := []cli.ActionFunc{}
95 | all := ctx.GlobalBool("all")
96 |
97 | if all || ctx.GlobalBool("interaction") {
98 | demos = append(demos, runs.Interaction)
99 | }
100 | if all || ctx.GlobalBool("logging") {
101 | demos = append(demos, runs.Logging)
102 | }
103 | if all || ctx.GlobalBool("lifecycle") {
104 | demos = append(demos, runs.LifeCycle)
105 | }
106 | if all || ctx.GlobalBool("port-forward") {
107 | demos = append(demos, runs.PortForward)
108 | }
109 | if all || ctx.GlobalBool("recovering") {
110 | demos = append(demos, runs.Recovering)
111 | }
112 | if all || ctx.GlobalBool("networking") {
113 | demos = append(demos, runs.Networking)
114 | }
115 | if all || ctx.GlobalBool("pull-auth") {
116 | demos = append(demos, runs.PullAuth)
117 | }
118 | if all || ctx.GlobalBool("registries") {
119 | demos = append(demos, runs.Registries)
120 | }
121 | if all || ctx.GlobalBool("registry-mirrors") {
122 | demos = append(demos, runs.RegistryMirrors)
123 | }
124 | if all || ctx.GlobalBool("storage") {
125 | demos = append(demos, runs.Storage)
126 | }
127 |
128 | runDemos := func() error {
129 | for _, runDemo := range demos {
130 | if err := runDemo(ctx); err != nil {
131 | return err
132 | }
133 | if err := demo.Setup(ctx); err != nil {
134 | return err
135 | }
136 | }
137 | return nil
138 | }
139 | if ctx.GlobalBool("continuously") {
140 | for {
141 | if err := runDemos(); err != nil {
142 | return err
143 | }
144 | }
145 | }
146 | return runDemos()
147 | }
148 |
149 | // Catch interrupts and cleanup
150 | c := make(chan os.Signal, 1)
151 | signal.Notify(c, os.Interrupt)
152 | go func() {
153 | for range c {
154 | _ = demo.Cleanup(nil)
155 | os.Exit(0)
156 | }
157 | }()
158 |
159 | if err := app.Run(os.Args); err != nil {
160 | fmt.Printf("run failed: %v", err)
161 | os.Exit(1)
162 | }
163 | }
164 |
--------------------------------------------------------------------------------
/cri-o/pkg/demo/demo.go:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | import (
4 | "bufio"
5 | "fmt"
6 | "math/rand"
7 | "os"
8 | "os/exec"
9 | "strings"
10 | "time"
11 |
12 | "github.com/gookit/color"
13 | "github.com/pkg/errors"
14 | "github.com/urfave/cli"
15 | )
16 |
17 | type Demo struct {
18 | steps []step
19 | }
20 |
21 | type step struct {
22 | text, command []string
23 | }
24 |
25 | func New(description ...string) *Demo {
26 | for i, d := range description {
27 | if i == 0 {
28 | color.Cyan.Println(d)
29 | for range d {
30 | color.Cyan.Print("=")
31 | }
32 | fmt.Printf("\n")
33 | } else {
34 | color.White.Darken().Println(d)
35 | }
36 | }
37 | return &Demo{}
38 | }
39 |
40 | func S(s ...string) []string {
41 | return s
42 | }
43 |
44 | func (d *Demo) Step(text []string, command []string) {
45 | d.steps = append(d.steps, step{text, command})
46 | }
47 |
48 | func (d *Demo) Run(ctx *cli.Context) error {
49 | for i, step := range d.steps {
50 | if ctx.GlobalInt("skip-steps") > i {
51 | continue
52 | }
53 | if err := step.run(ctx, i+1, len(d.steps)); err != nil {
54 | return err
55 | }
56 | }
57 | return nil
58 | }
59 |
60 | func Ensure(commands ...string) {
61 | for _, c := range commands {
62 | cmd := exec.Command("bash", "-c", c)
63 | cmd.Stderr = nil
64 | cmd.Stdout = nil
65 | _ = cmd.Run()
66 | }
67 | }
68 |
69 | func (s *step) run(ctx *cli.Context, current, max int) error {
70 | if err := waitOrSleep(ctx); err != nil {
71 | return errors.Wrapf(err, "unable to run step: %v", s)
72 | }
73 | if len(s.text) > 0 {
74 | s.echo(ctx, current, max)
75 | }
76 | if len(s.command) > 0 {
77 | return s.execute(ctx)
78 | }
79 | return nil
80 | }
81 |
82 | func (s *step) echo(ctx *cli.Context, current, max int) {
83 | prepared := []string{" "}
84 | for i, x := range s.text {
85 | if i == len(s.text)-1 {
86 | prepared = append(
87 | prepared,
88 | color.White.Darken().Sprintf(
89 | "# %s [%d/%d]:\n",
90 | x, current, max,
91 | ),
92 | )
93 | } else {
94 | m := color.White.Darken().Sprintf("# %s", x)
95 | prepared = append(prepared, m)
96 | }
97 | }
98 | print(ctx, prepared...)
99 | }
100 |
101 | func (s *step) execute(ctx *cli.Context) error {
102 | joinedCommand := strings.Join(s.command, " ")
103 | cmd := exec.Command("bash", "-c", joinedCommand)
104 |
105 | cmd.Stderr = os.Stderr
106 | cmd.Stdout = os.Stdout
107 |
108 | cmdString := color.Green.Sprintf("> %s", strings.Join(s.command, " \\\n "))
109 | print(ctx, cmdString)
110 | if err := waitOrSleep(ctx); err != nil {
111 | return errors.Wrapf(err, "unable to execute step: %v", s)
112 | }
113 | return errors.Wrap(cmd.Run(), "step command failed")
114 | }
115 |
116 | func print(ctx *cli.Context, msg ...string) {
117 | for _, m := range msg {
118 | for _, c := range m {
119 | if !ctx.GlobalBool("immediate") {
120 | time.Sleep(time.Duration(rand.Intn(40)) * time.Millisecond)
121 | }
122 | fmt.Printf("%c", c)
123 | }
124 | println()
125 | }
126 | }
127 |
128 | func waitOrSleep(ctx *cli.Context) error {
129 | if ctx.GlobalBool("auto") {
130 | time.Sleep(ctx.GlobalDuration("auto-timeout"))
131 | } else {
132 | fmt.Print("…")
133 | _, err := bufio.NewReader(os.Stdin).ReadBytes('\n')
134 | if err != nil {
135 | return errors.Wrap(err, "unable to read newline")
136 | }
137 | fmt.Printf("\x1b[1A") // Move cursor up again
138 | }
139 | return nil
140 | }
141 |
--------------------------------------------------------------------------------
/cri-o/pkg/demo/setup.go:
--------------------------------------------------------------------------------
1 | package demo
2 |
3 | import (
4 | "github.com/urfave/cli"
5 | )
6 |
7 | func EnsureInfoLogLevel() {
8 | Ensure(
9 | `sudo sed -i -E 's/(log_level = )(.*)/\1"info"/' /etc/crio/crio.conf`,
10 | "sudo kill -HUP $(pgrep crio)",
11 | )
12 | }
13 |
14 | func Setup(ctx *cli.Context) error {
15 | Ensure(
16 | // Set log_level to debug
17 | `sudo sed -i -E 's/(log_level = )(.*)/\1"debug"/' /etc/crio/crio.conf`,
18 | "sudo kill -HUP $(pgrep crio)",
19 |
20 | // Remove all events
21 | "kubectl delete events --all",
22 |
23 | // Remove dead pods
24 | "sudo crictl rmp -f $(sudo crictl pods -s NotReady -q)",
25 | )
26 | return Cleanup(ctx)
27 | }
28 |
29 | func Cleanup(ctx *cli.Context) error {
30 | Ensure(
31 | "sudo pkill kubectl",
32 | "kubectl delete pod nginx alpine --now",
33 | "kubectl delete deploy nginx --now",
34 | "sudo crictl rmi hello-world nginx quay.io/crio/private-image",
35 | "[ -f /etc/containers/registries.conf.bak ] && sudo mv /etc/containers/registries.conf.bak /etc/containers/registries.conf",
36 | "sudo systemctl restart crio",
37 | "podman stop registry",
38 | "echo | sudo tee /etc/containers/mounts.conf",
39 | )
40 | return nil
41 | }
42 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/example.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | . "github.com/containers/Demos/cri-o/pkg/demo"
5 | "github.com/urfave/cli"
6 | )
7 |
8 | func Example(ctx *cli.Context) error {
9 | d := New(
10 | "Title",
11 | "Some additional",
12 | "multiline description",
13 | )
14 |
15 | d.Step(S(
16 | "This is a possible",
17 | "description of the command",
18 | "to be executed",
19 | ), S(
20 | "echo hello world",
21 | ))
22 |
23 | // Commands to not need to have a description
24 | d.Step(nil, S(
25 | "echo without description",
26 | ))
27 |
28 | // It is also not needed to provide a command
29 | d.Step(S(
30 | "Just a description without a command",
31 | ), nil)
32 |
33 | return d.Run(ctx)
34 | }
35 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/interaction.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | . "github.com/containers/Demos/cri-o/pkg/demo"
5 | "github.com/urfave/cli"
6 | )
7 |
8 | func Interaction(ctx *cli.Context) error {
9 | d := New(
10 | "Basic interactions with CRI-O",
11 | "This demo shows basic interactions with CRI-O, the kubelet",
12 | "and between both of them",
13 | )
14 |
15 | d.Step(S(
16 | "The recommended way of running CRI-O is within a systemd unit.",
17 | "Let’s verify that CRI-O is running as expected",
18 | ), S(
19 | "sudo systemctl --no-pager status crio",
20 | ))
21 |
22 | d.Step(S(
23 | "If CRI-O is up and running, then a kubelet instance can",
24 | "be configured to run CRI-O",
25 | ), S(
26 | "sudo systemctl --no-pager status kubelet",
27 | ))
28 |
29 | d.Step(S(
30 | "We can use the tool `crictl` to interact with the Container Runtime ",
31 | "Interface (CRI). To let this work out of the box with CRI-O, we",
32 | "just have to adapt the configuration file `/etc/crictl.yaml`.",
33 | ), S(
34 | "cat /etc/crictl.yaml",
35 | ))
36 |
37 | d.Step(S(
38 | "We should be now able to interact with CRI-O via `crictl`",
39 | ), S(
40 | "sudo crictl version",
41 | ))
42 |
43 | d.Step(S(
44 | "We can list the pods and their status",
45 | ), S(
46 | "sudo crictl pods",
47 | ))
48 |
49 | d.Step(S(
50 | "Or the containers",
51 | ), S(
52 | "sudo crictl ps -a",
53 | ))
54 |
55 | d.Step(S(
56 | "All crictl calls result in direct gRPC request to CRI-O",
57 | "For example, `crictl ps` results in a `ListContainersRequest`.",
58 | ), S(
59 | "sudo journalctl -u crio --since '1 seconds ago' |",
60 | "grep -Po '.*ListContainers(Request|Response){.*?}'",
61 | ))
62 |
63 | d.Step(S(
64 | "It looks like that the kubelet generally syncs periodically",
65 | "with CRI-O.",
66 | ), S(
67 | "sudo journalctl -u crio --no-pager --since '2 seconds ago' |",
68 | "grep -Po 'time.*(Request|Response)'",
69 | ))
70 |
71 | return d.Run(ctx)
72 | }
73 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/lifecycle.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | . "github.com/containers/Demos/cri-o/pkg/demo"
5 | "github.com/urfave/cli"
6 | )
7 |
8 | func LifeCycle(ctx *cli.Context) error {
9 | d := New(
10 | "Life Cycle of a Kubernetes workload",
11 | "This demo shows how CRI-O ensures the containers life-cycle",
12 | "in conjunction with the kubelet",
13 | )
14 |
15 | d.Step(S(
16 | "Multiple steps are needed by CRI-O to run a container workload",
17 | "First, let’s create a new pod printing out the current date every 2 seconds",
18 | ), S(
19 | "kubectl run --generator=run-pod/v1 --image=alpine alpine",
20 | "-- sh -c 'while true; do date; sleep 2; done' &&",
21 | "kubectl wait pod/alpine --for=condition=ready --timeout=2m",
22 | ))
23 |
24 | d.Step(S(
25 | "The first thing CRI-O has to accomplish is setting up the pod sandbox",
26 | ), S(
27 | "sudo journalctl -u crio --since '5 minutes ago' |",
28 | "grep -P 'RunPodSandbox(Request|Response)'",
29 | ))
30 |
31 | d.Step(S(
32 | "The `RunPodSandboxRequest` already contains a lot of information",
33 | "for CRI-O to prepare an isolated environment for Kubernetes workloads.",
34 | "The resulting sandbox can now be examined via `crictl`",
35 | ), S(
36 | "sudo crictl inspectp",
37 | `$(sudo crictl pods -o json | jq -r '.items[] | select(.metadata.name == "alpine").id') |`,
38 | "jq .",
39 | ))
40 |
41 | d.Step(S(
42 | "The data from `crictl inspectp` is retrieved via a `PodSandboxStatusRequest`,",
43 | "which is continuously called by the kubelet during its synchronization loop.",
44 | "The sandbox seems ready, now the kubelet has to ensure that the image exists",
45 | "on the target node. This is done by a `PullImageRequest`",
46 | ), S(
47 | "sudo journalctl -u crio --since '5 minutes ago' | grep -P 'PullImage(Request|Response)'",
48 | ))
49 |
50 | d.Step(S(
51 | "It looks like that the image should be available on the node",
52 | ), S(
53 | "sudo crictl images -o yaml alpine",
54 | ))
55 |
56 | d.Step(S(
57 | "CRI-O can now create the container workload",
58 | ), S(
59 | "sudo journalctl -u crio --since '5 minutes ago' | grep -P 'CreateContainer(Request|Response)'",
60 | ))
61 |
62 | d.Step(S(
63 | "A container is not started by default. The kubelet will call a `StartContainerRequest`",
64 | "to CRI-O to start the workload",
65 | ), S(
66 | "sudo journalctl -u crio --since '5 minutes ago' | grep -P 'StartContainer(Request|Response)'",
67 | ))
68 |
69 | d.Step(S(
70 | "The kubelet continuously verifies that the workload is still running",
71 | "We can do this too, via `crictl ps` or `crictl inspect`",
72 | ), S(
73 | "sudo crictl inspect",
74 | `$(sudo crictl ps -o json | jq -r '.containers[] | select(.metadata.name == "alpine").id') |`,
75 | "jq .",
76 | ))
77 |
78 | d.Step(S(
79 | "Now since the container is running, we should be able to retrieve its logs",
80 | ), S(
81 | "kubectl logs alpine",
82 | ))
83 |
84 | d.Step(S(
85 | "The container logs are retrieved directly from the local log path",
86 | ), S(
87 | "sudo tail",
88 | "$(sudo crictl inspect",
89 | `$(sudo crictl ps -o json | jq -r '.containers[] | select(.metadata.name == "alpine").id') | jq -r .status.logPath)`,
90 | ))
91 |
92 | d.Step(S(
93 | "We can also exec the container and run another command in parallel",
94 | ), S(
95 | `kubectl exec alpine echo Hello World`,
96 | ))
97 |
98 | d.Step(S(
99 | "A `kubectl exec` results in an `ExecRequest` to CRI-O, initiated by the kubelet",
100 | ), S(
101 | "sudo journalctl -u crio --since '1 minutes ago' | grep Exec",
102 | ))
103 |
104 | d.Step(S(
105 | "The lifecycle of a kubernetes workload can also be examined by the kubelets events",
106 | ), S(
107 | "kubectl get events --field-selector=involvedObject.kind=Pod,involvedObject.name=alpine",
108 | ))
109 |
110 | d.Step(S(
111 | "If we delete the workload again, CRI-O takes care of removing the system resources",
112 | ), S(
113 | "kubectl delete pod alpine --now &&",
114 | "sudo journalctl -u crio --since '2 minute ago' | grep -oE '(Stop|Remove).*'",
115 | ))
116 |
117 | return d.Run(ctx)
118 | }
119 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/logging_live_reload.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | . "github.com/containers/Demos/cri-o/pkg/demo"
5 | "github.com/urfave/cli"
6 | )
7 |
8 | func Logging(ctx *cli.Context) error {
9 | EnsureInfoLogLevel()
10 |
11 | d := New(
12 | "Logging and configuration reload",
13 | "This demo shows how to configure CRI-O logging and",
14 | "reload the configuration during runtime",
15 | )
16 |
17 | d.Step(S(
18 | "The basic configuration file of CRI-O is available in",
19 | "/etc/crio/crio.conf",
20 | ), S(
21 | "head -11 /etc/crio/crio.conf",
22 | ))
23 |
24 | d.Step(S(
25 | "For example, the log level can be changed there too",
26 | ), S(
27 | "grep -B3 log_level /etc/crio/crio.conf",
28 | ))
29 |
30 | d.Step(S(
31 | "So we can set the `log_level` to a higher verbosity",
32 | ), S(
33 | `sudo sed -i -E 's/(log_level = )(.*)/\1"debug"/' /etc/crio/crio.conf &&`,
34 | "grep -B3 log_level /etc/crio/crio.conf",
35 | ))
36 |
37 | d.Step(S(
38 | "To reload CRI-O, we have to send a SIGHUP (hangup) to the process.",
39 | "This can be done via `systemctl reload` for your convenience.",
40 | ), S(
41 | "sudo systemctl reload crio",
42 | ))
43 |
44 | d.Step(S(
45 | "The logs indicate that the configuration has been reloaded correctly",
46 | ), S(
47 | "sudo journalctl -u crio --since '30 seconds ago' |",
48 | "grep -A3 reloading",
49 | ))
50 |
51 | d.Step(S(
52 | "CRI-O now logs every request and response in debug mode",
53 | ), S(
54 | `sudo journalctl -u crio --no-pager -n 5 | cut -c-130`,
55 | ))
56 |
57 | return d.Run(ctx)
58 | }
59 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/networking.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | . "github.com/containers/Demos/cri-o/pkg/demo"
5 | "github.com/urfave/cli"
6 | )
7 |
8 | func Networking(ctx *cli.Context) error {
9 | EnsureInfoLogLevel()
10 |
11 | d := New(
12 | "Networking",
13 | "This demo shows how the basic networking works in CRI-O",
14 | )
15 |
16 | d.Step(S(
17 | "If not configured, the default location for CRI-O to look for",
18 | "Container Networking Interface (CNI) configurations is `/etc/cni/net.d`.",
19 | "For example, a simple bridge interface definition could look like this",
20 | ), S(
21 | "jq . /etc/cni/net.d/10-crio-bridge.conf",
22 | ))
23 |
24 | d.Step(S(
25 | "CRI-O picks up the configuration with the highest priority",
26 | "and applies it to new pods.",
27 | ), S(
28 | "kubectl run --generator=run-pod/v1 --image=alpine alpine",
29 | "-- sh -c 'while true; do date; sleep 2; done' &&",
30 | "kubectl wait pod/alpine --for=condition=ready --timeout=2m",
31 | ))
32 |
33 | d.Step(S(
34 | "CRI-O tells the CNI plugin to allocate the IP address",
35 | ), S(
36 | "sudo journalctl -u crio --since '3 minutes ago' | grep -A1 'About to add CNI network'",
37 | ))
38 |
39 | d.Step(S(
40 | "We now can directly examine the IP addresses of the pod via `crictl`",
41 | ), S(
42 | "sudo crictl inspectp",
43 | `$(sudo crictl pods -o json | jq -r '.items[] | select(.metadata.name == "alpine").id') |`,
44 | "jq '.status | .network, .linux'",
45 | ))
46 |
47 | d.Step(S(
48 | "The namespace options for the `network` specify if the pod should access the hosts network",
49 | "For example, the API server runs with host network and got a corresponding IP assigned",
50 | ), S(
51 | "sudo crictl inspectp",
52 | `$(sudo crictl pods -o json | jq -r '.items[] |`,
53 | `select(.metadata.name == "kube-apiserver-'$(hostname)'" and .state == "SANDBOX_READY").id') |`,
54 | "jq '.status | .network, .linux'",
55 | ))
56 |
57 | d.Step(S(
58 | "If we delete the workload again, CRI-O takes care of removing the allocated IPs",
59 | ), S(
60 | "kubectl delete pod alpine --now &&",
61 | "sudo journalctl -u crio --since '3 minutes ago' | grep -A1 'Got pod network'",
62 | ))
63 |
64 | d.Step(S(
65 | "CRI-O manages the network namespace lifecycle only if the appropriate configuration",
66 | "option is set",
67 | ), S(
68 | "grep -B2 manage_network_ns_lifecycle /etc/crio/crio.conf",
69 | ))
70 |
71 | return d.Run(ctx)
72 | }
73 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/portforward.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | . "github.com/containers/Demos/cri-o/pkg/demo"
5 | "github.com/urfave/cli"
6 | )
7 |
8 | func PortForward(ctx *cli.Context) error {
9 | d := New(
10 | "Port Forwarding",
11 | "This demo shows how port forwaring works in CRI-O",
12 | )
13 |
14 | d.Step(S(
15 | "First, let’s create a workload which we want to access",
16 | "In our case an example nginx server",
17 | ), S(
18 | "kubectl run --generator=run-pod/v1 --image=nginx:1.17-alpine nginx &&",
19 | "kubectl wait pod/nginx --for=condition=ready --timeout=2m",
20 | ))
21 |
22 | d.Step(S(
23 | "Then, a port-forward can be done using kubectl",
24 | ), S(
25 | "kubectl port-forward pod/nginx 8888:80 &",
26 | ))
27 |
28 | d.Step(S(
29 | "Now we’re able to access the pod via localhost",
30 | ), S(
31 | "curl 127.0.0.1:8888",
32 | ))
33 |
34 | d.Step(S(
35 | "During port forward, CRI-O returns a streaming endpoint to the kubelet",
36 | ), S(
37 | "sudo journalctl -u crio --since '3 minutes ago' | grep -E '(PortForward(Request|Response)|socat).*'",
38 | ))
39 |
40 | d.Step(S(
41 | "It looks like that running socat inside the PID namespace is",
42 | "the way to achieve the port forward.",
43 | "This means we could use `socat` directly to access the web server",
44 | "after entering the PID namespace",
45 | ), S(
46 | `echo "GET /" |`,
47 | `sudo $(sudo journalctl -u crio --since '2 minute ago' |`,
48 | `sed -n -E 's;.*executing port forwarding command: (.*80).*;\1;p')`,
49 | ))
50 |
51 | return d.Run(ctx)
52 | }
53 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/pull_auth.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | "os"
5 |
6 | . "github.com/containers/Demos/cri-o/pkg/demo"
7 | "github.com/urfave/cli"
8 | )
9 |
10 | func PullAuth(ctx *cli.Context) error {
11 | Ensure(
12 | "sudo crictl rmi quay.io/crio/private-image",
13 | `sudo sed -i -E 's/(global_auth_file = )(.*)/\1""/' /etc/crio/crio.conf`,
14 | "sudo systemctl restart crio",
15 | )
16 |
17 | d := New(
18 | "Image Pull Authentication",
19 | "This demo shows how registry authentication works in CRI-O",
20 | "(Please be aware that this demo does not work if the credentials",
21 | "are not valid)",
22 | )
23 |
24 | d.Step(S(
25 | "With the default configuration, CRI-O is not able to pull private images",
26 | ), S(
27 | "sudo crictl -D pull quay.io/crio/private-image || true",
28 | ))
29 |
30 | d.Step(S(
31 | "But CRI-O is able to reuse the Docker authentication configuration as well",
32 | ), S(
33 | `sudo sed -i -E 's;(global_auth_file = )(.*);\1"`+os.Getenv("HOME")+
34 | `/.docker/config.json";' /etc/crio/crio.conf &&`,
35 | "grep -B2 global_auth_file /etc/crio/crio.conf",
36 | ))
37 |
38 | d.Step(S(
39 | "The `global_auth_file` configuration does not support live configuration yet.",
40 | "Which means that we have to restart CRI-O.",
41 | "This is totally safe, since CRI-O relies only on the state on disk.",
42 | ), S(
43 | "sudo systemctl restart crio",
44 | ))
45 |
46 | d.Step(S(
47 | "If the credentials inside this file are valid,",
48 | "then CRI-O can pull private images too",
49 | ), S(
50 | "sudo crictl pull quay.io/crio/private-image",
51 | ))
52 |
53 | d.Step(S(
54 | "We can see that the `containers/image` library takes care of the",
55 | "authentication. Kubernetes is not involved in the authentication",
56 | "at all in this demo",
57 | ), S(
58 | "sudo journalctl -u crio --since '1 minute ago' |",
59 | "grep -oP '(PullImageRequest|GET).*'",
60 | ))
61 |
62 | return d.Run(ctx)
63 | }
64 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/recovering.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | . "github.com/containers/Demos/cri-o/pkg/demo"
5 | "github.com/urfave/cli"
6 | )
7 |
8 | func Recovering(ctx *cli.Context) error {
9 | d := New(
10 | "Recovering Workloads",
11 | "This demo shows what happens if a workload unexpectedly stops",
12 | )
13 |
14 | d.Step(S(
15 | "Let’s start with a fresh nginx deployment",
16 | ), S(
17 | "kubectl create deployment --image=nginx:1.17-alpine nginx &&",
18 | "kubectl wait deploy/nginx --for=condition=available --timeout=2m",
19 | ))
20 |
21 | d.Step(S(
22 | "Now we kill the container’s nginx process",
23 | ), S(
24 | "sudo pkill -KILL nginx",
25 | ))
26 |
27 | d.Step(S(
28 | "Then, the container monitor `conmon` will notice that",
29 | "something bad happened and CRI-O removes the workload.",
30 | ), S(
31 | "sudo journalctl -u crio --since '30 seconds ago' | grep exited",
32 | ))
33 |
34 | d.Step(S(
35 | "The kubelet’s synchronization loop will notice that",
36 | "the workload does not exist any more and will re-schedule it",
37 | ), S(
38 | "sudo journalctl -u kubelet --since '2 minute ago' | grep -A1 ContainerDied",
39 | ))
40 |
41 | d.Step(S(
42 | "The kubelet’s synchronization loop will watch over all workloads.",
43 | "This means if we manually create a pod like this",
44 | ), S(
45 | `echo '{ "metadata": { "name": "test-sandbox", "namespace": "default" } }'`,
46 | "> /tmp/sandbox.json &&",
47 | "sudo crictl runp /tmp/sandbox.json",
48 | ))
49 |
50 | d.Step(S(
51 | "Then the kubelet will remove it again",
52 | ), S(
53 | "sudo journalctl -u kubelet --since '1 minute ago' | grep unwanted",
54 | ))
55 |
56 | return d.Run(ctx)
57 | }
58 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/registries.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | "io/ioutil"
5 |
6 | . "github.com/containers/Demos/cri-o/pkg/demo"
7 | "github.com/urfave/cli"
8 | )
9 |
10 | const r1 = `# An array of host[:port] registries to try when
11 | # pulling an unqualified image, in order.
12 | unqualified-search-registries = ["docker.io", "quay.io"]
13 |
14 | [[registry]]
15 | prefix = "localhost"
16 | location = "docker.io/library"
17 | blocked = false
18 | insecure = false
19 | `
20 |
21 | const (
22 | f = "registries.conf"
23 | r = "/etc/containers/" + f
24 | )
25 |
26 | func Registries(ctx *cli.Context) error {
27 | if err := ioutil.WriteFile(f, []byte(r1), 0o644); err != nil {
28 | return err
29 | }
30 | Ensure(
31 | "[ ! -f "+r+".bak ] && sudo mv "+r+" "+r+".bak",
32 | "sudo cp "+f+" "+r,
33 | "rm "+f,
34 | "sudo systemctl reload crio",
35 | )
36 |
37 | d := New(
38 | "Registry Configurations",
39 | "This demo shows how to configure registries with CRI-O",
40 | )
41 |
42 | d.Step(S(
43 | "CRI-O supports multiple registry configuration syntaxes.",
44 | "From now on we focus on the latest version, which comes with the",
45 | "highest set of features. The default configuration can be found",
46 | "at "+r,
47 | ), S(
48 | "grep -B2 unqualified-search-registries "+r,
49 | ))
50 |
51 | d.Step(S(
52 | "The `unqualified-search-registries` allows us to pull images without",
53 | "prepending a registry prefix",
54 | ), S(
55 | "sudo crictl -D pull hello-world",
56 | ))
57 |
58 | d.Step(S(
59 | "A single registry can be specified within a [[registry]] entry",
60 | ), S(
61 | `grep -A4 '^\[\[registry\]\]' `+r,
62 | ))
63 |
64 | d.Step(S(
65 | "We have been rewritten the docker library to localhost.",
66 | "Now it is possible to pull via localhost",
67 | ), S(
68 | "sudo crictl -D pull localhost/alpine",
69 | ))
70 |
71 | d.Step(S(
72 | "The logs indicate that the rewrite was successful",
73 | ), S(
74 | "sudo journalctl -u crio --since '1 minute ago' |",
75 | `grep -o "reference rewritten from 'localhost/alpine:latest'.*"`,
76 | ))
77 |
78 | return d.Run(ctx)
79 | }
80 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/registry_mirrors.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | "io/ioutil"
5 |
6 | . "github.com/containers/Demos/cri-o/pkg/demo"
7 | "github.com/urfave/cli"
8 | )
9 |
10 | const r2 = `unqualified-search-registries = ["docker.io"]
11 |
12 | [[registry]]
13 | location = "docker.io/library"
14 | mirror = [
15 | { location = "localhost/mirror-path" }, # doesnt work
16 | { location = "localhost:5000", insecure = true }, # should work
17 | ]
18 | `
19 |
20 | func RegistryMirrors(ctx *cli.Context) error {
21 | if err := ioutil.WriteFile(f, []byte(r2), 0o644); err != nil {
22 | return err
23 | }
24 | Ensure(
25 | "[ ! -f "+r+".bak ] && sudo mv "+r+" "+r+".bak",
26 | "sudo cp "+f+" "+r,
27 | "rm "+f,
28 | "sudo systemctl reload crio",
29 | )
30 |
31 | d := New(
32 | "Registry Mirrors",
33 | "This demo shows how to configure registries mirrors in CRI-O",
34 | )
35 |
36 | d.Step(S(
37 | "Registry mirrors are especially useful in air-gapped scenarios,",
38 | "where access to the internet is limited.",
39 | "A registry mirror can be configured like this",
40 | ), S(
41 | `grep -A5 '^\[\[registry\]\]' `+r,
42 | ))
43 |
44 | d.Step(S(
45 | "To let the mirror work, we would have to setup one",
46 | "For this we use podman to setup a local registry",
47 | ), S(
48 | "podman run --rm --name=registry -p 5000:5000 -d registry",
49 | ))
50 |
51 | d.Step(S(
52 | "Podman uses the same registry configuration as CRI-O",
53 | "So we can transfer our target image into the local registry",
54 | ), S(
55 | "podman pull hello-world &&",
56 | "podman tag hello-world localhost:5000/hello-world &&",
57 | "podman push --tls-verify=false localhost:5000/hello-world",
58 | ))
59 |
60 | d.Step(S(
61 | "If we now pull an image from docker.io, then we first lookup our",
62 | "configured mirrors.",
63 | ), S(
64 | "sudo crictl pull hello-world",
65 | ))
66 |
67 | d.Step(S(
68 | "The logs show us that the image got pulled successfully from the mirror",
69 | ), S(
70 | "sudo journalctl -u crio --since '1 minute ago' |",
71 | `grep -Po "(reference rewritten from|Trying to pull|Downloading|GET).*"`,
72 | ))
73 |
74 | return d.Run(ctx)
75 | }
76 |
--------------------------------------------------------------------------------
/cri-o/pkg/runs/storage.go:
--------------------------------------------------------------------------------
1 | package runs
2 |
3 | import (
4 | . "github.com/containers/Demos/cri-o/pkg/demo"
5 | "github.com/urfave/cli"
6 | )
7 |
8 | func Storage(ctx *cli.Context) error {
9 | d := New(
10 | "Container Storage",
11 | "This demo shows how container storage can be configured",
12 | )
13 |
14 | d.Step(S(
15 | "The containers storage configuration allows us fine granular",
16 | "storage adaptions, like changing the directories",
17 | ), S(
18 | `grep -A9 '^\[storage\]' /etc/containers/storage.conf`,
19 | ))
20 |
21 | d.Step(S(
22 | "We can also define mounts which should apply for every container",
23 | ), S(
24 | "echo $(pwd):/mnt | sudo tee /etc/containers/mounts.conf &&",
25 | "sudo systemctl restart crio",
26 | ))
27 |
28 | d.Step(S(
29 | "If we now run a container workload,",
30 | "the mount directory gets attached automatically",
31 | ), S(
32 | "kubectl run --generator=run-pod/v1 --image=alpine alpine",
33 | "-- sh -c 'while true; do ls -lah /mnt; sleep 2; done' &&",
34 | "kubectl wait pod/alpine --for=condition=ready --timeout=2m &&",
35 | "kubectl logs alpine",
36 | ))
37 |
38 | return d.Run(ctx)
39 | }
40 |
--------------------------------------------------------------------------------
/podman_cli/README.md:
--------------------------------------------------------------------------------
1 | # Demos - podman_cli
2 |
3 | ## Podman Command Demo Scripts
4 |
5 | This directory is the home of the Demo scripts for the Podman CLI commands.
6 | It is expected that these scripts will be used for demonstration purposes, and most
7 | specifically as links on the [commands.md](https://github.com/containers/libpod/blob/master/commands.md)
8 | file in the [libpod](https://github.com/containers/libpod) GitHub project. The scripts in this directory
9 | should be run and recorded using [asciinema](https://asciinema.org/). The casts from
10 | that recording should be captured and stored on the [podman.io](https://github.com/containers/podman.io) site under the [asciinema](https://github.com/containers/podman.io/tree/master/asciinema)
11 | top level directory. This page documents how the casts should be recorded and the
12 | files that need to be created or modified to display them.
13 |
14 | ### Script creation
15 |
16 | Create a script to be put into the [containers/Demos](https://github.com/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.
17 |
18 | Once you are satisfied with your script, do a standard Git add/commit/push cycle to create a PR for the script.
19 |
20 | ### VM setup
21 |
22 | Create a new Fedora Virtual Machine (vm) and `dnf -y install asciinema` to install asciinema.
23 | Install the latest Podman with `dnf -y install podman --enablerepo updates-testing`.
24 |
25 | 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.
26 |
27 | ### Demo recording
28 |
29 | Before running the script, start asciinema with `asciinema rec`. Then run your script making sure to
30 | pause long enough for each command so that a first time viewer can read all of the output.
31 |
32 | When your script has completed, turn off the recording with `d` `c`. Then copy the /tmp/*.cast file that was created by the recording to ./podman_{command}.cast
33 |
34 | ### Store cast in podman.io
35 |
36 | Create a PR in https://github.com/containers/podman.io
37 |
38 | 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.
39 |
40 | 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.
41 |
42 | Do a standard Git add/commit/push cycle to create a PR for these changes.
43 |
44 | ### Update commands.md in libpod
45 |
46 | After the PR's for the script and recording are merged, create a PR in [libpod](https://github.com/containers/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.
47 |
--------------------------------------------------------------------------------
/podman_cli/podman_images.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # podman_images.sh demo script.
4 | # This script will demonstrate at an introductory level
5 | # the use of the podman images command.
6 | # Podman must be installed prior to running this script.
7 |
8 |
9 | # Setting up some colors for helping read the demo output.
10 | # Comment out any of the below to turn off that color.
11 | bold=$(tput bold)
12 | cyan=$(tput setaf 6)
13 | reset=$(tput sgr0)
14 |
15 | read_color() {
16 | read -p "${bold}$1${reset}"
17 | }
18 |
19 | echo_color() {
20 | echo "${cyan}$1${reset}"
21 | }
22 |
23 | setup() {
24 | command -v podman >/dev/null
25 | if [ $? != 0 ]; then
26 | echo $0 requires the podman package to be installed
27 | exit 1
28 | fi
29 | clear
30 | }
31 |
32 | intro() {
33 | echo_color "\`podman images\` Demo"
34 | echo
35 | echo_color "Available at https://github.com/containers/Demos/podman_cli/podman_images.sh"
36 | echo
37 | }
38 |
39 | version() {
40 |
41 | echo_color "First check the Podman version"
42 | echo
43 | read_color "podman version"
44 | echo
45 | podman version
46 | echo
47 |
48 | echo
49 | read -p "Enter to continue"
50 | clear
51 | }
52 |
53 | podman_pull_images() {
54 | echo_color "Let's pull our very first container image"
55 | echo
56 | read_color "podman pull alpine"
57 | podman pull alpine
58 |
59 | echo
60 | echo_color "Let's look at the image"
61 | echo
62 | read_color "podman images"
63 | podman images
64 |
65 | echo
66 | echo_color "Let's pull a busybox and nginx container image"
67 | echo
68 | read_color "podman pull busybox"
69 | podman pull busybox
70 | echo
71 | read_color "podman pull nginx:latest"
72 | podman pull nginx:latest
73 |
74 | echo
75 | echo_color "Let's look at the images"
76 | echo
77 | read_color "podman images"
78 | podman images
79 |
80 | echo
81 | read -p "Enter to continue"
82 | clear
83 | }
84 |
85 |
86 | podman_from_dockerfile() {
87 |
88 | /bin/cat <<- "EOF" > ./Dockerfile.hello
89 | FROM alpine
90 | RUN apk add python3
91 | ADD HelloFromContainer.py /home
92 | WORKDIR HOME
93 | CMD ["python3","/home/HelloFromContainer.py"]
94 | EOF
95 | /bin/cat <<- "EOF" > ./HelloFromContainer.py
96 | #!/usr/bin/env python3
97 | #
98 | import sys
99 | def main(argv):
100 | for i in range(0,10):
101 | print ("Hello World from Container Land! Message # [%d]" % i)
102 | if __name__ == "__main__":
103 | main(sys.argv[1:])
104 | EOF
105 |
106 | echo
107 | echo_color "Create an image from a Dockerfile and run the container"
108 | echo_color "Let's first look at our Dockerfile"
109 | echo
110 | read_color "cat ./Dockerfile.hello"
111 | cat ./Dockerfile.hello
112 |
113 | echo
114 | echo_color "Let's look at our HelloFromContainer.py"
115 | echo
116 | read_color "cat ./HelloFromContainer.py"
117 | cat ./HelloFromContainer.py
118 |
119 | echo
120 | echo_color "Create the \"hello\" image from the Dockerfile"
121 | echo
122 | read_color "podman build -t hello -f ./Dockerfile.hello ."
123 | podman build -t hello -f ./Dockerfile.hello .
124 |
125 | echo
126 | echo_color "Run the container just to prove the container image is viable"
127 | echo
128 | read_color "podman run --name helloctr hello"
129 | podman run --name helloctr hello
130 |
131 | echo
132 | echo_color "Commit the helloctr to make a personal image named myhello"
133 | echo
134 | read_color "podman commit -q --author \"John Smith\" helloctr myhello"
135 | podman commit -q --author "John Smith" helloctr myhello
136 |
137 | echo
138 | echo_color "Let's look at the images"
139 | echo
140 | read_color "podman images"
141 | podman images
142 | }
143 |
144 | podman_images() {
145 | echo
146 | echo_color "Let's look at what else the images command can do"
147 | echo
148 | echo_color "Show only the image ID's"
149 | echo
150 | read_color "podman images -q"
151 | podman images -q
152 |
153 | echo
154 | echo_color "Show the busybox image"
155 | echo
156 | read_color "podman images busybox"
157 | podman images busybox
158 |
159 | echo
160 | echo_color "Show the images without a table heading"
161 | echo
162 | read_color "podman images --noheading"
163 | podman images --noheading
164 |
165 | echo
166 | echo_color "Show the images without truncating any fields"
167 | echo
168 | read_color "podman images --no-trunc"
169 | podman images --no-trunc
170 |
171 | echo
172 | echo_color "Show the image digests"
173 | echo
174 | read_color "podman images --digests"
175 | podman images --digests
176 |
177 | echo
178 | echo_color "Show only the ID, Repository and Tag fields"
179 | echo
180 | read_color "podman images --format \"table {{.ID}} {{.Repository}} {{.Tag}}\""
181 | podman images --format "table {{.ID}} {{.Repository}} {{.Tag}}"
182 |
183 | echo
184 | echo_color "Show in json format"
185 | echo
186 | read_color "podman images --format json"
187 | podman images --format json
188 |
189 | echo
190 | echo_color "Show only the alpine image using a filter"
191 | echo
192 | read_color "podman images --filter reference=alpine"
193 | podman images --filter reference=alpine
194 |
195 | echo
196 | echo_color "Show the images sorted by size"
197 | echo
198 | read_color "podman images --sort size"
199 | podman images --sort size
200 |
201 |
202 | echo
203 | read -p "Enter to continue"
204 | clear
205 | }
206 |
207 | clean_images_and_containers() {
208 |
209 | echo
210 | echo_color "Time to clean up!"
211 | read_color "podman rm -a -f"
212 | podman rm -a -f
213 | echo
214 | read_color "podman rmi -a -f"
215 | podman rmi -a -f
216 |
217 | echo
218 | read -p "Enter to continue"
219 | clear
220 | }
221 |
222 | clean_temp_files() {
223 |
224 | rm -rf Dockerfile.hello HelloFromContainer.py
225 | }
226 |
227 | setup
228 |
229 | intro
230 |
231 | version
232 |
233 | podman_pull_images
234 |
235 | podman_from_dockerfile
236 |
237 | podman_images
238 |
239 | clean_images_and_containers
240 |
241 | clean_temp_files
242 |
243 | read -p "End of Demo!!!"
244 | echo
245 | echo "Thank you!"
246 |
--------------------------------------------------------------------------------
/podman_cli/podman_inspect.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # podman_inspect.sh demo script.
4 | # This script will demonstrate at an introductory level
5 | # the use of the podman inspect command.
6 | # Podman must be installed prior to running this script.
7 |
8 |
9 | # Setting up some colors for helping read the demo output.
10 | # Comment out any of the below to turn off that color.
11 | bold=$(tput bold)
12 | cyan=$(tput setaf 6)
13 | reset=$(tput sgr0)
14 |
15 | read_color() {
16 | read -p "${bold}$1${reset}"
17 | }
18 |
19 | echo_color() {
20 | echo "${cyan}$1${reset}"
21 | }
22 |
23 | setup() {
24 | command -v podman >/dev/null
25 | if [ $? != 0 ]; then
26 | echo $0 requires the podman package to be installed
27 | exit 1
28 | fi
29 | clear
30 | }
31 |
32 | intro() {
33 | echo_color "\`podman inspect\` Demo"
34 | echo
35 | echo_color "Available at https://github.com/containers/Demos/podman_cli/podman_inspect.sh"
36 | echo
37 | }
38 |
39 | version() {
40 |
41 | echo_color "First check the Podman version"
42 | echo
43 | read_color "podman version"
44 | echo
45 | podman version
46 | echo
47 |
48 | echo
49 | read -p "Enter to continue"
50 | clear
51 | }
52 |
53 | podman_pull_images() {
54 | echo_color "Let's pull our container image"
55 | echo
56 | read_color "podman pull alpine"
57 | podman pull alpine
58 |
59 | echo
60 | echo_color "Let's look at the image"
61 | echo
62 | read_color "podman images"
63 | podman images
64 |
65 | echo
66 | read -p "Enter to continue"
67 | clear
68 | }
69 |
70 | podman_inspect() {
71 | echo
72 | echo_color "Let's look at what the inspect command can do"
73 | echo
74 | echo_color "Inspect the alpine image"
75 | echo
76 | read_color "podman inspect -t image alpine | less"
77 | podman inspect -t image alpine | less
78 |
79 | echo
80 | echo_color "Let's create a container to inspect"
81 | echo
82 | read_color "podman run --name=myctr alpine ls /etc/network"
83 | podman run --name=myctr alpine ls /etc/network
84 |
85 | echo
86 | echo_color "Now inspect our container"
87 | echo
88 | read_color "podman inspect -t container myctr | less"
89 | podman inspect -t container myctr | less
90 |
91 | echo
92 | echo_color "Inspect our latest container"
93 | echo
94 | read_color "podman inspect --latest | less"
95 | podman inspect --latest | less
96 |
97 | echo
98 | echo_color "Look at the containers ImageName"
99 | echo
100 | read_color "podman inspect -t container --format \"imagename: {{.ImageName}}\" myctr"
101 | podman inspect -t container --format "imagename: {{.ImageName}}" myctr
102 |
103 | echo
104 | echo_color "Look at the containers GraphDriver.Name"
105 | echo
106 | read_color "podman inspect -t container --format \"table {{.GraphDriver.Name}}\" myctr"
107 | podman inspect -t container --format "graphdriver: {{.GraphDriver.Name}}" myctr
108 |
109 | echo
110 | echo_color "Look at the image size using format"
111 | echo
112 | read_color "podman inspect -t image --format \"size: {{.Size}}\" alpine"
113 | podman inspect -t image --format "size: {{.Size}}" alpine
114 |
115 | echo
116 | read -p "Enter to continue"
117 | clear
118 | }
119 |
120 | clean_images_and_containers() {
121 |
122 | echo
123 | echo_color "Time to clean up!"
124 | read_color "podman rm -a -f"
125 | podman rm -a -f
126 | echo
127 | read_color "podman rmi -a -f"
128 | podman rmi -a -f
129 |
130 | echo
131 | read -p "Enter to continue"
132 | clear
133 | }
134 |
135 | setup
136 |
137 | intro
138 |
139 | version
140 |
141 | podman_pull_images
142 |
143 | podman_inspect
144 |
145 | clean_images_and_containers
146 |
147 | read -p "End of Demo!!!"
148 | echo
149 | echo "Thank you!"
150 |
--------------------------------------------------------------------------------
/podman_cli/podman_pause_unpause.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # podman_pause_unpause.sh demo script.
4 | # This script will demonstrate at an introductory level
5 | # the use of the podman pause and unpause commands.
6 | # Podman must be installed prior to running this script.
7 |
8 |
9 | # Setting up some colors for helping read the demo output.
10 | # Comment out any of the below to turn off that color.
11 | bold=$(tput bold)
12 | cyan=$(tput setaf 6)
13 | reset=$(tput sgr0)
14 |
15 | read_color() {
16 | read -p "${bold}$1${reset}"
17 | }
18 |
19 | echo_color() {
20 | echo "${cyan}$1${reset}"
21 | }
22 |
23 | setup() {
24 | command -v podman >/dev/null
25 | if [ $? != 0 ]; then
26 | echo $0 requires the podman package to be installed
27 | exit 1
28 | fi
29 | clear
30 | }
31 |
32 | intro() {
33 | echo_color "\`podman pause\` Demo"
34 | echo
35 | echo_color "Available at https://github.com/containers/Demos/podman_cli/podman_pause.sh"
36 | echo
37 | }
38 |
39 | version() {
40 |
41 | echo_color "First check the Podman version"
42 | echo
43 | read_color "podman version"
44 | echo
45 | podman version
46 | echo
47 |
48 | echo
49 | read -p "Enter to continue"
50 | clear
51 | }
52 |
53 | podman_pull_images() {
54 | echo_color "Let's pull the alpine image"
55 | echo
56 | read_color "podman pull alpine"
57 | podman pull alpine
58 |
59 | echo
60 | echo_color "Let's pull the busybox image"
61 | echo
62 | read_color "podman pull busybox"
63 | podman pull busybox
64 |
65 | echo
66 | echo_color "Let's look at the images"
67 | echo
68 | read_color "podman images"
69 | podman images
70 |
71 | echo
72 | read -p "Enter to continue"
73 | clear
74 | }
75 |
76 | podman_do_pause_demo() {
77 |
78 | echo_color "Let's create and run an alpine container for 10 minutes."
79 | echo
80 | read_color "podman run --detach --name alpinectr alpine sh -c 'while true ;do sleep 600 ; done'"
81 | podman run --detach --name alpinectr alpine sh -c 'while true ;do sleep 600 ; done'
82 |
83 | echo
84 | echo_color "Let's create and run a busybox container for 10 minutes."
85 | echo
86 | read_color "podman run --detach --name busyboxctr busybox sh -c 'while true ;do sleep 600 ; done'"
87 | podman run --detach --name busyboxctr busybox sh -c 'while true ;do sleep 600 ; done'
88 |
89 | echo
90 | echo_color "Let's look at the containers"
91 | echo
92 | read_color "podman ps --all"
93 | podman ps --all
94 |
95 | echo
96 | echo_color "Let's pause the busyboxctr. This will cause runc to suspend all of the"
97 | echo_color "processes associated with the container."
98 | echo
99 | read_color "podman pause busyboxctr"
100 | podman pause busyboxctr
101 |
102 | echo
103 | echo_color "Let's look at the containers, busyboxctr should show 'Paused' now."
104 | echo
105 | read_color "podman ps --all"
106 | podman ps --all
107 |
108 | echo
109 | echo_color "Let's pause the alpinectr. This will cause runc to suspend all of the"
110 | echo_color "processes associated with the container."
111 | echo
112 | read_color "podman pause alpinectr"
113 | podman pause alpinectr
114 |
115 | echo
116 | echo_color "Let's look at the containers, busyboxctr and alpinectr should both "
117 | echo_color "show 'Paused' now."
118 | echo
119 | read_color "podman ps --all"
120 | podman ps --all
121 |
122 | }
123 |
124 | podman_do_unpause_demo() {
125 |
126 | echo
127 | echo_color "Now let's use the 'podman unpause' command to unpause the containers."
128 | echo
129 | read_color "podman unpause --help"
130 | podman unpause --help
131 |
132 | echo
133 | echo_color "Let's unpause the busyboxctr. This will cause runc to unsuspend all of the"
134 | echo_color "processes associated with the container."
135 | echo
136 | read_color "podman unpause busyboxctr"
137 | podman unpause busyboxctr
138 |
139 | echo
140 | echo_color "Let's look at the containers, busyboxctr should show 'Up' now."
141 | echo
142 | read_color "podman ps --all"
143 | podman ps --all
144 |
145 | echo
146 | echo_color "Let's unpause the alpinectr. This will cause runc to unsuspend all of the"
147 | echo_color "processes associated with the container."
148 | echo
149 | read_color "podman unpause alpinectr"
150 | podman unpause alpinectr
151 |
152 | echo
153 | echo_color "Let's look at the containers, busyboxctr and alpinectr should both "
154 | echo_color "show 'Up' now."
155 | echo
156 | read_color "podman ps --all"
157 | podman ps --all
158 |
159 | }
160 |
161 | clean_images_and_containers() {
162 |
163 | echo
164 | echo_color "Time to clean up!"
165 | read_color "podman rm --all --force"
166 | podman rm --all --force
167 | echo
168 | read_color "podman rmi --all --force"
169 | podman rmi --all --force
170 |
171 | echo
172 | read -p "Enter to continue"
173 | }
174 |
175 | setup
176 |
177 | intro
178 |
179 | version
180 |
181 | podman_pull_images
182 |
183 | podman_do_pause_demo
184 |
185 | podman_do_unpause_demo
186 |
187 | clean_images_and_containers
188 |
189 | read -p "End of Demo!!!"
190 | echo
191 | echo "Thank you!"
192 |
--------------------------------------------------------------------------------
/podman_go_bindings/README.md:
--------------------------------------------------------------------------------
1 | # Demos - podman_Go_bindings
2 |
3 | ## Sample Application for Podman Go Bindings
4 |
5 | This directory contains a sample application to run Podman operations in
6 | external applications via a set of Go bindings.
7 |
8 | There's a single Go file, which uses the Podman Go bindings to run the
9 | following operations:
10 |
11 | 0. Pull Image
12 | 1. List Images
13 | 2. Start Container
14 | 3. List Containers
15 | 4. Inspect Container
16 | 5. Stop Container
17 |
18 | ### Running the application
19 |
20 | 0. Clone the repo and enter the podman_go_bindings directory.
21 | ```bash
22 | $ git clone https://github.com/containers/Demos.git
23 | $ cd Demos/podman_go_bindings
24 | ```
25 |
26 | 1. Download the [required packages](https://podman.io/getting-started/installation#build-and-run-dependencies) to build from source.
27 |
28 | 2. Ensure podman.socket is activated
29 | ```bash
30 | systemctl --user start podman.socket
31 | ```
32 |
33 | 3. Run the application
34 | ```bash
35 | $ go run main.go
36 | ```
37 |
38 | ### More Information
39 |
40 | Please see the [`README`](https://github.com/containers/podman/tree/main/pkg/bindings#podman-golang-bindings) in the Podman bindings package for more documentation.
--------------------------------------------------------------------------------
/podman_go_bindings/go.mod:
--------------------------------------------------------------------------------
1 | module github.com/containers/Demos/podman_go_bindings
2 |
3 | go 1.21
4 |
5 | toolchain go1.22.1
6 |
7 | require github.com/containers/podman/v5 v5.1.1
8 |
9 | require (
10 | dario.cat/mergo v1.0.0 // indirect
11 | github.com/Azure/go-ansiterm v0.0.0-20230124172434-306776ec8161 // indirect
12 | github.com/BurntSushi/toml v1.3.2 // indirect
13 | github.com/Microsoft/go-winio v0.6.2 // indirect
14 | github.com/Microsoft/hcsshim v0.12.3 // indirect
15 | github.com/VividCortex/ewma v1.2.0 // indirect
16 | github.com/acarl005/stripansi v0.0.0-20180116102854-5a71ef0e047d // indirect
17 | github.com/asaskevich/govalidator v0.0.0-20230301143203-a9d515a09cc2 // indirect
18 | github.com/blang/semver/v4 v4.0.0 // indirect
19 | github.com/chzyer/readline v1.5.1 // indirect
20 | github.com/cilium/ebpf v0.11.0 // indirect
21 | github.com/containerd/cgroups/v3 v3.0.3 // indirect
22 | github.com/containerd/containerd v1.7.17 // indirect
23 | github.com/containerd/errdefs v0.1.0 // indirect
24 | github.com/containerd/log v0.1.0 // indirect
25 | github.com/containerd/stargz-snapshotter/estargz v0.15.1 // indirect
26 | github.com/containers/buildah v1.36.0 // indirect
27 | github.com/containers/common v0.59.1 // indirect
28 | github.com/containers/image/v5 v5.31.0 // indirect
29 | github.com/containers/libtrust v0.0.0-20230121012942-c1716e8a8d01 // indirect
30 | github.com/containers/ocicrypt v1.1.10 // indirect
31 | github.com/containers/psgo v1.9.0 // indirect
32 | github.com/containers/storage v1.54.0 // indirect
33 | github.com/coreos/go-systemd/v22 v22.5.1-0.20231103132048-7d375ecc2b09 // indirect
34 | github.com/cyberphone/json-canonicalization v0.0.0-20231217050601-ba74d44ecf5f // indirect
35 | github.com/cyphar/filepath-securejoin v0.2.5 // indirect
36 | github.com/disiqueira/gotree/v3 v3.0.2 // indirect
37 | github.com/distribution/reference v0.6.0 // indirect
38 | github.com/docker/distribution v2.8.3+incompatible // indirect
39 | github.com/docker/docker v26.1.4+incompatible // indirect
40 | github.com/docker/docker-credential-helpers v0.8.1 // indirect
41 | github.com/docker/go-connections v0.5.0 // indirect
42 | github.com/docker/go-units v0.5.0 // indirect
43 | github.com/felixge/httpsnoop v1.0.4 // indirect
44 | github.com/fsnotify/fsnotify v1.7.0 // indirect
45 | github.com/go-jose/go-jose/v3 v3.0.3 // indirect
46 | github.com/go-logr/logr v1.4.1 // indirect
47 | github.com/go-logr/stdr v1.2.2 // indirect
48 | github.com/go-openapi/analysis v0.23.0 // indirect
49 | github.com/go-openapi/errors v0.22.0 // indirect
50 | github.com/go-openapi/jsonpointer v0.21.0 // indirect
51 | github.com/go-openapi/jsonreference v0.21.0 // indirect
52 | github.com/go-openapi/loads v0.22.0 // indirect
53 | github.com/go-openapi/runtime v0.28.0 // indirect
54 | github.com/go-openapi/spec v0.21.0 // indirect
55 | github.com/go-openapi/strfmt v0.23.0 // indirect
56 | github.com/go-openapi/swag v0.23.0 // indirect
57 | github.com/go-openapi/validate v0.24.0 // indirect
58 | github.com/godbus/dbus/v5 v5.1.1-0.20230522191255-76236955d466 // indirect
59 | github.com/gogo/protobuf v1.3.2 // indirect
60 | github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
61 | github.com/golang/protobuf v1.5.4 // indirect
62 | github.com/google/go-containerregistry v0.19.1 // indirect
63 | github.com/google/go-intervals v0.0.2 // indirect
64 | github.com/google/uuid v1.6.0 // indirect
65 | github.com/gorilla/mux v1.8.1 // indirect
66 | github.com/gorilla/schema v1.4.1 // indirect
67 | github.com/hashicorp/errwrap v1.1.0 // indirect
68 | github.com/hashicorp/go-multierror v1.1.1 // indirect
69 | github.com/jinzhu/copier v0.4.0 // indirect
70 | github.com/josharian/intern v1.0.0 // indirect
71 | github.com/json-iterator/go v1.1.12 // indirect
72 | github.com/klauspost/compress v1.17.8 // indirect
73 | github.com/klauspost/pgzip v1.2.6 // indirect
74 | github.com/kr/fs v0.1.0 // indirect
75 | github.com/letsencrypt/boulder v0.0.0-20230907030200-6d76a0f91e1e // indirect
76 | github.com/mailru/easyjson v0.7.7 // indirect
77 | github.com/manifoldco/promptui v0.9.0 // indirect
78 | github.com/mattn/go-runewidth v0.0.15 // indirect
79 | github.com/mattn/go-sqlite3 v1.14.22 // indirect
80 | github.com/miekg/pkcs11 v1.1.1 // indirect
81 | github.com/mistifyio/go-zfs/v3 v3.0.1 // indirect
82 | github.com/mitchellh/mapstructure v1.5.0 // indirect
83 | github.com/moby/docker-image-spec v1.3.1 // indirect
84 | github.com/moby/sys/mountinfo v0.7.1 // indirect
85 | github.com/moby/sys/user v0.1.0 // indirect
86 | github.com/moby/term v0.5.0 // indirect
87 | github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
88 | github.com/modern-go/reflect2 v1.0.2 // indirect
89 | github.com/morikuni/aec v1.0.0 // indirect
90 | github.com/nxadm/tail v1.4.11 // indirect
91 | github.com/oklog/ulid v1.3.1 // indirect
92 | github.com/opencontainers/go-digest v1.0.0 // indirect
93 | github.com/opencontainers/image-spec v1.1.0 // indirect
94 | github.com/opencontainers/runc v1.1.14 // indirect
95 | github.com/opencontainers/runtime-spec v1.2.0 // indirect
96 | github.com/opencontainers/runtime-tools v0.9.1-0.20230914150019-408c51e934dc // indirect
97 | github.com/opencontainers/selinux v1.11.0 // indirect
98 | github.com/ostreedev/ostree-go v0.0.0-20210805093236-719684c64e4f // indirect
99 | github.com/pkg/errors v0.9.1 // indirect
100 | github.com/pkg/sftp v1.13.6 // indirect
101 | github.com/proglottis/gpgme v0.1.3 // indirect
102 | github.com/rivo/uniseg v0.4.7 // indirect
103 | github.com/secure-systems-lab/go-securesystemslib v0.8.0 // indirect
104 | github.com/sigstore/fulcio v1.4.5 // indirect
105 | github.com/sigstore/rekor v1.3.6 // indirect
106 | github.com/sigstore/sigstore v1.8.3 // indirect
107 | github.com/sirupsen/logrus v1.9.3 // indirect
108 | github.com/spf13/pflag v1.0.5 // indirect
109 | github.com/stefanberger/go-pkcs11uri v0.0.0-20230803200340-78284954bff6 // indirect
110 | github.com/sylabs/sif/v2 v2.16.0 // indirect
111 | github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635 // indirect
112 | github.com/tchap/go-patricia/v2 v2.3.1 // indirect
113 | github.com/titanous/rocacheck v0.0.0-20171023193734-afe73141d399 // indirect
114 | github.com/ulikunitz/xz v0.5.12 // indirect
115 | github.com/vbatts/tar-split v0.11.5 // indirect
116 | github.com/vbauerster/mpb/v8 v8.7.3 // indirect
117 | go.mongodb.org/mongo-driver v1.14.0 // indirect
118 | go.mozilla.org/pkcs7 v0.0.0-20210826202110-33d05740a352 // indirect
119 | go.opencensus.io v0.24.0 // indirect
120 | go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.49.0 // indirect
121 | go.opentelemetry.io/otel v1.24.0 // indirect
122 | go.opentelemetry.io/otel/metric v1.24.0 // indirect
123 | go.opentelemetry.io/otel/trace v1.24.0 // indirect
124 | golang.org/x/crypto v0.31.0 // indirect
125 | golang.org/x/exp v0.0.0-20240506185415-9bf2ced13842 // indirect
126 | golang.org/x/net v0.25.0 // indirect
127 | golang.org/x/sync v0.10.0 // indirect
128 | golang.org/x/sys v0.28.0 // indirect
129 | golang.org/x/term v0.27.0 // indirect
130 | golang.org/x/text v0.21.0 // indirect
131 | golang.org/x/time v0.5.0 // indirect
132 | google.golang.org/genproto/googleapis/rpc v0.0.0-20240318140521-94a12d6c2237 // indirect
133 | google.golang.org/grpc v1.62.1 // indirect
134 | google.golang.org/protobuf v1.34.1 // indirect
135 | gopkg.in/go-jose/go-jose.v2 v2.6.3 // indirect
136 | gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect
137 | gopkg.in/yaml.v3 v3.0.1 // indirect
138 | sigs.k8s.io/yaml v1.4.0 // indirect
139 | tags.cncf.io/container-device-interface v0.7.2 // indirect
140 | )
141 |
--------------------------------------------------------------------------------
/podman_go_bindings/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "os"
7 |
8 | "github.com/containers/podman/v5/libpod/define"
9 | "github.com/containers/podman/v5/pkg/bindings"
10 | "github.com/containers/podman/v5/pkg/bindings/containers"
11 | "github.com/containers/podman/v5/pkg/bindings/images"
12 | "github.com/containers/podman/v5/pkg/specgen"
13 | )
14 |
15 | func ptr[T any](t T) *T {
16 | return &t
17 | }
18 |
19 | func main() {
20 | fmt.Println("Welcome to the Podman Go bindings tutorial")
21 |
22 | // Get Podman socket location
23 | sock_dir := os.Getenv("XDG_RUNTIME_DIR")
24 | if sock_dir == "" {
25 | sock_dir = "/var/run"
26 | }
27 | socket := "unix:" + sock_dir + "/podman/podman.sock"
28 |
29 | // Connect to Podman socket
30 | ctx, err := bindings.NewConnection(context.Background(), socket)
31 | if err != nil {
32 | fmt.Println(err)
33 | os.Exit(1)
34 | }
35 |
36 | // Pull Busybox image (Sample 1)
37 | fmt.Println("Pulling Busybox image...")
38 | _, err = images.Pull(ctx, "docker.io/busybox", &images.PullOptions{})
39 | if err != nil {
40 | fmt.Println(err)
41 | os.Exit(1)
42 | }
43 |
44 | // Pull Fedora image (Sample 2)
45 | rawImage := "registry.fedoraproject.org/fedora:latest"
46 | fmt.Println("Pulling Fedora image...")
47 | _, err = images.Pull(ctx, rawImage, &images.PullOptions{})
48 | if err != nil {
49 | fmt.Println(err)
50 | os.Exit(1)
51 | }
52 |
53 | // List images
54 | imageSummary, err := images.List(ctx, &images.ListOptions{})
55 | if err != nil {
56 | fmt.Println(err)
57 | os.Exit(1)
58 | }
59 | var names []string
60 | for _, i := range imageSummary {
61 | names = append(names, i.RepoTags...)
62 | }
63 | fmt.Println("Listing images...")
64 | fmt.Println(names)
65 |
66 | // Container create
67 | s := specgen.NewSpecGenerator(rawImage, false)
68 | s.Terminal = ptr(true)
69 | r, err := containers.CreateWithSpec(ctx, s, &containers.CreateOptions{})
70 | if err != nil {
71 | fmt.Println(err)
72 | os.Exit(1)
73 | }
74 |
75 | // Container start
76 | fmt.Println("Starting Fedora container...")
77 | err = containers.Start(ctx, r.ID, &containers.StartOptions{})
78 | if err != nil {
79 | fmt.Println(err)
80 | os.Exit(1)
81 | }
82 |
83 | _, err = containers.Wait(ctx, r.ID, &containers.WaitOptions{
84 | Condition: []define.ContainerStatus{define.ContainerStateRunning},
85 | })
86 | if err != nil {
87 | fmt.Println(err)
88 | os.Exit(1)
89 | }
90 |
91 | // Container list
92 | var latestContainers = 1
93 | containerLatestList, err := containers.List(ctx, &containers.ListOptions{
94 | Last: &latestContainers,
95 | })
96 | if err != nil {
97 | fmt.Println(err)
98 | os.Exit(1)
99 | }
100 | fmt.Printf("Latest container is %s\n", containerLatestList[0].Names[0])
101 |
102 | // Container inspect
103 | ctrData, err := containers.Inspect(ctx, r.ID, &containers.InspectOptions{})
104 | if err != nil {
105 | fmt.Println(err)
106 | os.Exit(1)
107 | }
108 | fmt.Printf("Container uses image %s\n", ctrData.ImageName)
109 | fmt.Printf("Container running status is %s\n", ctrData.State.Status)
110 |
111 | // Container stop
112 | fmt.Println("Stopping the container...")
113 | err = containers.Stop(ctx, r.ID, &containers.StopOptions{})
114 | if err != nil {
115 | fmt.Println(err)
116 | os.Exit(1)
117 | }
118 | ctrData, err = containers.Inspect(ctx, r.ID, &containers.InspectOptions{})
119 | if err != nil {
120 | fmt.Println(err)
121 | os.Exit(1)
122 | }
123 | fmt.Printf("Container running status is now %s\n", ctrData.State.Status)
124 | return
125 |
126 | }
127 |
--------------------------------------------------------------------------------
/qm/devconf/README.md:
--------------------------------------------------------------------------------
1 | # Driving Simulation and Service Monitoring
2 |
3 | This demo is a driving simulation application that combines video playback with
4 | real-time service status monitoring.
5 | It leverages modern open-source projects such as
6 | [Podman](https://github.com/containers/podman)
7 | [Systemd](https://github.com/systemd/systemd)
8 | [QM](https://github.com/containers/qm)
9 | [Bluechi](https://github.com/containers/bluechi)
10 |
11 | The application uses Pygame for video display, OpenCV for video processing
12 | and system commands to check service statuses.
13 |
14 | ## Requirements
15 |
16 | Install the following packages
17 |
18 | ```bash
19 | pip install pygame opencv-python click
20 | ```
21 |
22 | ## Setup VM for Containers
23 |
24 | First, you need to create a virtual machine (VM) to run HOST partition and
25 | QM partitions as isolated files systems. After setting up the VM, configure
26 | SSH access without a password. This can be achieved by generating SSH keys
27 | on your local machine and copying the public key to the VM's `authorized_keys`
28 | file.
29 |
30 | ## Usage
31 |
32 | 1. Ensure your driving video file is available in mp4 format.
33 |
34 | 2. The IP host must contain two partitions:
35 | `host`: Runs critical processes such as tires, safety,
36 | brakes, and cruise control.
37 | `QM`: Runs QM non critical services such as radio, maps, store
38 | and stream audio (which are isolated under /usr/lib/qm/rootfs/
39 | file systed with its own system).
40 | How to setup the QM environment? It's possible to use
41 | [qm setup](https://github.com/containers/qm/blob/main/demos/devconf-2024/setup)
42 | inside VM.
43 |
44 | 3. Run the application with the IP address of the server where the services are
45 | running and the path to the video file:
46 |
47 | ```bash
48 | ./driving-displaying-host-qm-status
49 | --ip IP_VM_RUNNING_BLUECHI_AND_QM_CONTAINERS
50 | --port VM_SSH_PORT_FORWARD
51 | --video .video_car_driving.mp4
52 | ```
53 |
54 | 4. On a different terminal use bluechictl stop, start, restart HOST/QM services
55 | in the NODE and QM partitions the messages popup in the video while driving
56 | like a real agent.
57 |
58 | You could also run load tests and check the status in video indicators
59 |
--------------------------------------------------------------------------------
/qm/devconf/driving-displaying-host-qm-status/.driving.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/containers/Demos/eb287284f7666c730d613f7b68b7bd356a71fc37/qm/devconf/driving-displaying-host-qm-status/.driving.mp4
--------------------------------------------------------------------------------
/qm/devconf/driving-displaying-host-qm-status/driving-displaying-host-qm-status:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 |
3 | # Licensed under the Apache License, Version 2.0 (the "License");
4 | # you may not use this file except in compliance with the License.
5 | # You may obtain a copy of the License at
6 | #
7 | # http://www.apache.org/licenses/LICENSE-2.0
8 | #
9 | # Unless required by applicable law or agreed to in writing, software
10 | # distributed under the License is distributed on an "AS IS" BASIS,
11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 | # See the License for the specific language governing permissions and
13 | # limitations under the License.
14 |
15 | # flake8: noqa: E501
16 |
17 | import os
18 | import subprocess
19 | import threading
20 | import time
21 |
22 | import click
23 | import cv2
24 | import pygame
25 |
26 |
27 | class ServiceStatusChecker:
28 | """
29 | Periodically checks the status of a service and updates its active state in a shared data structure.
30 |
31 | Attributes:
32 | interval (int): How often to check the service status, in seconds.
33 | item_label (str): Label of the legend item linked to the service.
34 | service_name (str): Name of the service to check.
35 | service_type (str): Type of the service (e.g., "HOST" or "QM").
36 | legend_items (list): List containing the service legend items.
37 | ip_address (str): IP address to connect to for checking service status.
38 | ssh_port (str): SSH port forward.
39 | """
40 | def __init__(self, interval, item_label, service_name, service_type, legend_items, ip_address, ssh_port):
41 | self.interval = interval
42 | self.item_label = item_label
43 | self.service_name = service_name
44 | self.service_type = service_type
45 | self.legend_items = legend_items
46 | self.ip_address = ip_address
47 | self.ssh_port = ssh_port
48 | self.thread = threading.Thread(target=self.check_service_status_periodically)
49 | self.thread.daemon = True
50 | self.thread.start()
51 |
52 | def check_service_status(self):
53 | """Executes the system command to check service status based on service_type and parses the output."""
54 | if self.service_type == "HOST":
55 | result = subprocess.run(['ssh', f'root@{self.ip_address}',f'-p {self.ssh_port}' , '-oStrictHostKeyChecking=no', '-oUserKnownHostsFile=/dev/null', 'systemctl', 'is-active', self.service_name], capture_output=True, text=True)
56 | elif self.service_type == "QM":
57 | result = subprocess.run(['ssh', f'root@{self.ip_address}', f'-p {self.ssh_port}' , '-oStrictHostKeyChecking=no', '-oUserKnownHostsFile=/dev/null', 'podman', 'exec', '-it', 'qm', 'systemctl', 'is-active', self.service_name], capture_output=True, text=True)
58 | else:
59 | return None
60 | return 'active' in result.stdout
61 |
62 | def check_service_status_periodically(self):
63 | """Continuously checks service status at intervals, updating the legend items as needed."""
64 | while True:
65 | active_status = self.check_service_status()
66 | for item in self.legend_items:
67 | if item['label'] == self.item_label:
68 | item["active"] = not active_status
69 | time.sleep(self.interval)
70 |
71 | class VideoPlayer:
72 | """
73 | Manages video playback using OpenCV and Pygame for displaying the video on a window.
74 |
75 | Attributes:
76 | video_path (str): Path to the video file.
77 | screen_size (tuple): The resolution of the window as a tuple (width, height).
78 | """
79 | def __init__(self, video_path, screen_size):
80 | pygame.init()
81 | pygame.display.set_caption("DRIVING")
82 | self.video_path = video_path
83 | self.screen_size = screen_size
84 | self.cap = cv2.VideoCapture(self.video_path)
85 | if not self.cap.isOpened():
86 | print(f"Failed to open video: {self.video_path}")
87 | exit()
88 | self.fps = self.cap.get(cv2.CAP_PROP_FPS)
89 | self.frame_delay = int((1 / self.fps) * 1000)
90 | self.screen = pygame.display.set_mode(self.screen_size)
91 |
92 | def play_video(self):
93 | """Plays the video frame by frame, looping back to the start if the end is reached."""
94 | ret, frame = self.cap.read()
95 | if not ret:
96 | self.cap.set(cv2.CAP_PROP_POS_FRAMES, 0)
97 | return
98 | frame = cv2.transpose(frame)
99 | frame = cv2.cvtColor(frame, cv2.COLOR_BGR2RGB)
100 | frame_surface = pygame.surfarray.make_surface(frame)
101 | self.screen.blit(frame_surface, (0, 0))
102 |
103 | class MessageHandler:
104 | """
105 | Handles displaying messages and visual alerts on the screen.
106 |
107 | Attributes:
108 | font (pygame.Font): Font for regular labels.
109 | font_message (pygame.Font): Font for displaying messages.
110 | circle_radius (int): Radius of the status indicator circle.
111 | circle_color (tuple): RGB color of the circle.
112 | show_non_fatal_error_message (bool): Flag to show the non-fatal error message.
113 | """
114 | def __init__(self):
115 | self.font = pygame.font.SysFont('arial', 15)
116 | self.font_message = pygame.font.SysFont('arial', 20)
117 | self.circle_radius = 5
118 | self.circle_color = (0, 255, 0) # Green
119 | self.show_non_fatal_error_message = False
120 |
121 | def show_non_fatal_error(self):
122 | """Displays a non-fatal error message for 3 seconds."""
123 | self.show_non_fatal_error_message = True
124 | time.sleep(3)
125 | self.show_non_fatal_error_message = False
126 |
127 | def display_messages(self, screen, legend_items, screen_size):
128 | """Displays dynamic messages and status indicators based on the current state of legend items."""
129 | for item in legend_items:
130 | label = self.font.render(item['label'], True, (255, 255, 255))
131 | label_rect = label.get_rect(topleft=item['position'])
132 | circle_position = (label_rect.left - 30, label_rect.centery)
133 | if "HOST" in item['label']:
134 | current_circle_color = self.circle_color if not item["active"] else (255, 0, 0)
135 | elif item['label'].startswith("QM:"):
136 | current_circle_color = self.circle_color if not item["active"] else (255, 255, 0)
137 | else:
138 | current_circle_color = self.circle_color # Default to green
139 | pygame.draw.circle(screen, current_circle_color, circle_position, self.circle_radius)
140 | screen.blit(label, label_rect)
141 |
142 | if any(item["active"] for item in legend_items if "HOST" in item["label"]):
143 | must_stop_message = "Must Stop!"
144 | rendered_message = self.font_message.render(must_stop_message, True, (255, 0, 0))
145 | message_position = (screen_size[0] // 4 - rendered_message.get_width() // 2, (screen_size[1] // 8 + rendered_message.get_height() + 30))
146 | screen.blit(rendered_message, message_position)
147 |
148 | if self.show_non_fatal_error_message:
149 | rendered_message = self.font_message.render("A non-fatal error happened, will continue", True, (255, 255, 0))
150 | message_position = (screen_size[0] // 4 - rendered_message.get_width() // 2, (screen_size[1] // 5 + rendered_message.get_height() + 30))
151 | screen.blit(rendered_message, message_position)
152 |
153 | @click.command()
154 | @click.option('--ip', default='192.168.122.166', help='The IP address of machine set with qm.SSH must be set up with no password for easy access.')
155 | @click.option('--port', default='22', help='The port in case of ssh port forwarding')
156 | @click.option('--video', default='.driving.mp4', help='Path to the video file.')
157 |
158 | def main(ip, port, video):
159 | """
160 | Initializes and runs the main application integrating video playback and service monitoring.
161 | """
162 | class MainApplication:
163 | def __init__(self, ip_address, port , video_path):
164 | self.video_path = video_path
165 | self.screen_size = (1024, 768)
166 | self.legend_items = [
167 | {"label": "HOST: tires", "position": (50, 30), "active": False},
168 | {"label": "HOST: safety", "position": (200, 30), "active": False},
169 | {"label": "HOST: breaks", "position": (350, 30), "active": False},
170 | {"label": "HOST: cruise_control", "position": (500, 30), "active": False},
171 | {"label": "QM: radio", "position": (50, self.screen_size[1] - 30), "active": False, "freeze": True},
172 | {"label": "QM: maps", "position": (200, self.screen_size[1] - 30), "active": False},
173 | {"label": "QM: store", "position": (350, self.screen_size[1] - 30), "active": False},
174 | {"label": "QM: stream_audio", "position": (500, self.screen_size[1] - 30), "active": False}
175 | ]
176 | self.video_player = VideoPlayer(self.video_path, self.screen_size)
177 | self.message_handler = MessageHandler()
178 | self.ip_address = ip_address
179 | self.ssh_port = port
180 | self.setup_threads()
181 |
182 | def setup_threads(self):
183 | """Initializes threads for monitoring service statuses and displaying error messages."""
184 | ServiceStatusChecker(2, "HOST: tires", "container-tires", "HOST", self.legend_items, self.ip_address, self.ssh_port)
185 | ServiceStatusChecker(2, "HOST: safety", "container-safety", "HOST", self.legend_items, self.ip_address, self.ssh_port)
186 | ServiceStatusChecker(2, "HOST: breaks", "container-breaks", "HOST", self.legend_items, self.ip_address, self.ssh_port)
187 | ServiceStatusChecker(5, "HOST: cruise_control", "container-cruise_control", "HOST", self.legend_items, self.ip_address, self.ssh_port)
188 | ServiceStatusChecker(2, "QM: radio", "container-radio", "QM", self.legend_items, self.ip_address, self.ssh_port)
189 |
190 | def run(self):
191 | """Runs the main application loop, handling video playback and updating the display with messages."""
192 | running = True
193 | while running:
194 | for event in pygame.event.get():
195 | if event.type == pygame.QUIT:
196 | running = False
197 | self.video_player.play_video()
198 | self.message_handler.display_messages(self.video_player.screen, self.legend_items, self.screen_size)
199 | pygame.display.flip()
200 | pygame.time.wait(self.video_player.frame_delay)
201 | pygame.quit()
202 |
203 | app = MainApplication(ip, port, video)
204 | app.run()
205 |
206 | if __name__ == "__main__":
207 | main()
208 |
--------------------------------------------------------------------------------
/qm/qm.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Setting up some colors for helping read the demo output.
4 | # Comment out any of the below to turn off that color.
5 | bold=$(tput bold)
6 | cyan=$(tput setaf 6)
7 | reset=$(tput sgr0)
8 |
9 | read_color() {
10 | read -p "${bold}$1${reset}"
11 | }
12 |
13 | exec_color() {
14 | echo -n "
15 | ${bold}$ $1${reset}"
16 | read
17 | bash -c "$1"
18 | }
19 |
20 | echo_color() {
21 | echo "${cyan}$1${reset}"
22 | }
23 |
24 | init() {
25 | sudo systemctl stop qm > /dev/null
26 | sudo podman rm qm --force -t 0 > /dev/null
27 | sudo podman volume rm --force qmEtc qmVar > /dev/null
28 | sudo rm -rf /usr/lib/qm > /dev/null
29 | }
30 |
31 | install() {
32 | echo_color "Installing qm packages"
33 | exec_color "sudo dnf -y install qm; sudo dnf -y update qm"
34 | exec_color "rpm -q qm"
35 | read
36 | clear
37 | }
38 |
39 | setup() {
40 | echo_color "Executing setup"
41 | echo_color "Enable bluechi on the host system"
42 | exec_color "sudo systemctl start bluechi bluechi-agent"
43 | echo
44 | echo_color "Install and setup /usr/lib/qm/rootfs"
45 | exec_color "sudo /usr/share/qm/setup"
46 | read
47 | clear
48 | }
49 |
50 | status() {
51 | exec_color "sudo systemctl status qm.service"
52 | clear
53 | }
54 |
55 | status() {
56 | exec_color "sudo systemctl status qm.service"
57 | clear
58 | }
59 |
60 | cpuweight() {
61 | sudo systemctl set-property --runtime QM.slice CPUWeight=50
62 | sudo systemctl set-property --runtime qm.service CPUWeight=50
63 | exec_color "sudo cat /sys/fs/cgroup/QM.slice/cpu.weight"
64 | exec_color "sudo cat /sys/fs/cgroup/QM.slice/qm.service/cpu.weight"
65 | exec_color "sudo systemctl set-property --runtime QM.slice CPUWeight=10"
66 | exec_color "sudo cat /sys/fs/cgroup/QM.slice/cpu.weight"
67 | exec_color "sudo cat /sys/fs/cgroup/QM.slice/qm.service/cpu.weight"
68 | read
69 | }
70 |
71 | podman() {
72 | clear
73 | exec_color "sudo podman exec -ti qm ps -eZ"
74 | exec_color "sudo podman exec qm id | grep --color qm_t"
75 | exec_color "sudo podman exec qm podman run alpine echo hi"
76 | exec_color "sudo podman run ubi9 echo hi"
77 | exec_color "sudo podman exec qm podman images"
78 | exec_color "sudo podman images"
79 | exec_color "sudo podman exec qm podman run --userns=auto alpine cat /proc/self/uid_map"
80 | exec_color "sudo podman exec qm podman run --userns=auto alpine cat /proc/self/uid_map"
81 | exec_color "sudo podman exec qm podman run --userns=auto alpine cat /proc/self/uid_map"
82 | exec_color "sudo podman run --userns=auto ubi9 cat /proc/self/uid_map"
83 | exec_color "sudo podman run --userns=auto ubi9 cat /proc/self/uid_map"
84 | exec_color "sudo podman exec -ti qm sh"
85 | }
86 |
87 | bluechi() {
88 | clear
89 | exec_color "sudo bluechictl list-units | grep --color running"
90 | exec_color "sudo podman exec -ti qm podman pull ubi8/httpd-24"
91 | rootfs=/usr/lib/qm/rootfs
92 | exec_color "echo \"[Container]
93 | Image=registry.access.redhat.com/ubi8/httpd-24
94 | Network=host
95 | \" > /tmp/myquadlet.container"
96 |
97 | exec_color "sudo podman cp /tmp/myquadlet.container qm:/etc/containers/systemd/"
98 | exec_color "sudo podman exec qm systemctl daemon-reload"
99 | exec_color "sudo bluechictl restart qm.fedora myquadlet.service"
100 | exec_color "sudo bluechictl list-units | grep --color myquadlet"
101 | exec_color "curl 127.0.0.1:8080"
102 | exec_color "sudo bluechictl stop qm.fedora myquadlet.service"
103 | exec_color "sudo bluechictl list-units | grep --color myquadlet"
104 | }
105 |
106 | init
107 |
108 | install
109 |
110 | setup
111 |
112 | status
113 |
114 | cpuweight
115 |
116 | podman
117 |
118 | bluechi
119 |
120 | echo done
121 | read
122 |
--------------------------------------------------------------------------------
/restful_api/Exploring Podman RESTful API.md:
--------------------------------------------------------------------------------
1 | # Exploring Podman RESTful API using Python and Bash
2 |
3 | You may have heard Podman V2 has a new [RESTful](https://en.wikipedia.org/wiki/Representational_state_transfer) [API](https://docs.podman.io/en/latest/_static/api.html). 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.
4 |
5 | ## Requirements
6 |
7 | - You have Python >3.4 installed
8 | - You have installed the Python [requests](https://requests.readthedocs.io/en/master/) library
9 | - [installation notes](https://requests.readthedocs.io/en/master/user/install/#install)
10 | - An IDE for editing Python is recommended
11 | - Two terminal windows: one for running the Podman service and reviewing debugging information, the second window to run scripts
12 | - Usage of curl and [jq](https://stedolan.github.io/jq/) commands are demonstrated
13 |
14 | ## Getting Started
15 |
16 | ### The Service
17 |
18 | For these examples, we are running the Podman service as a normal user and on an unsecured TCP/IP port number.
19 |
20 | For production, the Podman service should use systemd's [socket activation protocol](https://www.freedesktop.org/software/systemd/man/systemd.socket.html). This allows Podman to support clients without additional daemons and secure the access endpoint.
21 |
22 | 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.
23 |
24 | ```shell
25 | podman system service tcp:localhost:8080 --log-level=debug --time=0
26 | ```
27 |
28 | In addition to the TCP socket demonstrated above the Podman service supports running under systemd's socket activation protocol and unix domain sockets (UDS).
29 |
30 | ## Python Code
31 |
32 | ### Info Resource
33 |
34 | The following will show us information about the Podman service and host.
35 |
36 | ```python
37 | import json
38 | import requests
39 |
40 | response = requests.get("http://localhost:8080/v1.40.0/libpod/info")
41 | ```
42 |
43 | #### Deep Dive
44 |
45 | - `requests.get()` call the requests library to pass the URL to the Podman service using the GET HTTP method
46 | - The requests library provides helper methods for all the popular HTTP methods
47 | - `http://localhost:8080` matches the Podman service invocation above
48 | - `/v1.40.0` denotes the API version we are using
49 | - `/libpod` denotes we expect the service to provide a libpod specific return payload
50 | - Not using this element causes the server to return a compatible payload
51 | - `/info` is the resource we are querying
52 |
53 | Interesting to read, but without output how do we know it worked?
54 |
55 | #### Getting output
56 |
57 | Append the lines below, and you can now see the version of Podman running on the host.
58 |
59 | ```python
60 |
61 | response.raise_for_status()
62 |
63 | info = json.loads(response.text)
64 | print(info.version.Version)
65 | ```
66 |
67 | - `raise_for_status()` will raise an exception if status code is not between 200 and 399.
68 | - `json.loads()` decodes the body of the HTTP response into an object/dictionary.
69 |
70 | When executed, the output is:
71 |
72 | ```text
73 | 2.1.0-dev
74 | ```
75 |
76 | The following works from the shell:
77 |
78 | ```shell
79 | $ curl -s 'http://localhost:8080/v1.40.0/libpod/info' | jq .version.Version
80 |
81 | "2.1.0-dev"
82 | ```
83 |
84 | ### Listing Containers
85 |
86 | ```python
87 | import json
88 | import requests
89 |
90 | response = requests.get("http://localhost:8080/v1.40.0/libpod/containers/json?all=true")
91 | response.raise_for_status()
92 |
93 | ctnrs = json.loads(response.text)
94 | for c in ctnrs:
95 | print(c.Id)
96 | ```
97 |
98 | `json.loads()` decodes the HTTP body into an array of objects/dictionaries, the program then prints each container Id.
99 |
100 | ```shell
101 | $ curl -s 'http://localhost:8080/v1.40.0/libpod/containers/json?all=true' | jq .[].Id
102 |
103 | "81af11ef7188a826cb5883330525e44afea3ae82634980d68e4e9eefc98d6f61"
104 | ```
105 |
106 | 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](https://docs.podman.io/en/latest/_static/api.html)
107 |
108 | ### Something Useful
109 |
110 | 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.
111 | (If you want to save on typing [clean_storage.py](https://github.com/containers/Demo/blob/master/restful_api/clean_storage.py).)
112 |
113 | ```python
114 | #!/usr/bin/env python
115 | import json
116 |
117 | import requests
118 |
119 | # Clean up local storage by removing all containers, pods, and images. Any error will
120 | # abort the process
121 |
122 | confirm = input("Really delete all items from storage? [y/N] ")
123 | if str(confirm).lower().strip() != 'y':
124 | exit(0)
125 |
126 | # Query for all pods in storage
127 | response = requests.get("http://localhost:8080/v1.40.0/libpod/pods/json")
128 | response.raise_for_status()
129 |
130 | pods = json.loads(response.text)
131 | # Workaround for https://github.com/containers/podman/issues/7392
132 | if pods is not None:
133 | for p in pods:
134 | # For each container: delete container and associated volumes
135 | response = requests.delete(f"http://localhost:8080/v1.40.0/libpod/pods/{p['Id']}?force=true")
136 | response.raise_for_status()
137 | print(f"Removed {len(pods)} pods and associated objects")
138 | else:
139 | print(f"Removed 0 pods and associated objects")
140 |
141 | # Query for all containers in storage
142 | response = requests.get("http://localhost:8080/v1.40.0/libpod/containers/json?all=true")
143 | response.raise_for_status()
144 |
145 | ctnrs = json.loads(response.text)
146 | for c in ctnrs:
147 | # For each container: delete container and associated volumes
148 | print(c.keys())
149 | response = requests.delete(f"http://localhost:8080/v1.40.0/libpod/containers/{c['Id']}?force=true&v=true")
150 | response.raise_for_status()
151 | print(f"Removed {len(ctnrs)} containers and associated objects")
152 |
153 | # Query for all images in storage
154 | response = requests.get("http://localhost:8080/v1.40.0/libpod/images/json")
155 | response.raise_for_status()
156 |
157 | imgs = json.loads(response.text)
158 | for i in imgs:
159 | # For each image: delete image and any associated containers
160 | response = requests.delete(f"http://localhost:8080/v1.40.0/libpod/images/{i['Id']}?force=true")
161 | response.raise_for_status()
162 | print(f"Removed {len(imgs)} images and associated objects")
163 |
164 | ```
165 |
166 | ## Summary
167 |
168 | I hope you find this helpful. The [API documentation](https://docs.podman.io/en/latest/_static/api.html) provides you with all the resources and required methods. The input and output bodies are included as well as the status codes.
169 |
170 | The Podman code is under heavy development and we would like your input with [github](https://github.com/containers/podman.git) [issues](https://github.com/containers/podman/issues) and [pull requests](https://github.com/containers/podman/pulls).
171 |
--------------------------------------------------------------------------------
/restful_api/clean_storage.py:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env python
2 | import json
3 |
4 | import requests
5 |
6 | # Clean up local storage by removing all containers, pods, and images. Any error will
7 | # abort the process
8 |
9 | confirm = input("Really delete all items from storage? [y/N] ")
10 | if str(confirm).lower().strip() != 'y':
11 | exit(0)
12 |
13 | # Query for all pods in storage
14 | response = requests.get("http://localhost:8080/v1.40.0/libpod/pods/json")
15 | response.raise_for_status()
16 |
17 | pods = json.loads(response.text)
18 | # Workaround for https://github.com/containers/podman/issues/7392
19 | if pods is not None:
20 | for p in pods:
21 | # For each container: delete container and associated volumes
22 | response = requests.delete(f"http://localhost:8080/v1.40.0/libpod/pods/{p['Id']}?force=true")
23 | response.raise_for_status()
24 | print(f"Removed {len(pods)} pods and associated objects")
25 | else:
26 | print(f"Removed 0 pods and associated objects")
27 |
28 | # Query for all containers in storage
29 | response = requests.get("http://localhost:8080/v1.40.0/libpod/containers/json?all=true")
30 | response.raise_for_status()
31 |
32 | ctnrs = json.loads(response.text)
33 | for c in ctnrs:
34 | # For each container: delete container and associated volumes
35 | print(c.keys())
36 | response = requests.delete(f"http://localhost:8080/v1.40.0/libpod/containers/{c['Id']}?force=true&v=true")
37 | response.raise_for_status()
38 | print(f"Removed {len(ctnrs)} containers and associated objects")
39 |
40 | # Query for all images in storage
41 | response = requests.get("http://localhost:8080/v1.40.0/libpod/images/json")
42 | response.raise_for_status()
43 |
44 | imgs = json.loads(response.text)
45 | for i in imgs:
46 | # For each image: delete image and any associated containers
47 | response = requests.delete(f"http://localhost:8080/v1.40.0/libpod/images/{i['Id']}?force=true")
48 | response.raise_for_status()
49 | print(f"Removed {len(imgs)} images and associated objects")
50 |
--------------------------------------------------------------------------------
/running/BuildahInPodman/README.MD:
--------------------------------------------------------------------------------
1 | # BuildahInPodman
2 |
3 | This script demonstrates running a Buildah container inside
4 | of a Podman container without needing root in the Buildah
5 | container. Buildah will be installed in both the Podman
6 | and the Buildah containers.
7 |
8 | You need to execute the building_ctr_wo_root.sh script in
9 | this directory. The script will install the latest versions
10 | of Podman and Buildah using yum.
11 |
--------------------------------------------------------------------------------
/running/BuildahInPodman/building_ctr_wo_root.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # building_ctr_wo_root.sh demo script.
4 | # This script will demonstrate how you can use
5 | # a container to build container images as "root"
6 | # inside of a container without actually being
7 | # being root inside of the container.
8 |
9 |
10 | # Setting up some colors for helping read the demo output.
11 | # Comment out any of the below to turn off that color.
12 | bold=$(tput bold)
13 | cyan=$(tput setaf 6)
14 | reset=$(tput sgr0)
15 |
16 | read_color() {
17 | read -p "${bold}$1${reset}"
18 | }
19 |
20 | echo_color() {
21 | echo "${cyan}$1${reset}"
22 | }
23 |
24 | setup() {
25 |
26 | echo_color "Installing/updating container-selinux and Podman"
27 | echo
28 | read_color "yum -y install --enablerepo updates-testing container-selinux podman"
29 | yum -y install --enablerepo updates-testing container-selinux podman
30 | if [[ $? != 0 ]]; then
31 | echo $0 requires the podman and containers-selinux packages to be installed
32 | exit 1
33 | fi
34 | echo_color "Updating fuse"
35 | echo
36 | read_color "echo fuse > /usr/lib/modules-load.d/fuse-overlayfs.conf"
37 | echo fuse > /usr/lib/modules-load.d/fuse-overlayfs.conf
38 | clear
39 | }
40 |
41 | intro() {
42 | read -p "Running Building Container Images without being root Demo"
43 | echo
44 | }
45 |
46 |
47 | podman_runs_buildah() {
48 |
49 | /bin/cat <<- "EOF" > ./Dockerfile
50 | FROM fedora
51 | RUN yum -y install buildah --exclude container-selinux --enablerepo updates-testing; rm -rf /var/cache /var/log/dnf* /var/log/yum.*
52 | RUN sed 's|^#mount_program|mount_program|g' -i /etc/containers/storage.conf
53 | ENV _BUILDAH_STARTED_IN_USERNS="" BUILDAH_ISOLATION=chroot
54 | COPY Dockerfile /root
55 | EOF
56 | echo
57 | echo_color "Create image from a Dockerfile and run the container"
58 | echo_color "Let's look at our Dockerfile, note it copies itself into the container at /root"
59 | echo
60 | read_color "cat ./Dockerfile"
61 | cat ./Dockerfile
62 |
63 | echo
64 | echo_color "Let's create a directory to to mount a volume on"
65 | echo
66 | read_color "mkdir /var/lib/mycontainers"
67 | mkdir /var/lib/mycontainers
68 |
69 | echo
70 | echo_color "Set the ownership of the directory"
71 | echo
72 | read_color "chown 5000:5000 /var/lib/mycontainers"
73 | chown 5000:5000 /var/lib/mycontainers
74 |
75 | echo
76 | echo_color "Create the \"buildahimage\" image from the Dockerfile"
77 | echo
78 | read_color "podman build -t buildahimage -f ./Dockerfile ."
79 | podman build -t buildahimage -f ./Dockerfile .
80 |
81 | echo
82 | echo_color "Run the container with the volume mounted into it for it's storage."
83 | echo_color "The Buildah container will run the same Dockerfile creating another"
84 | echo_color "container image."
85 | echo_color "This demonstrates building a container within a usernamespace with a locked"
86 | echo_color "down container. This is the equivalent of running the build as UID=5000."
87 |
88 | echo
89 | read_color "podman run --net=host --device=/dev/fuse -v /var/lib/mycontainers:/var/lib/containers:Z -ti --uidmap 0:5000:1000 buildahimage buildah bud /root"
90 | podman run --net=host --device=/dev/fuse -v /var/lib/mycontainers:/var/lib/containers:Z -ti --uidmap 0:5000:1000 buildahimage buildah bud /root
91 | echo
92 | read_color "Press return to start cleanup process"
93 | }
94 |
95 |
96 | clean_images_and_containers() {
97 |
98 | read_color "podman rm -a -f"
99 | podman rm -a -f
100 | echo
101 | read_color "podman rmi -a -f"
102 | podman rmi -a -f
103 |
104 | echo
105 | read -p "Enter to continue"
106 | clear
107 | }
108 |
109 | clean_temp_files() {
110 |
111 | rm -rf ./Dockerfile
112 | rm -rf /var/lib/mycontainers
113 | }
114 |
115 | setup
116 |
117 | intro
118 |
119 | podman_runs_buildah
120 |
121 | clean_images_and_containers
122 |
123 | clean_temp_files
124 |
125 | read -p "End of Demo!!!"
126 | echo
127 | echo "Thank you!"
128 |
129 |
--------------------------------------------------------------------------------
/running/ContainerSecurity/README.md:
--------------------------------------------------------------------------------
1 | # ReplacingDocker
2 |
3 | This script demonstrates new security features in podman
4 | You need to execute the podman.sh script in this directory.
5 | * Running ping without NET_RAW
6 | * Using oci-seccomp-bpf-hook to generate seccomp.json files
7 | * Using containers.conf
8 | * Using Udica
9 | * Using Capability lists specified inside of a container image
10 |
11 | The script will create the buildah-ctr if it does not exist.
12 |
--------------------------------------------------------------------------------
/running/ContainerSecurity/containers.conf:
--------------------------------------------------------------------------------
1 | [containers]
2 |
3 | # List of default capabilities for containers. If it is empty or commented out,
4 | # the default capabilities defined in the container engine will be added.
5 | #
6 | default_capabilities = [
7 | "CHOWN",
8 | "DAC_OVERRIDE",
9 | "FOWNER",
10 | "FSETID",
11 | "KILL",
12 | "NET_BIND_SERVICE",
13 | "SETFCAP",
14 | "SETGID",
15 | "SETPCAP",
16 | "SETUID",
17 | ]
18 |
19 | default_sysctls = [
20 | "net.ipv4.ping_group_range=0 1000",
21 | ]
22 |
--------------------------------------------------------------------------------
/running/ContainerSecurity/myvol/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine
2 | ENV foo=bar
3 | LABEL colour=blue
4 |
--------------------------------------------------------------------------------
/running/ContainerSecurity/podman.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | bold=$(tput bold)
4 | blue=$(tput setaf 6)
5 | yellow=$(tput setaf 11)
6 | reset=$(tput sgr0)
7 |
8 | # podmah.sh demo script.
9 |
10 | user=$(id -u)
11 | if [ $user != 0 ]; then
12 | read -p "
13 | ${bold}${yellow} podman.sh demo must be run as root
14 |
15 | "
16 | reset
17 | exit 1
18 | fi
19 |
20 | read -p "${bold}${yellow}This script will demonstrate new security features of podman${reset}"
21 | echo ""
22 | clear
23 |
24 | setup() {
25 | rpm -q podman audit oci-seccomp-bpf-hook perl-JSON-PP >/dev/null
26 | if [[ $? != 0 ]]; then
27 | echo $0 requires the podman, oci-seccomp-bpf-hook, perl-JSON-PP, and audit packages be installed
28 | exit 1
29 | fi
30 | augenrules --load > /dev/null
31 | systemctl restart auditd 2> /dev/null
32 | cat > /tmp/Containerfile < /tmp/Fedorafile < /tmp/Capfile < /tmp/InvalidCapfile < podman run ping ping -c 3 4.2.2.2${reset}"
65 | echo ""
66 | podman run ping ping -c 3 4.2.2.2
67 | echo ""
68 |
69 | # Podman inside a container
70 | read -p "${bold}--> podman run ${yellow}--cap-drop NET_RAW${reset}${bold} ping ping -c 3 4.2.2.2${reset}"
71 | echo ""
72 | podman run --cap-drop NET_RAW ping ping -c 3 4.2.2.2
73 | echo ""
74 | read -p "
75 | ${blue}${bold}Fails because ${yellow}NET_RAW${reset}${blue}${bold} disabled.${reset}"
76 |
77 | # Podman inside a container
78 | read -p "
79 | ${blue}${bold}Execute same container with --sysctl 'net.ipv4.ping_group_range=0 1000' enabled${reset}"
80 |
81 | read -p "${bold}--> podman run -sysctl --cap-drop NET_RAW ${yellow}--sysctl 'net.ipv4.ping_group_range=0 1000'${reset}${bold} ping ping -c 3 4.2.2.2${reset}"
82 | echo ""
83 | podman run -ti --cap-drop NET_RAW --sysctl 'net.ipv4.ping_group_range=0 1000' ping ping -c 3 4.2.2.2
84 | echo ""
85 | read -p "${bold}--> clear${reset}"
86 | clear
87 | }
88 |
89 | capabilities_in_image() {
90 | read -p "${blue}${bold}Let image developer select the capabilities they want in the image by setting a label${reset}"
91 | read -p "${bold}--> cat /tmp/Dockerfile.capabilities${reset}"
92 | cat /tmp/Capfile
93 | echo ""
94 | read -p "${bold}--> podman run --name capctr -d fedoracap sleep 1000${reset}"
95 | podman run --name capctr -d fedoracap sleep 1000
96 | echo ""
97 | read -p "${bold}--> podman top capctr capeff${reset}"
98 | podman top capctr capeff
99 | echo ""
100 | read -p "${bold}--> podman run --name defctr -d registry.fedoraproject.org/fedora sleep 1000${reset}"
101 | podman run --name defctr -d registry.fedoraproject.org/fedora sleep 1000
102 | echo ""
103 | read -p "${bold}--> podman top defctr capeff${reset}"
104 | podman top defctr capeff
105 | echo ""
106 | read -p "${bold}--> cat /tmp/Dockerfile.InvalidCapabilities${reset}"
107 | cat /tmp/InvalidCapfile
108 | echo ""
109 | read -p "${bold}--> podman run --name invalidcapctr -d fedorainvalidcap sleep 1000${reset}"
110 | podman run --name invalidcapctr -d fedorainvalidcap sleep 1000
111 | echo ""
112 | read -p "${bold}--> podman top invalidcapctr capeff${reset}"
113 | podman top invalidcapctr capeff
114 | echo ""
115 | read -p "${bold}--> podman run -d --cap-add SYS_ADMIN --cap-add NET_ADMIN fedorainvalidcap sleep 1000${reset}"
116 | podman run -d --cap-add SYS_ADMIN --cap-add NET_ADMIN fedorainvalidcap sleep 1000
117 | echo ""
118 | read -p "${bold}--> podman top -l capeff${reset}"
119 | podman top -l capeff
120 | echo ""
121 | read -p "${bold}--> cleanup${reset}"
122 | podman stop -a -t 0
123 | podman rm -af
124 | read -p "${bold}--> clear${reset}"
125 | clear
126 | }
127 |
128 |
129 | udica_demo() {
130 | podman stop -a -t 0
131 | podman rm -af 2> /dev/null
132 | read -p "${bold}${blue}Podman run with volumes using udica${reset}"
133 | # check /home, /var/spool, and the network nc -lvp (port)
134 | read -p "${bold}--> podman run --rm -v /home:/home:ro -v /var/spool:/var/spool:rw -it myfedora bash${reset}"
135 | echo ""
136 | podman run -v /home:/home:ro -v /var/spool:/var/spool:rw -it myfedora bash
137 | echo ""
138 | read -p "${bold}${blue}Use udica to generate a custom policy for this container${reset}"
139 | echo ""
140 | read -p "${bold}--> podman run --name myctr -v /home:/home:ro -v /var/spool:/var/spool:rw -d myfedora sleep 1000${reset}"
141 | echo ""
142 | podman run --name myctr -v /home:/home:ro -v /var/spool:/var/spool:rw -d myfedora sleep 1000
143 | echo ""
144 | read -p "${bold}--> podman inspect myctr | udica my_container${reset}"
145 | echo ""
146 | podman inspect myctr | udica my_container
147 | echo ""
148 | read -p "${bold}--> semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}${reset}"
149 | # semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}
150 | echo ""
151 | read -p "${blue}${bold}Let's restart the container${reset}"
152 | echo ""
153 | read -p "${bold}--> podman run --name udica_ctr --security-opt label=type:my_container.process -v /home:/home:ro -v /var/spool:/var/spool:rw -d myfedora sleep 1000${reset}"
154 | echo ""
155 | podman run --name udica_ctr --security-opt label=type:my_container.process -v /home:/home:ro -v /var/spool:/var/spool:rw -d myfedora sleep 1000
156 | echo ""
157 | read -p "${bold}--> podman top -l label"
158 | podman top -l label | grep -a --color=auto -B 1 my_container.process
159 |
160 | echo ""
161 | read -p "${bold}--> podman exec -it udica_ctr bash${reset}"
162 | podman exec -it udica_ctr bash
163 | echo ""
164 | read -p "${bold}--> cleanup${reset}"
165 | podman stop -a -t 0
166 | podman rm -af 2> /dev/null
167 | echo ""
168 | read -p "${bold}--> clear${reset}"
169 | clear
170 | }
171 |
172 | syscalls() {
173 | out=$(awk '/SYSCALL/{print $NF}' /var/log/audit/audit.log | grep SYSCALL | cut -f2 -d = | sort -u)
174 | echo "
175 | "
176 | for i in $out; do echo -n \"$i\",; done
177 | echo "
178 | "
179 | read -p ""
180 | }
181 |
182 | seccomp() {
183 | # Podman Generate Seccomp Rules
184 | read -p "${blue}${bold}
185 | Podman Generate Seccomp Rules
186 |
187 | This demonstration with use an OCI Hook to fire up a BPF Program to trace
188 | all sycalls generated from a container.
189 |
190 | We will then use the generated seccomp file to lock down the container, only
191 | allowing the generated syscalls, rather then the system default.${reset}
192 | "
193 | echo ""
194 |
195 | read -p "${bold}--> less /usr/share/containers/oci/hooks.d/oci-seccomp-bpf-hook.json${reset}"
196 | less /usr/share/containers/oci/hooks.d/oci-seccomp-bpf-hook.json
197 | echo ""
198 | echo ""
199 |
200 | read -p "${bold}--> podman run ${yellow}--annotation io.containers.trace-syscall=of:/tmp/myseccomp.json${reset}${bold} fedora ${yellow}ls /${reset}"
201 | podman run --rm --annotation io.containers.trace-syscall=of:/tmp/myseccomp.json --pull=missing registry.fedoraproject.org/fedora ls /
202 | echo ""
203 |
204 | read -p "${bold}--> cat /tmp/myseccomp.json | json_pp${reset}"
205 | cat /tmp/myseccomp.json | json_pp > /tmp/myseccomp.pp
206 | less /tmp/myseccomp.pp
207 | echo ""
208 | clear
209 | read -p "${bold}--> podman run ${yellow}--security-opt seccomp=/tmp/myseccomp.json${reset}${bold} fedora ${yellow}ls /${reset}"
210 | podman run --rm --security-opt seccomp=/tmp/myseccomp.json --pull=never registry.fedoraproject.org/fedora ls /
211 | echo ""
212 | read -p "${bold}--> clear${reset}"
213 | clear
214 |
215 | read -p "${bold}--> podman run --security-opt seccomp=/tmp/myseccomp.json fedora ${yellow}ls -l /${reset}"
216 | podman run --rm --security-opt seccomp=/tmp/myseccomp.json --pull=never registry.fedoraproject.org/fedora ls -l /
217 | echo ""
218 |
219 | read -p "${bold}--> grep --color SYSCALL=.* /var/log/audit/audit.log${reset}"
220 | grep --color SYSCALL=.* /var/log/audit/audit.log
221 | echo ""
222 |
223 | syscalls
224 |
225 | read -p "${bold}--> podman run --annotation io.containers.trace-syscall=\"if:/tmp/myseccomp.json;of:/tmp/myseccomp2.json\" fedora ls -l / > /dev/null${reset}"
226 | podman run --rm --annotation io.containers.trace-syscall="if:/tmp/myseccomp.json;of:/tmp/myseccomp2.json" --pull=never registry.fedoraproject.org/fedora ls -l /
227 | echo ""
228 |
229 | read -p "${bold}--> podman run --security-opt seccomp=/tmp/myseccomp2.json fedora ls -l /${reset}"
230 | podman run --rm --security-opt seccomp=/tmp/myseccomp2.json --pull=never registry.fedoraproject.org/fedora ls -l /
231 | echo ""
232 |
233 | read -p "${bold}--> diff -u /tmp/myseccomp.json /tmp/myseccomp2.json${reset}"
234 | cat /tmp/myseccomp2.json | json_pp > /tmp/myseccomp2.pp
235 | diff -u /tmp/myseccomp.pp /tmp/myseccomp2.pp | less
236 | read -p "${bold}--> clear${reset}"
237 | clear
238 | }
239 |
240 |
241 | containers_conf_ping() {
242 | read -p "${blue}${bold}
243 | This demonstration will show how you can specify the default linux capabilities
244 | for all containers on your system.
245 |
246 | Then of the demonstration will show ping still running without NET_RAW
247 | Capability, since containers_conf will automatically set the sycall.
248 | ${reset}"
249 | cat > containers.conf < podman run -d fedora sleep 6000${reset}"
271 | echo ""
272 | podman run -d --pull=never registry.fedoraproject.org/fedora sleep 6000
273 | echo ""
274 |
275 | # Podman ping inside a container
276 | read -p "${bold}--> podman top -l capeff${reset}"
277 | echo ""
278 | podman top -l capeff | grep --color=auto -B 1 NET_RAW
279 | echo ""
280 |
281 | # Podman ping inside a container
282 | read -p "${bold}--> cat containers.conf${reset}"
283 | echo ""
284 | cat containers.conf
285 | echo ""
286 |
287 | # Podman ping inside a container
288 | read -p "${bold}--> CONTAINERS_CONF=containers.conf podman run -d fedora sleep 6000${reset}"
289 | echo ""
290 | CONTAINERS_CONF=containers.conf podman run -d --pull=never registry.fedoraproject.org/fedora sleep 6000
291 | echo ""
292 |
293 | # Podman ping inside a container
294 | read -p "${bold}--> podman top -l capeff${reset}"
295 | echo ""
296 | podman top -l capeff
297 | echo ""
298 |
299 | # Podman inside a container
300 | read -p "${blue}${bold}
301 | Notice NET_RAW as well as AUDIT_WRITE, SYS_CHROOT, and MKNOD capabilies are gone${reset}"
302 |
303 | read -p "${bold}--> CONTAINERS_CONF=containers.conf podman run ping ping -c 3 4.2.2.2${reset}"
304 | echo ""
305 | CONTAINERS_CONF=containers.conf podman run ping ping -c 3 4.2.2.2
306 | echo ""
307 | read -p "${blue}${bold}
308 | Fails because ${yellow}NET_RAW${reset}${blue}${bold} disabled${reset}.
309 |
310 | "
311 |
312 | cat >> containers.conf < cat containers.conf${reset}"
325 | echo ""
326 | cat containers.conf
327 | echo ""
328 |
329 | # Podman inside a container
330 | read -p "${bold}--> CONTAINERS_CONF=containers.conf podman run ping ping -c 3 4.2.2.2${reset}"
331 | echo ""
332 | CONTAINERS_CONF=containers.conf podman run ping ping -c 3 4.2.2.2
333 | echo ""
334 | read -p "${bold}--> clear${reset}"
335 | clear
336 | }
337 |
338 | userns() {
339 | # Note, this is still a WIP and has not yet been merged into podman master
340 | # Podman user namespace
341 | read -p "${blue}${bold}Podman User Namespace Support${reset}"
342 | echo ""
343 |
344 | read -p "${bold}--> podman run --uidmap 0:100000:5000 -d fedora sleep 1000${reset}"
345 | podman run --net=host --uidmap 0:100000:5000 -d --pull=never registry.fedoraproject.org/fedora sleep 1000
346 | echo ""
347 |
348 | read -p "${bold}--> podman top --latest user huser | grep --color=auto -B 1 100000${reset}"
349 | podman top --latest user huser | grep --color=auto -B 1 100000
350 | echo ""
351 |
352 | read -p "${bold}--> ps -ef | grep -v grep | grep --color=auto 100000.*sleep${reset}"
353 | ps -ef | grep -v grep | grep --color=auto 100000.*sleep
354 | echo ""
355 |
356 | read -p "${bold}--> podman run --uidmap 0:200000:5000 -d fedora sleep 1000${reset}"
357 | podman run --net=host --uidmap 0:200000:5000 -d --pull=never registry.fedoraproject.org/fedora sleep 1000
358 | echo ""
359 |
360 | read -p "${bold}--> podman top --latest user huser | grep --color=auto -B 1 200000${reset}"
361 | podman top --latest user huser | grep --color=auto -B 1 200000
362 | echo ""
363 |
364 | read -p "${bold}--> ps -ef | grep -v grep | grep --color=auto 200000.*sleep${reset}"
365 | ps -ef | grep -v grep | grep --color=auto 200000.*sleep
366 | echo ""
367 |
368 | read -p "${bold}--> clear${reset}"
369 | clear
370 |
371 | read -p "${blue}${bold}Podman User Namespace Support Using --userns=auto${reset}"
372 | echo ""
373 |
374 | read -p "${bold}--> podman run --userns=auto -d fedora sleep 1000${reset}"
375 | podman run --userns=auto -d --pull=never registry.fedoraproject.org/fedora sleep 1000
376 | echo ""
377 |
378 | read -p "${bold}--> podman top --latest user huser${reset}"
379 | podman top --latest user huser | grep --color=auto -B 1 [0-9].*
380 | echo ""
381 |
382 | read -p "${bold}--> podman run --userns=auto -d fedora sleep 1000${reset}"
383 | podman run --userns=auto -d --pull=never registry.fedoraproject.org/fedora sleep 1000
384 | echo ""
385 |
386 | read -p "${bold}--> podman top --latest user huser${reset}"
387 | podman top --latest user huser | grep --color=auto -B 1 [0-9].*
388 | echo ""
389 |
390 | read -p "${bold}--> podman run --userns=auto:size=5000 -d fedora sleep 1000${reset}"
391 | podman run --userns=auto:size=5000 -d --pull=never registry.fedoraproject.org/fedora sleep 1000
392 | echo ""
393 |
394 | read -p "${bold}--> podman top --latest user huser${reset}"
395 | podman top --latest user huser | grep --color=auto -B 1 [0-9].*
396 | echo ""
397 |
398 | read -p "${bold}--> podman exec --latest cat /proc/self/uid_map${reset}"
399 | podman exec --latest cat /proc/self/uid_map
400 | echo ""
401 |
402 | read -p "${bold}--> cleanup${reset}"
403 | podman stop -a -t 0
404 | podman rm -af
405 | echo ""
406 |
407 | read -p "${bold}--> clear${reset}"
408 | clear
409 | }
410 |
411 | setup
412 | ping
413 | capabilities_in_image
414 | seccomp
415 | udica_demo
416 | userns
417 | containers_conf_ping
418 |
419 | read -p "${yellow}${bold}End of Demo"
420 | echo "Thank you!${reset}"
421 |
--------------------------------------------------------------------------------
/running/GenerateSeccomp/podman.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # podmah.sh demo script.
4 | # This script will demonstrate a lot of the features of podman, concentrating
5 | # on the security features.
6 |
7 | setup() {
8 | rpm -q podman audit >/dev/null
9 | if [[ $? != 0 ]]; then
10 | echo $0 requires the podman, buildah and audit packages be installed
11 | exit 1
12 | fi
13 | # sudo bash -c "> /var/log/audit/audit.log"
14 | clear
15 | }
16 |
17 | syscalls() {
18 | out=$(sudo awk '/SYSCALL/{print $NF}' /var/log/audit/audit.log | cut -f2 -d = | sort -u)
19 | for i in $out; do echo -n \"$i\",; done
20 | read -p ""
21 | }
22 |
23 | version() {
24 | # Podman inside a container
25 | read -p "sudo podman version"
26 | echo ""
27 | sudo podman version
28 | echo ""
29 |
30 | # Podman inside a container
31 | read -p "sudo podman info"
32 | echo ""
33 | sudo podman info
34 | }
35 |
36 | seccomp() {
37 | # Podman Generate Seccomp Rules
38 | read -p "OCI Hooks"
39 | echo ""
40 |
41 | read -p "--> cat /usr/share/containers/oci/hooks.d/oci-seccomp-bpf-hook-run.json"
42 | sudo cat /usr/share/containers/oci/hooks.d/oci-seccomp-bpf-hook-run.json
43 | echo ""
44 | echo ""
45 |
46 | read -p "--> sudo podman run --annotation io.containers.trace-syscall=/tmp/myseccomp.json fedora ls /"
47 | sudo podman run --annotation io.containers.trace-syscall=/tmp/myseccomp.json fedora ls /
48 | echo ""
49 |
50 | read -p "--> sudo cat /tmp/myseccomp.json | json_pp"
51 | sudo sudo cat /tmp/myseccomp.json | json_pp > /tmp/myseccomp.pp
52 | cat /tmp/myseccomp.pp
53 | echo ""
54 |
55 | read -p "--> sudo podman run --security-opt seccomp=/tmp/myseccomp.json fedora ls /"
56 | sudo podman run --security-opt seccomp=/tmp/myseccomp.json fedora ls /
57 | echo ""
58 |
59 | read -p "--> sudo podman run --security-opt seccomp=/tmp/myseccomp.json fedora ls -l /"
60 | sudo podman run --security-opt seccomp=/tmp/myseccomp.json fedora ls -l /
61 | echo ""
62 |
63 | read -p "--> sudo grep --color SYSCALL=.* /var/log/audit/audit.log"
64 | sudo sudo grep --color SYSCALL=.* /var/log/audit/audit.log
65 | echo ""
66 |
67 | syscalls
68 |
69 | read -p "--> sudo vi /tmp/myseccomp.json"
70 | sudo sudo vi /tmp/myseccomp.json
71 | echo ""
72 |
73 | read -p "--> sudo podman run --security-opt seccomp=/tmp/myseccomp.json fedora ls -l /"
74 | sudo podman run --security-opt seccomp=/tmp/myseccomp.json fedora ls -l /
75 | echo ""
76 |
77 | read -p "--> sudo podman run --annotation io.containers.trace-syscall=/tmp/myseccomp2.json fedora ls -l / > /dev/null"
78 | sudo podman run --annotation io.containers.trace-syscall=/tmp/myseccomp2.json fedora ls -l / > /dev/null
79 | echo ""
80 |
81 | read -p "--> diff -u /tmp/myseccomp.pp /tmp/myseccomp2.pp"
82 | sudo sudo cat /tmp/myseccomp2.json | json_pp > /tmp/myseccomp2.pp
83 | diff -u /tmp/myseccomp.pp /tmp/myseccomp2.pp
84 |
85 | read -p "--> clear"
86 | clear
87 | }
88 |
89 | setup
90 | seccomp
91 |
92 | read -p "End of Demo"
93 | echo "Thank you!"
94 |
--------------------------------------------------------------------------------
/running/PINP/podman-in-podman.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | read -p "# rootful podman in rootful podman with --privileged"
4 | read -p "--> sudo podman run --privileged quay.io/podman/stable id && podman run ubi8-minimal echo hello"
5 | echo ""
6 | sudo podman run --privileged quay.io/podman/stable id && podman run ubi8-minimal echo hello
7 | echo ""
8 |
9 | read -p "# rootless podman in rootful podman with --privileged"
10 | read -p "--> sudo podman run --privileged --user podman quay.io/podman/stable id && podman run ubi8-minimal echo hello"
11 | echo ""
12 | sudo podman run --privileged --user podman quay.io/podman/stable id && podman run ubi8-minimal echo hello
13 | echo ""
14 |
15 | read -p "# rootful podman in rootless podman with --privileged"
16 | read -p "--> podman run --privileged quay.io/podman/stable id && podman run ubi8-minimal echo hello"
17 | echo ""
18 | podman run --privileged quay.io/podman/stable id && podman run ubi8-minimal echo hello
19 | echo ""
20 |
21 | read -p "# rootless podman in rootless podman with --privileged"
22 | read -p "--> podman run --privileged --user podman quay.io/podman/stable id && podman run ubi8-minimal echo hello"
23 | echo ""
24 | sudo podman run --privileged --user podman quay.io/podman/stable id && podman run ubi8-minimal echo hello
25 | echo ""
26 |
27 | read -p "# rootful podman in rootful podman without --privileged"
28 | read -p "--> sudo podman run --cap-add=sys_admin,mknod --device=/dev/fuse --security-opt label=disable quay.io/podman/stable id && podman run ubi8-minimal echo hello"
29 | echo ""
30 | sudo podman run --cap-add=sys_admin,mknod --device=/dev/fuse --security-opt label=disable quay.io/podman/stable id && podman run ubi8-minimal echo hello
31 | echo ""
32 |
33 | read -p "# rootless podman in rootful podman without --privileged"
34 | read -p "--> sudo podman run --user podman --security-opt label=disable --security-opt unmask=ALL --device /dev/fuse -ti quay.io/podman/stable id && podman run ubi8-minimal echo hello"
35 | echo ""
36 | sudo podman run --user podman --security-opt label=disable --security-opt unmask=ALL --device /dev/fuse -ti quay.io/podman/stable id && podman run ubi8-minimal echo hello
37 | echo ""
38 |
39 | read -p "# rootless podman in rootless podman without --privileged"
40 | read -p "--> podman run --security-opt label=disable --user podman --device /dev/fuse quay.io/podman/stable id && podman run ubi8-minimal echo hello"
41 | echo ""
42 | podman run --security-opt label=disable --user podman --device /dev/fuse quay.io/podman/stable id && podman run ubi8-minimal echo hello
43 | echo ""
--------------------------------------------------------------------------------
/running/PINP/podman.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # podmah.sh demo script.
4 | # This script will demonstrate running podmain within a container
5 | # on the security features.
6 |
7 | # Setting up some colors for helping read the demo output.
8 | bold=$(tput bold)
9 | bright=$(tput setaf 14)
10 | yellow=$(tput setaf 11)
11 | reset=$(tput sgr0)
12 |
13 | # commands
14 | read_bright() {
15 | read -p "${bold}${bright}$1${reset}"
16 | }
17 | echo_bright() {
18 | echo "${bold}${bright}$1${reset}"
19 | }
20 |
21 | exec_command() {
22 | echo
23 | read_bright "$@"
24 | $@
25 | }
26 |
27 | # headings
28 | read_yellow() {
29 | read -p "${bold}${yellow}$1${reset}"
30 | }
31 |
32 | PODMANIMAGE=quay.io/podman/testing
33 | IMAGE=registry.access.redhat.com/ubi8-micro:latest
34 |
35 | setup() {
36 | rpm -q podman docker-ce >/dev/null
37 | if [[ $? != 0 ]]; then
38 | echo $0 requires the podman and docker-ce packages be installed
39 | exit 1
40 | fi
41 | sudo systemctl start docker
42 | sudo docker pull -q ${PODMANIMAGE}
43 | sudo podman pull -q ${PODMANIMAGE}
44 | podman pull -q ${PODMANIMAGE}
45 | clear
46 | }
47 |
48 | version() {
49 | # Podman inside a container
50 | read -p "podman version"
51 | echo ""
52 | podman version
53 | echo ""
54 | }
55 |
56 |
57 | rootfull_privileged() {
58 | echo ""
59 | echo ""
60 | read_bright "rootfull privileged"
61 | exec_command "sudo podman run --rm --privileged ${PODMANIMAGE} podman run ${IMAGE} echo hello"
62 |
63 | echo ""
64 | read_bright "rootfull docker privileged"
65 | exec_command "sudo docker run --rm --privileged ${PODMANIMAGE} podman run ${IMAGE} echo hello"
66 | }
67 |
68 | rootfull_rootfull_less_privs() {
69 | echo ""
70 | echo ""
71 | read_bright "rootfull rootfull less privs"
72 | exec_command "sudo podman run --cap-add=sys_admin,mknod --device=/dev/fuse --security-opt label=disable ${PODMANIMAGE} podman run ${IMAGE} echo hello"
73 | }
74 |
75 | rootfull_volume_privileged() {
76 | echo ""
77 | echo ""
78 | read_bright "rootfull volume privileged"
79 |
80 | mkdir -p mycontainers
81 | exec_command "sudo podman run -v ./mycontainers:/var/lib/containers --rm --privileged ${PODMANIMAGE} podman run ${IMAGE} echo hello"
82 | }
83 |
84 | rootless_privileged() {
85 | echo ""
86 | echo ""
87 | read_bright "rootless privileged"
88 | exec_command "podman run --rm --privileged ${PODMANIMAGE} podman run ${IMAGE} echo hello"
89 | }
90 |
91 | rootfull_rootless() {
92 | echo ""
93 | echo ""
94 | read_bright "rootfull rootless"
95 | exec_command "sudo podman run --device /dev/fuse --user podman --security-opt label=disable --rm ${PODMANIMAGE} podman run ${IMAGE} echo hello"
96 |
97 | echo ""
98 | read_bright "rootfull docker rootless"
99 |
100 | tmp_dir=$(mktemp -d -t ci-XXXXXXXXXX)
101 | sudo chown 1000:1000 ${tmp_dir}
102 | exec_command "sudo docker run --device /dev/fuse -v ${tmp_dir}:/home/podman/.local/share/containers/storage --user podman --security-opt label=disable --security-opt seccomp=unconfined --rm ${PODMANIMAGE} podman unshare cat /proc/self/uid_map"
103 | IMAGE=docker.io/library/alpine:latest
104 | exec_command "sudo docker run --device /dev/fuse -v ${tmp_dir}:/home/podman/.local/share/containers/storage --user podman --security-opt label=disable --security-opt seccomp=unconfined --rm ${PODMANIMAGE} podman run ${IMAGE} echo hello"
105 | sudo rm -rf ${tmp_dir}
106 | }
107 |
108 | rootless_rootless() {
109 | echo ""
110 | echo ""
111 | read_bright "rootless rootless"
112 | exec_command "podman run --user podman --device /dev/fuse --security-opt label=disable --rm ${PODMANIMAGE} podman run ${IMAGE} echo hello"
113 | }
114 |
115 | setup
116 | version
117 | rootfull_privileged
118 | rootfull_rootfull_less_privs
119 | rootfull_volume_privileged
120 | rootless_privileged
121 | rootfull_rootless
122 | rootless_rootless
123 |
124 | read -p "End of Demo"
125 | echo "Thank you!"
126 |
--------------------------------------------------------------------------------
/running/README.md:
--------------------------------------------------------------------------------
1 | ## Demos for libpod (Podman)
2 | The following subdirectories contain demos related to Podman.
3 |
--------------------------------------------------------------------------------
/running/ReplacingDocker/Dockerfile.buildah:
--------------------------------------------------------------------------------
1 | FROM fedora
2 |
3 | RUN dnf -y install buildah; dnf -y clean all
4 | ENTRYPOINT ["/usr/bin/buildah"]
5 | WORKDIR /root
6 |
--------------------------------------------------------------------------------
/running/ReplacingDocker/README.md:
--------------------------------------------------------------------------------
1 | # ReplacingDocker
2 |
3 | This script demonstrates running podman as a replacement for the Docker CLI.
4 | You need to execute the podman.sh script in this directory.
5 |
6 | The script will create the buildah-ctr if it does not exist.
7 |
8 |
--------------------------------------------------------------------------------
/running/ReplacingDocker/myvol/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine
2 | ENV foo=bar
3 | LABEL colour=blue
4 |
--------------------------------------------------------------------------------
/running/ReplacingDocker/podman.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # podmah.sh demo script.
4 | # This script will demonstrate a lot of the features of podman, concentrating
5 | # on the security features.
6 |
7 | setup() {
8 | rpm -q podman audit >/dev/null
9 | if [[ $? != 0 ]]; then
10 | echo $0 requires the podman, buildah and audit packages be installed
11 | exit 1
12 | fi
13 | command -v docker > /dev/null
14 | if [[ $? != 0 ]]; then
15 | echo $0 requires the docker package be installed
16 | exit 1
17 | fi
18 | sudo cp /usr/share/audit/sample-rules/10-base-config.rules /etc/audit/rules.d/audit.rules
19 | sudo augenrules --load > /dev/null
20 | sudo systemctl restart auditd 2> /dev/null
21 | sudo systemctl restart docker
22 | clear
23 | }
24 | version() {
25 | # Podman inside a container
26 | read -p "sudo podman version"
27 | echo ""
28 | sudo podman version
29 | echo ""
30 |
31 | # Podman inside a container
32 | read -p "sudo podman info"
33 | echo ""
34 | sudo podman info
35 | }
36 |
37 | rootless() {
38 | # Rootless podman
39 | read -p "Podman as rootless"
40 | echo ""
41 |
42 | read -p "--> podman pull alpine"
43 | podman pull alpine
44 | echo ""
45 |
46 | read -p "--> podman run --net=host --rm alpine ls"
47 | podman run --net=host alpine ls
48 | echo ""
49 |
50 | echo "Show Non Privileged containers"
51 | read -p "--> podman ps -a"
52 | podman ps -a
53 | echo ""
54 |
55 | echo "Show Non Privileged images"
56 | read -p "--> podman images"
57 | podman images
58 | echo ""
59 |
60 | echo "Show Privileged images"
61 | read -p "--> sudo podman images"
62 | sudo podman images
63 | echo ""
64 |
65 | read -p "--> clear"
66 | clear
67 | }
68 |
69 | userns() {
70 | echo "
71 | The demo will now unshare the usernamespace of a rootless container,
72 | using the 'podman unshare' command.
73 |
74 | First outside of the continer, we will cat /etc/subuid, and you should
75 | see your username. This indicates the UID map that is assigned to you.
76 | When executing podman unshare, it will map your UID to root within the container
77 | and then map the range of UIDS in /etc/subuid starting at UID=1 within your container.
78 | "
79 | read -p "--> cat /etc/subuid"
80 | cat /etc/subuid
81 | echo ""
82 |
83 | echo "
84 |
85 |
86 | Explore your home directory to see what it looks like while in a user namespace.
87 | 'cat /proc/self/uid_map' will show you the user namespace mapping.
88 |
89 | Type 'exit' to exit the user namespace and continue running the demo.
90 | "
91 | read -p "--> podman unshare"
92 | podman unshare
93 | echo ""
94 |
95 | read -p "--> clear"
96 | clear
97 |
98 | # Podman user namespace
99 | read -p "Podman User Namespace Support"
100 | echo ""
101 |
102 | read -p "--> sudo podman run --uidmap 0:100000:5000 -d fedora sleep 1000"
103 | sudo podman run --net=host --uidmap 0:100000:5000 -d fedora sleep 1000
104 | echo ""
105 |
106 | read -p "--> sudo podman top --latest user huser | grep --color=auto -B 1 100000"
107 | sudo podman top --latest user huser | grep --color=auto -B 1 100000
108 | echo ""
109 |
110 | read -p "--> ps -ef | grep -v grep | grep --color=auto 100000"
111 | ps -ef | grep -v grep | grep --color=auto 100000
112 | echo ""
113 |
114 | read -p "--> sudo podman run --uidmap 0:200000:5000 -d fedora sleep 1000"
115 | sudo podman run --net=host --uidmap 0:200000:5000 -d fedora sleep 1000
116 | echo ""
117 |
118 | read -p "--> sudo podman top --latest user huser | grep --color=auto -B 1 200000"
119 | sudo podman top --latest user huser | grep --color=auto -B 1 200000
120 | echo ""
121 |
122 | read -p "--> ps -ef | grep -v grep | grep --color=auto 200000"
123 | ps -ef | grep -v grep | grep --color=auto 200000
124 | echo ""
125 |
126 | read -p "--> clear"
127 | clear
128 | }
129 |
130 | forkexec() {
131 | # Podman Fork/Exec model
132 | read -p "Podman Fork/Exec Model"
133 | echo ""
134 |
135 | read -p "--> cat /proc/self/loginuid"
136 | cat /proc/self/loginuid
137 | echo ""
138 | echo ""
139 |
140 | read -p "--> sudo podman run -ti fedora bash -c \"cat /proc/self/loginuid; echo\""
141 | sudo podman run -ti fedora bash -c "cat /proc/self/loginuid; echo"
142 | echo ""
143 |
144 | read -p "--> sudo docker run -ti fedora bash -c \"cat /proc/self/loginuid; echo\""
145 | sudo docker run -ti fedora bash -c "cat /proc/self/loginuid; echo"
146 | echo ""
147 |
148 | read -p "--> sudo auditctl -w /etc/shadow"
149 | sudo auditctl -w /etc/shadow 2>/dev/null
150 | echo ""
151 |
152 | # Showing how podman keeps track of the person trying to wreak havoc on your system
153 | read -p "--> sudo podman run --privileged -v /:/host fedora touch /host/etc/shadow"
154 | sudo podman run --privileged -v /:/host fedora touch /host/etc/shadow
155 | echo ""
156 |
157 | read -p "--> ausearch -m path -ts recent -i | grep touch | tail -n 1 | grep --color=auto 'auid=[^ ]*'"
158 | sudo ausearch -m path -ts recent -i | grep touch | tail -n 1 | grep --color=auto 'auid=[^ ]*'
159 | echo ""
160 |
161 | read -p "--> sudo docker run --privileged -v /:/host fedora touch /host/etc/shadow"
162 | sudo docker run --privileged -v /:/host fedora touch /host/etc/shadow
163 | echo ""
164 |
165 | read -p "--> ausearch -m path -ts recent -i | grep touch | tail -n 1 | grep --color=auto 'auid=[^ ]*'"
166 | sudo ausearch -m path -ts recent -i | grep touch | tail -n 1 |grep --color=auto 'auid=[^ ]*'
167 | echo ""
168 |
169 | read -p "--> clear"
170 | clear
171 | }
172 |
173 | top() {
174 | # Podman top commands
175 | read -p "Podman top features"
176 | echo ""
177 |
178 | read -p "--> sudo podman run -d fedora sleep 1000"
179 | sudo podman run -d fedora sleep 1000
180 | echo ""
181 |
182 | read -p "--> sudo podman top --latest pid hpid"
183 | sudo podman top --latest pid hpid
184 | echo ""
185 |
186 | read -p "--> sudo podman top --latest label"
187 | sudo podman top --latest label
188 | echo ""
189 |
190 | read -p "--> sudo podman top --latest seccomp"
191 | sudo podman top --latest seccomp
192 | echo ""
193 |
194 | read -p "--> sudo podman top --latest capeff"
195 | sudo podman top --latest capeff
196 | echo ""
197 |
198 | read -p "--> clear"
199 | clear
200 | }
201 |
202 | pods() {
203 | sudo podman kill -a
204 | sudo podman rm -a -f
205 | clear
206 |
207 | read -p "--> sudo podman pod list"
208 | sudo podman pod list
209 | echo ""
210 |
211 | read -p "--> sudo podman pod --name podtest create"
212 | sudo podman pod create --name podtest
213 | echo ""
214 |
215 | read -p "--> sudo podman create --pod podtest fedora sleep 600"
216 | sudo podman create --pod podtest fedora sleep 600
217 | echo ""
218 |
219 | read -p "--> sudo podman create --pod podtest fedora sleep 600"
220 | sudo podman create --pod podtest fedora sleep 600
221 | echo ""
222 |
223 | echo "
224 | Notice that you have no containers running.
225 | "
226 | read -p "--> sudo podman ps"
227 | sudo podman ps
228 | echo ""
229 |
230 | read -p "--> sudo podman pod start podtest"
231 | sudo podman pod start podtest
232 | echo ""
233 |
234 | echo "
235 | Notice that the \"podman pod start podtest\" command started both containers.
236 | "
237 | read -p "--> sudo podman ps"
238 | sudo podman ps
239 | echo ""
240 |
241 | read -p "--> sudo podman pod stop podtest"
242 | sudo podman pod kill --signal KILL podtest
243 | echo ""
244 |
245 | echo "
246 | Notice that the \"podman pod stop podtest\" command stopped both containers.
247 | "
248 | read -p "--> sudo podman ps"
249 | sudo podman ps
250 | echo ""
251 |
252 | echo "
253 | Remove the pod and all of the containers
254 | "
255 | read -p "--> sudo podman pod rm --force podtest"
256 | sudo podman pod rm --force podtest
257 | echo ""
258 | clear
259 |
260 | echo "
261 | Pod should no longer exist
262 | "
263 | read -p "--> sudo podman pod list"
264 | sudo podman pod list
265 | echo ""
266 | }
267 |
268 | build() {
269 | echo ""
270 | # Already built an image with buildah installed in it
271 | # and made buildah the entrypoint
272 |
273 | sudo mkdir -p /var/lib/mycontainer
274 | mkdir -p $PWD/myvol
275 | cat >$PWD/myvol/Dockerfile <<_EOF
276 | FROM alpine
277 | ENV foo=bar
278 | LABEL colour=blue
279 | _EOF
280 |
281 | read -p "--> cat Dockerfile"
282 | cat $PWD/myvol/Dockerfile
283 | echo ""
284 | echo ""
285 | read -p "--> sudo podman run -v \$PWD/myvol:/myvol:Z -v /var/lib/mycontainer:/var/lib/containers:Z quay.io/buildah/stable buildah build -t myimage --isolation chroot /myvol"
286 |
287 | sudo podman run --net=host --device /dev/fuse -v $PWD/myvol:/myvol:Z -v /var/lib/mycontainer:/var/lib/containers:Z quay.io/buildah/stable buildah build -t myimage --isolation chroot /myvol
288 | echo ""
289 |
290 | read -p "--> sudo podman run --device /dev/fuse -v /var/lib/mycontainer:/var/lib/containers:Z quay.io/buildah/stable buildah images"
291 | sudo podman run --net=host -v /var/lib/mycontainer:/var/lib/containers:Z quay.io/buildah/stable buildah images
292 | echo ""
293 |
294 | read -p "--> sudo podman run -v /var/lib/mycontainer:/var/lib/containers:Z quay.io/buildah/stable buildah rmi --force --all"
295 | sudo podman run --net=host -v /var/lib/mycontainer:/var/lib/containers:Z quay.io/buildah/stable buildah rmi -f --all
296 | echo ""
297 |
298 | read -p "--> cleanup"
299 | echo "podman rm -a -f"
300 | sudo podman rm -a -f
301 | echo ""
302 |
303 | read -p "--> clear"
304 | clear
305 | }
306 |
307 | intro() {
308 | read -p "Podman Demos!"
309 | echo ""
310 | }
311 |
312 | setup
313 |
314 | intro
315 |
316 | version
317 |
318 | build
319 |
320 | rootless
321 |
322 | userns
323 |
324 | forkexec
325 |
326 | top
327 |
328 | pods
329 |
330 | read -p "End of Demo"
331 | echo "Thank you!"
332 |
--------------------------------------------------------------------------------
/running/SELinuxEscape/README.md:
--------------------------------------------------------------------------------
1 | # SELinuxEscape
2 |
3 | This script demonstrates what would happen if a container was to escape confinement
4 | You need to execute the podman.sh script in this directory.
5 |
6 | Podman, Docker, and auctl (audit daemon) executables required.
7 |
--------------------------------------------------------------------------------
/running/SELinuxEscape/breakout.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # breakout.sh demo script.
4 | # This script will demonstrate a lot of the features of podman, concentrating
5 | # on the security features.
6 |
7 | # Setting up some colors for helping read the demo output.
8 | # Comment out any of the below to turn off that color.
9 | bold=$(tput bold)
10 | blue=$(tput setaf 4)
11 | reset=$(tput sgr0)
12 |
13 | read_color() {
14 | read -p "${bold}$1${reset}"
15 | }
16 |
17 | echo_color() {
18 | echo "${blue}$1${reset}"
19 | }
20 |
21 | run() {
22 | echo
23 | echo_color "Inside container show SELinux label"
24 | echo
25 | read_color "--> id | grep --color=auto 'system_u:system_r:container_t:s0[^ ]*'"
26 | id | grep --color=auto 'system_u:system_r:container_t:s0[^ ]*'
27 | echo ""
28 | read_color "--> cat/etc/shadow"
29 | cat /etc/shadow
30 | echo ""
31 | read_color "--> touch /var/log/messages"
32 | touch /var/log/messages
33 | echo ""
34 | read_color "--> cd ${HOME}"
35 | cd $HOME
36 | echo ""
37 | read_color "--> ls ${HOME}/.ssh"
38 | ls ${HOME}/.ssh
39 | echo ""
40 | read_color "--> ls /proc/1/"
41 | ls /proc/1/
42 | echo ""
43 | read_color "--> systemctl status docker"
44 | systemctl status docker
45 | echo ""
46 | read_color "--> docker run fedora echo hello"
47 | docker run fedora echo hello
48 | echo ""
49 | }
50 |
51 | run
52 |
--------------------------------------------------------------------------------
/running/SELinuxEscape/podman.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | # podmah.sh demo script.
4 | # This script will demonstrate a lot of the features of podman, concentrating
5 | # on the security features.
6 |
7 | # Setting up some colors for helping read the demo output.
8 | # Comment out any of the below to turn off that color.
9 | bold=$(tput bold)
10 | blue=$(tput setaf 4)
11 | reset=$(tput sgr0)
12 |
13 | read_color() {
14 | read -p "${bold}$1${reset}"
15 | }
16 |
17 | echo_color() {
18 | echo "${blue}$1${reset}"
19 | }
20 |
21 | setup() {
22 | rpm -q podman audit >/dev/null
23 | if [[ $? != 0 ]]; then
24 | echo $0 requires the podman and audit packages be installed
25 | exit 1
26 | fi
27 | command -v docker > /dev/null
28 | if [[ $? != 0 ]]; then
29 | echo $0 requires the docker package be installed
30 | exit 1
31 | fi
32 | sudo systemctl restart auditd 2> /dev/null
33 | sudo systemctl restart docker
34 | chcon -t container_file_t breakout.sh
35 | chmod +x breakout.sh
36 | clear
37 | }
38 |
39 | audit() {
40 | echo ""
41 | echo_color "Lets look at the audit log to see what SELinux is reporting"
42 | echo
43 | read_color "--> sudo ausearch -m avc -ts recent | grep shadow | tail -1 | grep --color=auto 'system_u:system_r:container_t:s0[^ ]*'"
44 | echo
45 | sudo ausearch -m avc -ts recent | grep shadow | tail -1 | grep --color=auto 'system_u:system_r:container_t:s0[^ ]*'
46 | echo ""
47 | echo
48 | read_color "--> sudo ausearch -m avc -ts recent | grep docker | tail -1 | grep --color=auto 'docker'"
49 | echo
50 | sudo ausearch -m avc -ts recent | grep docker | tail -1 | grep --color=auto 'docker'
51 | echo ""
52 | read -p "--> clear"
53 | clear
54 | }
55 |
56 | run() {
57 | echo_color "Run Container with SELinux Breakout"
58 | echo
59 | read_color "--> sudo podman run -e HOME=\$HOME -rm -ti -v /:/host fedora chroot /host \${PWD}/breakout.sh"
60 | sudo podman run -e HOME=$HOME -rm -ti -v /:/host fedora chroot /host ${PWD}/breakout.sh
61 | read -p "--> clear"
62 | clear
63 | }
64 |
65 | setup
66 |
67 | run
68 |
69 | audit
70 |
71 | read -p "End of Demo"
72 | echo "Thank you!"
73 |
--------------------------------------------------------------------------------
/running/demo.sh:
--------------------------------------------------------------------------------
1 | pushd restapi
2 | ./restapi.sh
3 | popd
4 | pushd generatesystemd
5 | ./podman-generate-systemd.sh
6 | popd
7 |
--------------------------------------------------------------------------------
/running/generatekube/README.md:
--------------------------------------------------------------------------------
1 | ## Podman generate kube demo
2 |
3 | This demo demonstrates how to use the `podman generate kube` command. It requires
4 | a functioning Kubernetes environment and will use the `kubectl` command to create
5 | and remove pods and containers.
6 |
7 | Requires podman, kubctl, firefox
8 |
--------------------------------------------------------------------------------
/running/generatekube/kubedemo-openshift.sh:
--------------------------------------------------------------------------------
1 | #!/bin/bash
2 |
3 | trap 'exit 0' INT
4 |
5 | # Setting up some colors for helping read the demo output.
6 | # Comment out any of the below to turn off that color.
7 | bold=$(tput bold)
8 | blue=$(tput setaf 4)
9 | reset=$(tput sgr0)
10 |
11 | read_color() {
12 | read -p "${bold}$1${reset}"
13 | }
14 |
15 | echo_color() {
16 | echo "${blue}$1${reset}"
17 | }
18 |
19 | setup () {
20 | # Verify podman exists
21 | if ! hash podman 2>/dev/null; then
22 | echo "Unable to find the podman commmand"
23 | exit 1
24 | fi
25 |
26 | # Verify oc exists
27 | if ! hash oc 2>/dev/null; then
28 | echo "Unable to find the oc commmand"
29 | exit 1
30 | fi
31 |
32 | podman image exists quay.io/sallyom/hello-openshift:latest
33 | rc=$?; if [[ $rc != 0 ]]; then podman pull quay.io/sallyom/hello-openshift:latest; fi
34 | podman image exists quay.io/sallyom/hello-openshift:latest
35 | mkdir -p /tmp/hello-openshift-container
36 | }
37 |
38 | cleanPodmanContainers() {
39 | podman stop -a -t 1
40 | podman rm -fa
41 | }
42 |
43 | cleanKube() {
44 | oc delete pod --all
45 | oc delete --force --grace-period=0 project hello-openshift
46 | }
47 |
48 | tailContainer () {
49 | echo_color "Execute ^c to exit the log"
50 | echo ""
51 | read_color "$ podman logs -lf"
52 | while [ 0 -eq 0 ]
53 | do
54 | trap break INT
55 | podman logs -lf
56 | done
57 | echo ""
58 | trap 'exit 0' INT
59 | clear
60 | }
61 |
62 | watchPods() {
63 | read_color "$ oc get pods --watch "
64 | while [ 0 -eq 0 ]
65 | do
66 | trap break INT
67 | oc get pods --watch
68 | done
69 | echo ""
70 | trap 'exit 0' INT
71 | }
72 |
73 | runCommand() {
74 | echo ""
75 | read_color "$ $1"
76 | $1
77 | echo ""
78 | read -p "Continue"
79 | clear
80 | }
81 |
82 | runPipeCommand() {
83 | echo ""
84 | read_color "$ $1 > $2"
85 | $1 > $2
86 | echo ""
87 | read -p "Continue"
88 | clear
89 | }
90 |
91 | sendMessage() {
92 | echo ""
93 | echo_color "$1"
94 | echo ""
95 | }
96 |
97 | sendMessageWait() {
98 | echo ""
99 | read_color "$1"
100 | echo ""
101 | }
102 |
103 | setup
104 | clear
105 |
106 |
107 | ##
108 | ## Create hello-openshift as a container
109 | ##
110 | sendMessage "Use runlabel create components as containers only"
111 | sendMessage "Create the hello-openshift container"
112 | runCommand "podman container runlabel run quay.io/sallyom/hello-openshift:latest"
113 | sendMessage "Check the logs to make sure the container is running"
114 | tailContainer
115 |
116 | ##
117 | ## Show our containers
118 | ##
119 | runCommand "podman ps"
120 |
121 | ##
122 | ## Create YAML for containers
123 | ##
124 | sendMessage "Podman can generate YAML based on a container"
125 | runCommand "podman generate kube --help"
126 |
127 | sendMessage "Generate Kubernetes YAML for 'hello'"
128 | runCommand "podman generate kube hello"
129 |
130 | sendMessage "Run for each container and pipe to a file"
131 | sendMessage "Generate Kubernetes YAML for 'hello'"
132 | runPipeCommand "podman generate kube hello" "/tmp/hello-openshift-container/hello.yaml"
133 |
134 | ##
135 | ## Create Components in Kube
136 | ##
137 | sendMessage "Start creating the components in OpenShift"
138 | sendMessage "Create openshift-hello"
139 | runCommand "oc new-project hello-openshift"
140 |
141 | sendMessage "Create openshift-hello"
142 | runCommand "oc create -f /tmp/hello-openshift-container/hello.yaml"
143 | watchPods
144 |
145 | sendMessage "Expose the pod/hello to create a service"
146 | runCommand "oc expose pod/hello"
147 |
148 | sendMessage "Expose the service/hello to create a route"
149 | runCommand "oc expose service/hello"
150 |
151 | sendMessage "Check the route/hello was created"
152 | route=$(oc get route/hello | awk 'END {print $2}')
153 | runCommand "oc get route/hello"
154 |
155 | sendMessage "Curl http://$route"
156 | runCommand "curl http://$route"
157 |
158 | sendMessageWait "Next keystroke cleans up podman containers and OpenShift"
159 | cleanPodmanContainers
160 | cleanKube
161 |
--------------------------------------------------------------------------------
/running/generatekube/kubedemo.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env bash
2 |
3 | trap 'exit 0' INT
4 |
5 | # Setting up some colors for helping read the demo output.
6 | # Comment out any of the below to turn off that color.
7 | bold=$(tput bold)
8 | blue=$(tput setaf 4)
9 | reset=$(tput sgr0)
10 |
11 | read_color() {
12 | read -p "${bold}$1${reset}"
13 | }
14 |
15 | echo_color() {
16 | echo "${blue}$1${reset}"
17 | }
18 |
19 | setup () {
20 | # Verify podman exists
21 | if ! hash podman 2>/dev/null; then
22 | echo "Unable to find the podman commmand"
23 | exit 1
24 | fi
25 |
26 | # Verify kubectl exists
27 | if ! hash kubectl 2>/dev/null; then
28 | echo "Unable to find the kubectl commmand"
29 | exit 1
30 | fi
31 | # Verify firefox exists
32 | if ! hash firefox 2>/dev/null; then
33 | echo "Unable to find the firefox commmand"
34 | exit 1
35 | fi
36 | sudo systemctl restart crio
37 | rc=$?; if [[ $rc != 0 ]]; then
38 | echo "Unable to start the crio daemon"
39 | exit 1
40 | fi
41 |
42 | sudo podman image exists quay.io/baude/demodb:latest
43 | rc=$?; if [[ $rc != 0 ]]; then sudo podman pull quay.io/baude/demodb:latest; fi
44 | sudo podman image exists quay.io/baude/demogen:latest
45 | rc=$?; if [[ $rc != 0 ]]; then sudo podman pull quay.io/baude/demogen:latest; fi
46 | sudo podman image exists quay.io/baude/demoweb:latest
47 | rc=$?; if [[ $rc != 0 ]]; then sudo podman pull quay.io/baude/demoweb:latest; fi
48 |
49 | sudo podman stop -t 0 demodb demogen demoweb 2>/dev/null
50 | sudo podman rm -f demodb demogen demoweb 2>/dev/null
51 | mkdir -p /tmp/kube-container
52 | mkdir -p /tmp/kube-pod
53 | }
54 |
55 | cleanPodmanContainers() {
56 | sudo podman stop -a -t 1
57 | sudo podman rm -fa
58 | }
59 |
60 | cleanKube() {
61 | sudo kubectl delete svc demoweb
62 | sudo kubectl delete pod --all
63 | }
64 |
65 | tailContainer () {
66 | echo_color "Execute ^c to exit the log"
67 | echo ""
68 | read_color "$ sudo podman logs -lf"
69 | while [ 0 -eq 0 ]
70 | do
71 | trap break INT
72 | sudo podman logs -lf
73 | done
74 | echo ""
75 | trap 'exit 0' INT
76 | clear
77 | }
78 |
79 | watchPods() {
80 | read_color "$ sudo kubectl get pods --watch "
81 | while [ 0 -eq 0 ]
82 | do
83 | trap break INT
84 | sudo kubectl get pods --watch
85 | done
86 | echo ""
87 | trap 'exit 0' INT
88 | }
89 |
90 | runCommand() {
91 | echo ""
92 | read_color "$ $1"
93 | $1
94 | echo ""
95 | read -p "Continue"
96 | clear
97 | }
98 |
99 | runPipeCommand() {
100 | echo ""
101 | read_color "$ $1 > $2"
102 | $1 > $2
103 | echo ""
104 | read -p "Continue"
105 | clear
106 | }
107 |
108 | sendMessage() {
109 | echo ""
110 | echo_color "$1"
111 | echo ""
112 | }
113 |
114 | sendMessageWait() {
115 | echo ""
116 | read_color "$1"
117 | echo ""
118 | }
119 |
120 | setup
121 | clear
122 |
123 |
124 | ##
125 | ## Create demodb as a container
126 | ##
127 | sendMessage "Use runlabel create components as containers only"
128 | sendMessage "Create the database container"
129 | runCommand "sudo podman container runlabel run quay.io/baude/demodb:latest"
130 | sendMessage "Check the logs to make sure the database is running"
131 | tailContainer
132 |
133 |
134 | ##
135 | ## Create demogen as a container
136 | ##
137 | sendMessage "Create the workload generator"
138 | runCommand "sudo podman container runlabel run quay.io/baude/demogen:latest"
139 | sendMessage "Check the logs to make sure the generator is running"
140 | tailContainer
141 |
142 | ##
143 | ## Create demoweb as a container
144 | ##
145 | sendMessage "Create the web-client"
146 | runCommand "sudo podman container runlabel run quay.io/baude/demoweb:latest"
147 | sendMessage "Check the logs to make sure the generator is running"
148 | tailContainer
149 |
150 | ##
151 | ## Use firefox to connect to web service
152 | ##
153 | sendMessage "Connect to web-client using firefox"
154 | web=$(sudo podman logs -l | grep http | cut -f 5 -d ' ')
155 | runCommand "firefox $web"
156 |
157 | ##
158 | ## Show our containers
159 | ##
160 | runCommand "sudo podman ps"
161 |
162 | ##
163 | ## Create YAML for containers
164 | ##
165 | sendMessage "Podman can generate YAML based on a container"
166 | runCommand "sudo podman generate kube --help"
167 |
168 | sendMessage "Generate Kubernetes YAML for 'demodb'"
169 | runCommand "sudo podman generate kube demodb"
170 |
171 | sendMessage "Run for each container and pipe to a file"
172 | sendMessage "Generate Kubernetes YAML for 'demodb'"
173 | runPipeCommand "sudo podman generate kube demodb" "/tmp/kube-container/demodb.yaml"
174 |
175 | sendMessage "Generate Kubernetes YAML for 'demogen'"
176 | runPipeCommand "sudo podman generate kube demogen" "/tmp/kube-container/demogen.yaml"
177 | sendMessage "Generate Kubernetes YAML and a service for 'demoweb'"
178 | runPipeCommand "sudo podman generate kube -s demoweb" "/tmp/kube-container/demoweb.yaml"
179 |
180 |
181 | ##
182 | ## Create Components in Kube
183 | ##
184 | sendMessage "Start creating the components in minkube"
185 | sendMessage "Create demodb"
186 | runCommand "sudo kubectl create -f /tmp/kube-container/demodb.yaml"
187 | watchPods
188 |
189 | sendMessage "Create demogen"
190 | runCommand "sudo kubectl create -f /tmp/kube-container/demogen.yaml"
191 | watchPods
192 |
193 | sendMessage "Create demoweb"
194 | runCommand "sudo kubectl create -f /tmp/kube-container/demoweb.yaml"
195 | watchPods
196 |
197 | sendMessage "Check demoweb service"
198 | runCommand "sudo kubectl get svc"
199 |
200 | sendMessage "Check the IP for the demoweb pod"
201 | runCommand "sudo kubectl describe pod demoweb"
202 |
203 |
204 |
205 | IP=`sudo kubectl describe pod demoweb | grep "Node:" | cut -f2 --delimiter /`
206 | PORT=`sudo kubectl get svc --no-headers=true demoweb | awk '{print $5}' | cut -f 2 --delimiter : | sed -e "s/\/TCP//g"`
207 |
208 | sendMessage "Connect web browser to http://$IP:$PORT"
209 |
210 | sendMessageWait "Next keystroke cleans up podman containers and kube"
211 | cleanPodmanContainers
212 | cleanKube
213 |
--------------------------------------------------------------------------------
/running/generatesystemd/podman-generate-systemd.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Setting up some colors for helping read the demo output.
4 | bold=$(tput bold)
5 | bright=$(tput setaf 14)
6 | yellow=$(tput setaf 11)
7 | reset=$(tput sgr0)
8 |
9 | # commands
10 | read_bright() {
11 | read -p "${bold}${bright}$1${reset}"
12 | }
13 | echo_bright() {
14 | echo "${bold}${bright}$1${reset}"
15 | }
16 |
17 | # headings
18 | read_yellow() {
19 | read -p "${bold}${yellow}$1${reset}"
20 | }
21 |
22 | cleanup() {
23 | echo_bright "--> cleanup"
24 | echo ""
25 | podman stop -f -t 0 topservice 2> /dev/null
26 | podman rm -f topservice 2> /dev/null
27 | rm ~/.config/systemd/user/sometop.service
28 | }
29 |
30 | cmd() {
31 | command=$*
32 | read_bright "--> $command"
33 | $command
34 | echo ""
35 | }
36 |
37 | trap cleanup EXIT
38 | podman_generate_systemd() {
39 | clear
40 | read_yellow "Let's create a systemd service to run a container image"
41 | echo ""
42 |
43 | read_bright "--> podman run -ti ubi8-init"
44 | podman run -ti ubi8-init
45 | echo ""
46 |
47 | cmd clear
48 |
49 | cmd podman generate systemd --help
50 |
51 | read_yellow "Now I will create a container running top"
52 | read_bright "--> podman create --name topservice alpine:latest top"
53 | podman create --name topservice alpine:latest top
54 | echo ""
55 |
56 | read_bright "--> podman generate systemd --name topservice > ~/.config/systemd/user/sometop.service"
57 | podman generate systemd --name topservice > ~/.config/systemd/user/sometop.service
58 | echo ""
59 |
60 | cmd clear
61 |
62 | cmd less ~/.config/systemd/user/sometop.service
63 |
64 | clear
65 |
66 | cmd systemctl --user daemon-reload
67 |
68 | cmd podman ps
69 |
70 | read_yellow "when you start the service, you start the container"
71 |
72 | cmd systemctl --user start sometop.service
73 |
74 | cmd podman ps
75 |
76 | read_yellow "when you stop the service, you stop the container"
77 |
78 | cmd systemctl --user stop sometop.service
79 |
80 | cmd podman ps
81 |
82 | cmd podman logs topservice
83 |
84 | cmd clear
85 | }
86 |
87 | podman_generate_systemd
88 |
--------------------------------------------------------------------------------
/running/restapi/docker-compose.yml:
--------------------------------------------------------------------------------
1 | version: '3'
2 | services:
3 | app:
4 | build: myapp
5 | command: sleep 10002
6 |
--------------------------------------------------------------------------------
/running/restapi/myapp/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM alpine
2 | WORKDIR /app
3 |
--------------------------------------------------------------------------------
/running/restapi/restapi.sh:
--------------------------------------------------------------------------------
1 | #!/bin/sh
2 |
3 | # Setting up some colors for helping read the demo output.
4 | bold=$(tput bold)
5 | bright=$(tput setaf 14)
6 | yellow=$(tput setaf 11)
7 | reset=$(tput sgr0)
8 |
9 | # commands
10 | read_bright() {
11 | read -p "${bold}${bright}$1${reset}"
12 | }
13 | echo_bright() {
14 | echo "${bold}${bright}$1${reset}"
15 | }
16 |
17 | # headings
18 | read_yellow() {
19 | read -p "${bold}${yellow}$1${reset}"
20 | }
21 |
22 | setup() {
23 | sudo systemctl stop docker.socket
24 | sudo systemctl stop docker.service
25 | }
26 | cleanup() {
27 | setup
28 | echo_bright "--> cleanup"
29 | echo ""
30 | # podman stop -f -t 0 topservice 2> /dev/null
31 | # podman rm -f topservice 2> /dev/null
32 | }
33 |
34 | trap cleanup EXIT
35 | restapi() {
36 | clear
37 | echo_bright "Let's try out Docker on my machine"
38 | echo ""
39 |
40 | read_yellow "sudo docker version"
41 | read_bright "--> sudo docker version"
42 | sudo docker version
43 |
44 | echo ""
45 |
46 | cmd="sudo systemctl status docker"
47 | read_bright "--> $cmd"
48 | $cmd | grep -E --color "Active.*)|"
49 |
50 | echo ""
51 |
52 | cmd="sudo podman --remote version"
53 | read_bright "--> $cmd"
54 | $cmd
55 | echo ""
56 |
57 | cmd="sudo systemctl status podman.socket"
58 | read_bright "--> $cmd"
59 | $cmd
60 | echo ""
61 |
62 | cmd="sudo DOCKER_HOST=unix:///var/run/podman/podman.sock docker version"
63 | read_bright "--> $cmd"
64 | $cmd | grep -E --color "Podman.*|"
65 | echo ""
66 |
67 | cmd="sudo DOCKER_HOST=unix:///var/run/podman/podman.sock docker info"
68 | read_bright "--> $cmd"
69 | $cmd | grep -E --color "Containers.*|"
70 | echo ""
71 |
72 | cmd="sudo podman info"
73 | read_bright "--> $cmd"
74 | $cmd | grep -E --color "number.*|"
75 | echo ""
76 |
77 | cmd="sudo DOCKER_HOST=unix:///var/run/podman/podman.sock docker run registry.access.redhat.com/ubi8-micro printenv"
78 | read_bright "--> $cmd"
79 | $cmd | grep -E --color "container=podman|"
80 | echo ""
81 |
82 | read_bright "Demo Complete"
83 |
84 | clear
85 | }
86 | compose() {
87 | clear
88 | echo_bright "Now let's try out docker-compose in rootless mode"
89 | echo ""
90 | echo ""
91 | cmd="systemctl --user start podman.socket"
92 | read_bright "--> $cmd"
93 | $cmd
94 |
95 | echo ""
96 | cmd="podman --remote version"
97 | read_bright "--> $cmd"
98 | $cmd
99 | echo ""
100 |
101 | cmd="systemctl --user status podman.socket"
102 | read_bright "--> $cmd"
103 | $cmd | grep -E --color "/run.*sock|"
104 |
105 | cmd="DOCKER_HOST=unix:///run/user/3267/podman/podman.sock docker run registry.access.redhat.com/ubi8-micro printenv"
106 | read_bright "--> $cmd"
107 | eval $cmd | grep -E --color "container=podman|"
108 |
109 | echo ""
110 | cmd="podman ps"
111 | read_bright "--> $cmd"
112 | $cmd
113 | echo ""
114 |
115 | cmd="DOCKER_HOST=unix:///run/user/3267/podman/podman.sock docker-compose up -d"
116 | read_bright "--> $cmd"
117 | eval $cmd
118 |
119 | echo ""
120 | cmd="podman ps"
121 | read_bright "--> $cmd"
122 | $cmd
123 | echo ""
124 |
125 | cmd="DOCKER_HOST=unix:///run/user/3267/podman/podman.sock docker-compose down"
126 | read_bright "--> $cmd"
127 | eval $cmd
128 |
129 | echo ""
130 | cmd="podman ps"
131 | read_bright "--> $cmd"
132 | $cmd
133 | echo ""
134 | }
135 |
136 | setup
137 | restapi
138 | compose
139 |
--------------------------------------------------------------------------------
/running/restapi/tests.sh:
--------------------------------------------------------------------------------
1 | # -*- bash -*-
2 |
3 | sed -i -e 's/10001/10002/' docker-compose.yml
4 | docker-compose up -d
5 |
--------------------------------------------------------------------------------
/security/SELinuxUdica/.gitignore:
--------------------------------------------------------------------------------
1 | my_container.cil
2 |
--------------------------------------------------------------------------------
/security/SELinuxUdica/README.md:
--------------------------------------------------------------------------------
1 | # SELinuxUdica
2 |
3 | This script demonstrates creating specific SELinux security policy for example container.
4 |
5 | You need to execute the SELinuxUdica.sh script in this directory. SELinux policy for example container "my_container.cil" will be created.
6 |
--------------------------------------------------------------------------------
/security/SELinuxUdica/SELinuxUdica.sh:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env sh
2 |
3 | read -p "Using SELinux with container runtimes "
4 | echo ""
5 |
6 | read -p "--> dnf install udica podman setools-console "
7 | echo ""
8 | sudo dnf install udica podman setools-console -y
9 | echo ""
10 |
11 | read -p "--> getenforce"
12 | echo ""
13 | getenforce
14 | echo ""
15 |
16 | read -p "--> podman run -v /home:/home:rw -v /var/spool:/var/spool:ro -p 21:21 -d fedora sleep 1h"
17 | echo ""
18 | sudo podman run -v /home:/home:rw -v /var/spool:/var/spool:ro -p 21:21 -d fedora sleep 1h
19 | echo ""
20 |
21 | read -p "--> podman top -l label"
22 | echo ""
23 | sudo podman top -l label
24 | echo ""
25 |
26 | echo "--> sesearch -A -s container_t -t home_root_t -c dir -p read"
27 | echo ""
28 | sesearch -A -s container_t -t home_root_t -c dir -p read
29 | echo ""
30 |
31 | echo "--> sesearch -A -s container_t -t var_spool_t -c dir -p read"
32 | echo ""
33 | sesearch -A -s container_t -t var_spool_t -c dir -p read
34 | echo ""
35 |
36 |
37 | echo "--> sesearch -A -s container_t -t port_type -c tcp_socket"
38 | echo ""
39 | sesearch -A -s container_t -t port_type -c tcp_socket
40 | echo ""
41 |
42 | read -p "--> podman ps"
43 | echo ""
44 | sudo podman ps
45 | echo ""
46 |
47 | read -p "--> podman inspect -l | udica my_container
48 | "
49 | echo ""
50 | sudo podman inspect -l | sudo udica my_container
51 | echo ""
52 |
53 | echo "--> semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}"
54 | echo ""
55 | sudo semodule -i my_container.cil /usr/share/udica/templates/{base_container.cil,net_container.cil,home_container.cil}
56 | echo ""
57 |
58 | read -p "--> podman stop -l"
59 | echo ""
60 | sudo podman stop -l
61 | echo ""
62 |
63 | read -p "--> podman run --security-opt label=type:my_container.process -v /home:/home:rw -v /var/spool:/var/spool:ro -p 21:21 -d fedora sleep 1h"
64 | echo ""
65 | sudo podman run --security-opt label=type:my_container.process -v /home:/home:rw -v /var/spool:/var/spool:ro -p 21:21 -d fedora sleep 1h
66 | echo ""
67 |
68 | read -p "--> podman top -l label"
69 | echo ""
70 | sudo podman top -l label
71 | echo ""
72 |
73 | echo "--> sesearch -A -s my_container.process -t home_root_t -c dir -p read"
74 | echo ""
75 | sesearch -A -s my_container.process -t home_root_t -c dir -p read
76 | echo ""
77 |
78 | echo "--> sesearch -A -s my_container.process -t var_spool_t -c dir -p read"
79 | echo ""
80 | sesearch -A -s my_container.process -t var_spool_t -c dir -p read
81 | echo ""
82 |
83 |
84 | echo "--> sesearch -A -s my_container.process -t port_type -c tcp_socket"
85 | echo ""
86 | sesearch -A -s my_container.process -t port_type -c tcp_socket
87 | echo ""
88 |
89 | echo "--> cleanup"
90 | echo ""
91 | sudo podman stop -l
92 | sudo semodule -r my_container base_container net_container home_container &> /dev/null
93 | echo ""
94 |
95 | echo "Enf of Demo."
96 |
--------------------------------------------------------------------------------
/security/container_demo.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "name": "podsandbox1-fedora"
4 | },
5 | "image": {
6 | "image": "docker.io/library/fedora"
7 | },
8 | "args": [
9 | "/bin/bash"
10 | ],
11 | "working_dir": "/",
12 | "envs": [
13 | {
14 | "key": "PATH",
15 | "value": "/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"
16 | },
17 | {
18 | "key": "TERM",
19 | "value": "xterm"
20 | },
21 | {
22 | "key": "DISTTAG",
23 | "value": "f26container"
24 | },
25 | {
26 | "key": "FGC",
27 | "value": "f26"
28 | },
29 | {
30 | "key": "NAME",
31 | "value": "redis"
32 | },
33 | {
34 | "key": "VERSION",
35 | "value": "0"
36 | },
37 | {
38 | "key": "RELEASE",
39 | "value": "6"
40 | },
41 | {
42 | "key": "ARCH",
43 | "value": "x86_64"
44 | },
45 | {
46 | "key": "REDIS_VERSION",
47 | "value": "0"
48 | },
49 | {
50 | "key": "HOME",
51 | "value": "/home"
52 | },
53 | {
54 | "key": "CONTAINER_SCRIPTS_PATH",
55 | "value": "/usr/share/container-scripts/redis"
56 | },
57 | {
58 | "key": "REDIS_PREFIX",
59 | "value": "/usr"
60 | }
61 | ],
62 | "labels": {
63 | "tier": "backend"
64 | },
65 | "annotations": {
66 | "pod": "podsandbox1"
67 | },
68 | "readonly_rootfs": false,
69 | "log_path": "",
70 | "stdin": true,
71 | "stdin_once": false,
72 | "tty": true,
73 | "linux": {
74 | "resources": {
75 | "memory_limit_in_bytes": 209715200,
76 | "cpu_period": 10000,
77 | "cpu_quota": 20000,
78 | "cpu_shares": 512,
79 | "oom_score_adj": 30,
80 | "cpuset_cpus": "0",
81 | "cpuset_mems": "0"
82 | },
83 | "security_context": {
84 | "run_as_user": {
85 | "value": 0
86 | },
87 | "namespace_options": {
88 | "pid": 1
89 | },
90 | "capabilities": {
91 | "add_capabilities": [
92 | "sys_admin"
93 | ]
94 | }
95 | }
96 | }
97 | }
98 |
--------------------------------------------------------------------------------
/security/sandbox_config.json:
--------------------------------------------------------------------------------
1 | {
2 | "metadata": {
3 | "name": "podsandbox1",
4 | "uid": "redhat-test-crio",
5 | "namespace": "redhat.test.crio",
6 | "attempt": 1
7 | },
8 | "hostname": "crictl_host",
9 | "log_directory": "",
10 | "dns_config": {
11 | "searches": [
12 | "8.8.8.8"
13 | ]
14 | },
15 | "port_mappings": [],
16 | "resources": {
17 | "cpu": {
18 | "limits": 3,
19 | "requests": 2
20 | },
21 | "memory": {
22 | "limits": 50000000,
23 | "requests": 2000000
24 | }
25 | },
26 | "labels": {
27 | "group": "test"
28 | },
29 | "annotations": {
30 | "owner": "hmeng",
31 | "security.alpha.kubernetes.io/seccomp/pod": "unconfined"
32 | },
33 | "linux": {
34 | "cgroup_parent": "/Burstable/pod_123-456",
35 | "security_context": {
36 | "namespace_options": {
37 | "network": 0,
38 | "pid": 1,
39 | "ipc": 0
40 | },
41 | "selinux_options": {
42 | "user": "system_u",
43 | "role": "system_r",
44 | "type": "svirt_lxc_net_t",
45 | "level": "s0:c4,c5"
46 | }
47 | }
48 | }
49 | }
50 |
--------------------------------------------------------------------------------