├── .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 | ![](.github/demo.svg) 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 | --------------------------------------------------------------------------------