Skip to content

Latest commit

 

History

History
628 lines (504 loc) · 21.9 KB

buildah.adoc

File metadata and controls

628 lines (504 loc) · 21.9 KB

Container Dev with Buildah and Skopeo

1. Overview

ℹ️
These exercises are an extension of the podman unit and although not required, it is strongly encourage that you complete that unit first.

In this unit, we will continue to work with containers and get familiar with Buildah and Skopeo.

2. Getting Started

For these exercises, you will be using the host node3 as user root.

From host bastion, ssh to node3.

ssh node3

Use sudo to elevate your priviledges.

sudo -i

Verify that you are on the right host for these exercises.

workshop-buildah-checkhost.sh

You are now ready to proceed with these exercises.

3. Create a Container Image With Buildah

In the previous lab on podman, we pulled down the ubi image and used an OCIFile to build a "webserver" container image. That process used buildah under the hood, but in this lab we are going to use buildah directly to create a similar image manually, step by step.

3.1. Start a Fresh Build

Let’s get started by creating a new working container based off of the ubi image.

buildah from ubi8/ubi
Getting image source signatures
Copying blob befb03b11956 done
Copying blob ee2244abc66f done
Copying config 8121a9f530 done
Writing manifest to image destination
Storing signatures
ubi-working-container

This gives us the name of the "working container" and it is this container image that we will modify with buildah.

3.2. Add a Custom File

Let’s run:

buildah copy ubi-working-container /var/tmp/buildah-dan-cries.txt /var/www/html/dan-cries.txt
34f1621a22ffd90a2ebbd58eba315089dc2704ac69a3d33d60362422e4ec26a1

At this point, you have copied your local dan-cries.txt into the the ubi-working-container image.

The steps you performed above is equivalent to the following OCIFile (or Dockerfile):

FROM ubi8/ubi
COPY /root/dan-cries.txt /var/www/html/

So it’s nice that we can do that with buildah, manually.

But wait there’s more!!!

3.3. Install Additional Packages

We need to install an httpd server in our image, and what better way to do that than a simple yum install.

buildah run ubi-working-container yum install -y httpd
...SNIP...
Installed:
  httpd-2.4.37-16.module+el8.1.0+4134+e6bad0ed.x86_64
  apr-util-bdb-1.6.1-6.el8.x86_64
  apr-util-openssl-1.6.1-6.el8.x86_64
  mailcap-2.1.48-3.el8.noarch
  redhat-logos-httpd-81.1-1.el8.noarch
  apr-util-1.6.1-6.el8.x86_64
  httpd-tools-2.4.37-16.module+el8.1.0+4134+e6bad0ed.x86_64
  apr-1.6.3-9.el8.x86_64
  mod_http2-1.11.3-3.module+el8.1.0+4134+e6bad0ed.x86_64
  httpd-filesystem-2.4.37-16.module+el8.1.0+4134+e6bad0ed.noarch

3.4. Configure the Entry Point

Next we set the entry point (command) so when the image deploys it knows what process to launch.

buildah config --cmd "/usr/sbin/httpd -D FOREGROUND" ubi-working-container

3.5. Validate the Container Image

Now let us take a peek at our image and validate some of our changes.

Proceed to mount the root filesystem of your container with:

buildah mount ubi-working-container
/var/lib/containers/storage/overlay/3456a159b5b3c9e3056d14b97bde1f0e770500dd1cdd6168c894a52a3b3f12ee/merged

Using the long path provided by your mount command, change directories.

cd /var/lib/containers/storage/overlay/3456a159b5b3c9e3056d14b97bde1f0e770500dd1cdd6168c894a52a3b3f12ee/merged
ls -lah ./var/www/html
total 16K
drwxr-xr-x. 2 root root 4.0K Apr 12 21:12 .
drwxr-xr-x. 3 root root 4.0K Apr 12 21:12 ..
-rw-r--r--. 1 root root   58 Apr 12 21:12 dan-cries.txt

There is our dan-cries.txt! Let’s add an additional file:

cp /var/tmp/buildah-index.html ./var/www/html/index.html
cat ./var/www/html/index.html
<html>
<title>Stop Disabling SELinux</title>
<body>
<p>
Seriously, stop disabling SELinux. Learn how to use it before you blindly shut it off.
</p>
</body>
</html>

Let us just double check contents of the httpd docroot one last time:

ls -lahZ ./var/www/html/
total 20K
drwxr-xr-x. 2 root root system_u:object_r:container_file_t:s0:c60,c544 4.0K Apr 12 21:25 .
drwxr-xr-x. 3 root root system_u:object_r:container_file_t:s0:c60,c544 4.0K Apr 12 21:12 ..
-rw-r--r--. 1 root root system_u:object_r:container_file_t:s0:c60,c544   58 Apr 12 21:12 dan-cries.txt
-rw-r--r--. 1 root root system_u:object_r:container_file_t:s0:c60,c544  164 Apr 12 21:24 index.html

When you are done making direct changes to the root filesystem of your container, you can run:

cd /root
buildah unmount ubi-working-container
e918debcaabb5820997b1a4969fbd45284adc0a2869d1f22a1bce78f703ff3c6

3.5.1. Commit Changes to New Image

At this point, we’ve used buildah to run commands and create a container image similar to those in the OCIFile used in the podman unit. Go ahead and commit the working container in to an actual container image:

buildah commit ubi-working-container webserver2
Getting image source signatures
Copying blob d3ada5af5602 skipped: already exists
Copying blob 668db11eda93 skipped: already exists
Copying blob 0f75b7e04ec6 done
Copying config a831badcea done
Writing manifest to image destination
Storing signatures
a831badcea41e924fd4a37f98431702142c17a64d06bd5444ac4471c1285be50

Let’s look at our images:

podman images
REPOSITORY                            TAG      IMAGE ID       CREATED          SIZE
localhost/webserver2                  latest   a831badcea41   25 seconds ago   240 MB
registry.access.redhat.com/ubi8/ubi   latest   8121a9f5303b   12 days ago      240 MB

3.5.2. Deploy

Now let’s run that webserver:

podman run -d -p 8080:80 webserver2

3.5.3. Validate

Finally let’s test our new webserver:

curl http://localhost:8080/
<html>
<title>Stop Disabling SELinux</title>
<body>
<p>
Seriously, stop disabling SELinux. Learn how to use it before you blindly shut it off.
</p>
</body>
</html>

and:

curl http://localhost:8080/dan-cries.txt
Every time you run setenforce 0, you make Dan Walsh weep.

As you can see, all of the changes we made with buildah are active and working in this new container image!

4. Inspecting Images with Skopeo

Let’s take a look at the webserver2:latest container that we just built:

skopeo inspect containers-storage:localhost/webserver2:latest
{
    "Name": "localhost/webserver2",
    "Digest": "sha256:15ad1feee74c68a16031b2120793873432572d2592e0818bc4cff9842696b651",
    "RepoTags": [],
    "Created": "2020-04-13T02:17:40.873320811Z",
    "DockerVersion": "",
    "Labels": {
        "architecture": "x86_64",
        "authoritative-source-url": "registry.access.redhat.com",
        "build-date": "2020-03-31T14:54:13.907559",
        "com.redhat.build-host": "cpt-1007.osbs.prod.upshift.rdu2.redhat.com",
        "com.redhat.component": "ubi8-container",
        "com.redhat.license_terms": "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI",
        "description": "The Universal Base Image is designed and engineered to be the base layer for all of your containerized applications, middleware and utilities. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.",
        "distribution-scope": "public",
        "io.k8s.description": "The Universal Base Image is designed and engineered to be the base layer for all of your containerized applications, middleware and utilities. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.",
        "io.k8s.display-name": "Red Hat Universal Base Image 8",
        "io.openshift.expose-services": "",
        "io.openshift.tags": "base rhel8",
        "maintainer": "Red Hat, Inc.",
        "name": "ubi8",
        "release": "408",
        "summary": "Provides the latest release of Red Hat Universal Base Image 8.",
        "url": "https://access.redhat.com/containers/#/registry.access.redhat.com/ubi8/images/8.1-408",
        "vcs-ref": "26f36bfa3e3a04c8c866b250924c1aefc34f01c9",
        "vcs-type": "git",
        "vendor": "Red Hat, Inc.",
        "version": "8.1"
    },
    "Architecture": "amd64",
    "Os": "linux",
    "Layers": [
        "sha256:d3ada5af5602bd0da378e4f0144f8fe8bdbe3f5a65f367dd9ebe759756bada68",
        "sha256:668db11eda933a46ae8030a8643b96088218dae0efeac54bc6dbc88488725c1b",
        "sha256:d9142adf6c6796bbbccc6065c57508e87138921d3aea0e9fc368f9861606da68"
    ]
}

We will see that this container is based on the Red Hat UBI image.

Let’s look at the ubi8/ubi container that we built this off of and compare the layers section:

skopeo inspect containers-storage:registry.access.redhat.com/ubi8/ubi:latest
{
    "Name": "registry.access.redhat.com/ubi8/ubi",
    "Digest": "sha256:f6648a87c8c52099bacd19b112beb3b65407ae6d3441f9b559ba53c4112c57a4",
    "RepoTags": [],
    "Created": "2020-03-31T14:54:42.119985Z",
    "DockerVersion": "1.13.1",
    "Labels": {
        "architecture": "x86_64",
        "authoritative-source-url": "registry.access.redhat.com",
        "build-date": "2020-03-31T14:54:13.907559",
        "com.redhat.build-host": "cpt-1007.osbs.prod.upshift.rdu2.redhat.com",
        "com.redhat.component": "ubi8-container",
        "com.redhat.license_terms": "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI",
        "description": "The Universal Base Image is designed and engineered to be the base layer for all of your containerized applications, middleware and utilities. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.",
        "distribution-scope": "public",
        "io.k8s.description": "The Universal Base Image is designed and engineered to be the base layer for all of your containerized applications, middleware and utilities. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.",
        "io.k8s.display-name": "Red Hat Universal Base Image 8",
        "io.openshift.expose-services": "",
        "io.openshift.tags": "base rhel8",
        "maintainer": "Red Hat, Inc.",
        "name": "ubi8",
        "release": "408",
        "summary": "Provides the latest release of Red Hat Universal Base Image 8.",
        "url": "https://access.redhat.com/containers/#/registry.access.redhat.com/ubi8/images/8.1-408",
        "vcs-ref": "26f36bfa3e3a04c8c866b250924c1aefc34f01c9",
        "vcs-type": "git",
        "vendor": "Red Hat, Inc.",
        "version": "8.1"
    },
    "Architecture": "amd64",
    "Os": "linux",
    "Layers": [
        "sha256:ee2244abc66ff9c6a4bf50fe19041fec82a95c87d18ee3a3660368cb274927c7",
        "sha256:befb03b11956169cf23096fc58081ca35034a6545fc37d63605bf0d200fe5eda"
    ]
}

Comparing the layers section, we can see that our container has 3 layers whereas the original container only has 2 layers. In this, we can tell that there are differences between these containers.

Pretty neat that we can look inside local containers, but what about containers that are in registries? Skopeo can inspect containers on remote registries without the need to pull the image locally. Let’s give that a test:

# skopeo inspect docker://registry.access.redhat.com/ubi8/ubi-minimal:latest
{
    "Name": "registry.access.redhat.com/ubi8/ubi-minimal",
    "Digest": "sha256:df6f9e5d689e4a0b295ff12abc6e2ae2932a1f3e479ae1124ab76cf40c3a8cdd",
    "RepoTags": [
        "8.1",
        "8.0",
        "8.1-409-source",
        "8.0-127",
        "8.0-204",
        "8.1-398-source",
        "8.0-213",
        "8.0-159",
        "8.1-328",
        "8.1-398",
        "8.1-409",
        "8.1-407-source",
        "8.1-407",
        "8.1-279",
        "latest",
        "8.0-131"
    ],
    "Created": "2020-03-31T14:52:10.793843Z",
    "DockerVersion": "1.13.1",
    "Labels": {
        "architecture": "x86_64",
        "authoritative-source-url": "registry.access.redhat.com",
        "build-date": "2020-03-31T14:51:49.719962",
        "com.redhat.build-host": "cpt-1002.osbs.prod.upshift.rdu2.redhat.com",
        "com.redhat.component": "ubi8-minimal-container",
        "com.redhat.license_terms": "https://www.redhat.com/en/about/red-hat-end-user-license-agreements#UBI",
        "description": "The Universal Base Image Minimal is a stripped down image that uses microdnf as a package manager. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.",
        "distribution-scope": "public",
        "io.k8s.description": "The Universal Base Image Minimal is a stripped down image that uses microdnf as a package manager. This base image is freely redistributable, but Red Hat only supports Red Hat technologies through subscriptions for Red Hat products. This image is maintained by Red Hat and updated regularly.",
        "io.k8s.display-name": "Red Hat Universal Base Image 8 Minimal",
        "io.openshift.expose-services": "",
        "io.openshift.tags": "minimal rhel8",
        "maintainer": "Red Hat, Inc.",
        "name": "ubi8-minimal",
        "release": "409",
        "summary": "Provides the latest release of the minimal Red Hat Universal Base Image 8.",
        "url": "https://access.redhat.com/containers/#/registry.access.redhat.com/ubi8-minimal/images/8.1-409",
        "vcs-ref": "8c3c7acc321ed054dded6e6e13b5c09c043f42dc",
        "vcs-type": "git",
        "vendor": "Red Hat, Inc.",
        "version": "8.1"
    },
    "Architecture": "amd64",
    "Os": "linux",
    "Layers": [
        "sha256:b26afdf22be4e9c30220796780a297b91549a3b3041b6fdcbda71bf48a6912e7",
        "sha256:218f593046abe6e9f194aed3fc2a2ad622065d6800175514dffa55dfce624b56"
    ]
}

The above allows us to look at the registry’s copy of ubi8/ubi.

Next let’s run:

podman images
REPOSITORY                            TAG      IMAGE ID       CREATED         SIZE
localhost/webserver2                  latest   b660ca86ee4b   7 minutes ago   271 MB
registry.access.redhat.com/ubi8/ubi   latest   8121a9f5303b   12 days ago     240 MB

Notice that ubi8/ubi-minimal is not local to our registry. Skopeo provided that inspection completely remotely.

4.1. Obtaining tarballs of containers in remote registries for further inspection

Let’s run:

mkdir /root/ubi-tarball
skopeo copy docker://registry.access.redhat.com/ubi8/ubi-minimal:latest dir:/root/ubi-tarball
Getting image source signatures
Copying blob b26afdf22be4 done
Copying blob 218f593046ab done
Copying config 91d23a64fd done
Writing manifest to image destination
Storing signatures

and now we can do:

cd /root/ubi-tarball
ls -l
total 33888
drwxr-xr-x. 2 root root     4096 Apr 13 09:48 .
dr-xr-x---. 5 root root     4096 Apr 13 09:48 ..
-rw-r--r--. 1 root root     1529 Apr 13 09:48 218f593046abe6e9f194aed3fc2a2ad622065d6800175514dffa55dfce624b56
-rw-r--r--. 1 root root     4457 Apr 13 09:48 91d23a64fdf259ffce4181b40ce3dafa982a9e4a76ae6a88c1e662c6166c7324
-rw-r--r--. 1 root root 34668948 Apr 13 09:48 b26afdf22be4e9c30220796780a297b91549a3b3041b6fdcbda71bf48a6912e7
-rw-r--r--. 1 root root      737 Apr 13 09:48 manifest.json
-rw-r--r--. 1 root root       33 Apr 13 09:48 version

Inspecting the images with the file command, we discover that these a couple of text file along with a couple of zipped (compressed) tar files.

file *
218f593046abe6e9f194aed3fc2a2ad622065d6800175514dffa55dfce624b56: gzip compressed data, original size 20480
91d23a64fdf259ffce4181b40ce3dafa982a9e4a76ae6a88c1e662c6166c7324: ASCII text, with very long lines
b26afdf22be4e9c30220796780a297b91549a3b3041b6fdcbda71bf48a6912e7: gzip compressed data, original size 108462080
manifest.json:                                                    ASCII text
version:                                                          ASCII text

Let’s take a test view of the contents of the largest gzip file (examine "original size"):

# tar tvzf b26afdf22be4e9c30220796780a297b91549a3b3041b6fdcbda71bf48a6912e7
dr-xr-xr-x root/root         0 2020-03-31 10:48 ./
lrwxrwxrwx root/root         0 2018-08-12 05:46 ./lib64 -> usr/lib64
lrwxrwxrwx root/root         0 2018-08-12 05:46 ./lib -> usr/lib
drwxr-xr-x root/root         0 2020-03-31 10:48 ./etc/
drwxr-xr-x root/root         0 2020-03-31 10:48 ./etc/libssh/
-rw-r--r-- root/root       178 2019-08-05 10:32 ./etc/libssh/libssh_client.config
-rw-r--r-- root/root       179 2019-08-05 10:32 ./etc/libssh/libssh_server.config
-rw-r--r-- root/root        22 2019-09-25 14:17 ./etc/issue.net
-rw-r--r-- root/root      1498 2019-11-28 12:53 ./etc/nsswitch.conf.bak
-rw-r--r-- root/root        55 2020-03-31 10:47 ./etc/resolv.conf
drwxr-xr-x root/root         0 2018-08-12 05:46 ./etc/bash_completion.d/
lrwxrwxrwx root/root         0 2018-09-10 10:14 ./etc/rc0.d -> rc.d/rc0.d
-rw-r--r-- root/root      9490 2020-03-31 10:48 ./etc/ld.so.cache
-rw-r--r-- root/root        58 2018-09-10 07:51 ./etc/networks
-rw-r--r-- root/root      1362 2018-09-10 07:51 ./etc/ethertypes
... SNIP...

The output is going to scroll by rather quickly, but just note that this is a complete filesystem for the container image.

ℹ️
If you are more curious and would like to inspect the details a little further you could pipe the output to more or less and page through the archive contents. tar tvzf b26afdf22be4e9c30220796780a297b91549a3b3041b6fdcbda71bf48a6912e7 | less

The other two numeric files provided in the image download are:

  • a copy of the metadata in text

  • an additional tarball of any container secrets

Lastly, a couple of ASCII text files:

  • oci config info used to build the container

  • version info

  • manifest info

4.2. Other Uses of Skopeo

Skopeo can also do the following things:

  • Copy an image (manifest, filesystem layers, signatures) from one location to another. It can convert between manifest types in doing this (oci, v2s1, v2s2)

  • Delete images from registries that you have admin rights to.

  • Push images to registries that you have push rights to.

Examples of how to do these things are available in 'man skopeo'

4.3. Cleanup

podman stop --all
podman rm --all

buildah rm --all

podman rmi --all
buildah rmi --all

Additional Reference Materials

ℹ️
You are not required to reference any additional resources for these exercises. This is informational only.

End of Unit