Skip to main content

How to update container images with Podman

Keeping your images current is standard procedure for operating and managing a containerized environment. Here's how to do it.
Image
Container ships docked

Image by Hessel Visser from Pixabay

Podman is a daemon-less engine for developing, managing, and running Open Container Initiative (OCI)-compliant containers. This is the fourth article in a series about using Podman based on things I do in my real work environment. Previously, I showed how to display networking information with Podman, including containers and pod IP addresses.

Before reading this article, make sure you've read the first three parts: 

This article demonstrates how to update container images. Keeping running containers and pods current with the most up-to-date image changes is important. To follow along with this article, first run the shell scripts I used in the "Setting things up" section of the first article in this series.

Inspect images before updating

Before updating any images, it's important to understand what changes from one image version to another. Tracking these changes allows you to understand their impact on your environment. In certain scenarios, it might be useful to use more in-depth inspection tools like Skopeo, which allows you to inspect "a remote image showing its properties including its layers, without requiring you to pull the image to the host." You could also check the image's Dockerfile to get update information. However, the Podman command-line interface (CLI) alone can help you gather some of this information.

This example shows the images I have been using since the first article:

$ podman image ls
REPOSITORY                   TAG         IMAGE ID      CREATED        SIZE
docker.io/library/wordpress  latest      054741915cf1  6 weeks ago    629 MB
docker.io/library/mysql      latest      bbf6571db497  6 weeks ago    521 MB
docker.io/library/httpd      latest      ea28e1b82f31  6 weeks ago    148 MB
k8s.gcr.io/pause             3.5         ed210e3e4a5b  10 months ago  690 kB

I'll use the httpd image for this demonstration. In the CREATED column, Podman reports that the image with the latest tag was created six weeks ago. You can get the image history to check what was done to this image when it was created:

$ podman image history httpd
ID            CREATED      CREATED BY                                     SIZE              COMMENT
ea28e1b82f31  6 weeks ago  /bin/sh -c #(nop)  CMD ["httpd-foreground"]    0 B
<missing>     6 weeks ago  /bin/sh -c #(nop)  EXPOSE 80                   0 B  
<missing>     6 weeks ago  /bin/sh -c #(nop) COPY file:c432ff61c4993e...  3.58 kB
<missing>     6 weeks ago  /bin/sh -c #(nop)  STOPSIGNAL SIGWINCH         0 B               
<missing>     6 weeks ago  /bin/sh -c set -eux;                                             savedAptMark="$(apt...  61 MB
<missing>     6 weeks ago  /bin/sh -c #(nop)  ENV HTTPD_PATCHES=          0 B
<missing>     6 weeks ago  /bin/sh -c #(nop)  ENV HTTPD_SHA256=20e01d...  0 B
<missing>     6 weeks ago  /bin/sh -c #(nop)  ENV HTTPD_VERSION=2.4.51    0 B
<missing>     6 weeks ago  /bin/sh -c set -eux;                           apt-get update;   apt...      2.69 MB
<missing>     6 weeks ago  /bin/sh -c #(nop) WORKDIR /usr/local/apache2   0 B
<missing>     6 weeks ago  /bin/sh -c mkdir -p "$HTTPD_PREFIX"            && ch...          3.07 kB
<missing>     6 weeks ago  /bin/sh -c #(nop)  ENV PATH=/usr/local/apa...  0 B
<missing>     6 weeks ago  /bin/sh -c #(nop)  ENV HTTPD_PREFIX=/usr/l...  0 B
<missing>     6 weeks ago  /bin/sh -c #(nop)  CMD ["bash"]                0 B  
<missing>     6 weeks ago  /bin/sh -c #(nop) ADD file:ece5ff85ca549f0...  83.9 MB

Pay attention to the HTTPD_VERSION=2.4.51 environment variable. To get more detailed information about this image, view it using the inspect subcommand. The output is very verbose, so I've abbreviated it here:

$ podman image inspect httpd
[
    {
        "Id": "ea28e1b82f314092abd3f90a69e57d6ccf506382821ee0b8d9b48c3e47440c1f",
        "Digest": "sha256:fba8a9f4290180ceee5c74638bb85ff21fd15961e6fdfa4def48e18820512bb1",
        "RepoTags": [
            "docker.io/library/httpd:latest"
        ],
        "RepoDigests": [  "docker.io/library/httpd@sha256:24d492e04f02881adcc1d7543b0251754a2be6a24c75aae7a008fdae767b7337", "docker.io/library/httpd@sha256:fba8a9f4290180ceee5c74638bb85ff21fd15961e6fdfa4def48e18820512bb1"],
        "Parent": "",
        "Comment": "",
        "Created": "2021-12-02T10:03:55.933654778Z",
        "Config": {
            "ExposedPorts": {
                "80/tcp": {}
            },
            "Env": [
                "PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", "HTTPD_PREFIX=/usr/local/apache2", "HTTPD_VERSION=2.4.51",
[…]
        "Version": "20.10.7",
        "Author": "",
        "Architecture": "amd64",
        "Os": "linux",
        "Size": 147627312,
        "VirtualSize": 147627312,
        "GraphDriver": {
            "Name": "overlay",
            "Data": {
                "LowerDir": "/home/localuser/.local/share/containers/storage/overlay/e20054c1032fd3c5f8d8b35d8c75b806d8f813c90621b8304d543c7edf26b2f6/diff:/home/localuser/.local/share/containers/storage/overlay/1121e686efcde8973c70358a33725d8e9616f13eab864334568ee5aea0578295/diff:/home/localuser/.local/share/containers/storage/overlay/
[...]

Next, proceed with an image update.

[ Learn more about moving legacy applications to containers and Kubernetes. ]

Manually update container images

To update an image, run the same command used to pull an image, podman pull. Its syntax is:

podman pull [options] IMAGE [IMAGE...]

To run a specific image version, set the desired image tag. I will run the latest version for the httpd image for this demonstration, so Podman pulls the newest httpd version using the latest tag.

If you don't specify any tag, Podman pulls the image using the latest tag by default:

$ podman pull docker.io/library/httpd:latest
Trying to pull docker.io/library/httpd:latest...
Getting image source signatures
[...]
Copying blob 67283bbdd4a0 done  
Copying config dabbfbe0c5 done  
Writing manifest to image destination
Storing signatures
dabbfbe0c57b6e5cd4bc089818d3f664acfad496dc741c9a501e72d15e803b34

Now, when you check your pulled images again, you'll see the httpd image has changed its ID, and the CREATE column shows that it was created "4 weeks ago." That means this newly pulled image has two weeks of update differences from the previous version:

$ podman image ls
REPOSITORY                   TAG         IMAGE ID      CREATED        SIZE
docker.io/library/httpd      latest      dabbfbe0c57b  4 weeks ago    148 MB
docker.io/library/wordpress  latest      054741915cf1  6 weeks ago    629 MB
docker.io/library/mysql      latest      bbf6571db497  6 weeks ago    521 MB
<none>                       <none>      ea28e1b82f31  6 weeks ago    148 MB
k8s.gcr.io/pause             3.5         ed210e3e4a5b  10 months ago  690 kB

But what has changed between one image and another? Check the image history to find out:

$ podman image history httpd
ID            CREATED      CREATED BY                                     SIZE              COMMENT
dabbfbe0c57b  4 weeks ago  /bin/sh -c #(nop)  CMD ["httpd-foreground"]    0 B
<missing>     4 weeks ago  /bin/sh -c #(nop)  EXPOSE 80                   0 B    
<missing>     4 weeks ago  /bin/sh -c #(nop) COPY file:c432ff61c4993e...  3.58 kB
<missing>     4 weeks ago  /bin/sh -c #(nop)  STOPSIGNAL SIGWINCH         0 B
<missing>     4 weeks ago  /bin/sh -c set -eux;                                             savedAptMark="$(apt...  61.1 MB
[...]
<missing>     4 weeks ago  /bin/sh -c #(nop)  ENV HTTPD_PREFIX=/usr/l...  0 B
<missing>     4 weeks ago  /bin/sh -c #(nop)  CMD ["bash"]                0 B
<missing>     4 weeks ago  /bin/sh -c #(nop) ADD file:09675d11695f65c...  83.9 MB

Remember that HTTPD_VERSION=2.4.51 environment variable that I asked you to pay attention to? You can see that it was changed in this updated image to HTTPD_VERSION=2.4.52, which means that Apache was updated between versions.

But this updated image was not used by any running container. What happens when I update the image of a running container? Check it out.

Manually apply image updates to a running container

I'll use the same httpd image pulled from the docker.io registry as above. I'll run it as a rootfull container to make use of the older image again, since I pulled it for the root user before. Here is the older pulled image:

$ sudo  podman image ls
REPOSITORY                             TAG         IMAGE ID      CREATED        SIZE
docker.io/library/wordpress            latest      054741915cf1  6 weeks ago    629 MB
docker.io/library/mysql                latest      bbf6571db497  6 weeks ago    521 MB
docker.io/library/httpd                latest      ea28e1b82f31  6 weeks ago    148 MB
registry.access.redhat.com/ubi8/pause  latest      20b34168e325  2 months ago   3.49 MB
k8s.gcr.io/pause                       3.5         ed210e3e4a5b  10 months ago  690 kB

Here is the running rootfull container that uses the older image:

$ sudo podman ps
CONTAINER ID  IMAGE                           COMMAND           CREATED    STATUS            PORTS                 NAMES
b85600da6d86  docker.io/library/httpd:latest  httpd-foreground  4 min ago  Up 3 minutes ago  0.0.0.0:8081->80/tcp  httpd

A simple curl to the running container webserver shows the Apache version provided by this image:

$ sudo curl -v http://localhost:8081
*   Trying 127.0.0.1:8081...
* Connected to localhost (127.0.0.1) port 8081 (#0)
> GET / HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Tue, 18 Jan 2022 18:00:14 GMT
< Server: Apache/2.4.51 (Unix)
< Last-Modified: Tue, 07 Dec 2021 21:29:58 GMT
< ETag: "74-5d295133b0ae6"
< Accept-Ranges: bytes
< Content-Length: 116
< Content-Type: text/html
<
<html>
  <header>
    <title>Enable SysAdmin</title>
  </header>
  <body>
    <p>Hello World!</p>
  </body>
</html>
* Connection #0 to host localhost left intact

The Server: Apache/2.4.51 (Unix) output shows the same version as in the HTTPD_VERSION=2.4.51 environment variable for this image, proving that it is still running with the old image. I'll pull the latest image version again while the container remains running:

$ sudo podman pull docker.io/library/httpd:latest
Trying to pull docker.io/library/httpd:latest...
Getting image source signatures
Copying blob 41c22baa66ec done  
[...]
Copying blob d982c879c57e done  
Copying config dabbfbe0c5 done  
Writing manifest to image destination
Storing signatures
dabbfbe0c57b6e5cd4bc089818d3f664acfad496dc741c9a501e72d15e803b34

In the UP column, you can see that the container didn't stop at any time, which is good because the webserver continued to provide its services:

$ sudo podman ps
CONTAINER ID  IMAGE                           COMMAND           CREATED        STATUS            PORTS                 NAMES
b85600da6d86  docker.io/library/httpd:latest  httpd-foreground  4 minutes ago  Up 4 minutes ago  0.0.0.0:8081->80/tcp  httpd

Verify that the httpd image was updated, changed its IMAGE ID, and shows in the CREATED column that it was created "4 weeks ago." This means I now have the most up-to-date image version:

$ sudo podman image ls
REPOSITORY                             TAG         IMAGE ID      CREATED        SIZE
docker.io/library/httpd                latest      dabbfbe0c57b  4 weeks ago    148 MB
docker.io/library/wordpress            latest      054741915cf1  6 weeks ago    629 MB
docker.io/library/mysql                latest      bbf6571db497  6 weeks ago    521 MB
<none>                                 <none>      ea28e1b82f31  6 weeks ago    148 MB
registry.access.redhat.com/ubi8/pause  latest      20b34168e325  2 months ago   3.49 MB
k8s.gcr.io/pause                       3.5         ed210e3e4a5b  10 months ago  690 kB

But when I run a simple curl against the running container again, I see the Apache version didn’t change at all:

$ sudo curl -v http://localhost:8081
*   Trying 127.0.0.1:8081...
* Connected to localhost (127.0.0.1) port 8081 (#0)
> GET / HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Tue, 18 Jan 2022 18:04:12 GMT
< Server: Apache/2.4.51 (Unix)
< Last-Modified: Tue, 07 Dec 2021 21:29:58 GMT
< ETag: "74-5d295133b0ae6"
< Accept-Ranges: bytes
< Content-Length: 116
< Content-Type: text/html
<
<html>
  <header>
    <title>Enable SysAdmin</title>
  </header>
  <body>
    <p>Hello World!</p>
  </body>
</html>
* Connection #0 to host localhost left intact

[ Learn more about Red Hat OpenShift Container Platform. ]

When inspecting the running httpd container, it's possible to see that it is still mapping the HTTPD_VERSION=2.4.51 environment variable, which explains why it keeps using the Apache 2.4.51 version:

$ sudo podman inspect httpd --format "{{.Image}} {{.ImageName}} {{.Config.Env}}"
ea28e1b82f314092abd3f90a69e57d6ccf506382821ee0b8d9b48c3e47440c1f docker.io/library/httpd:latest [PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin TERM=xterm container=podman HTTPD_PREFIX=/usr/local/apache2 HTTPD_VERSION=2.4.51 HTTPD_SHA256=20e01d81fecf077690a4439e3969a9b22a09a8d43c525356e863407741b838f4 HTTPD_PATCHES= HOME=/root HOSTNAME=b85600da6d86]

That happens because simply pulling and updating container images won't automatically update running containers that use these images. That's a different step. To manually make a running container use the updated image, stop the container and start it again. I created the create_web.sh script in this example in the first article of this series:

$ sudo podman stop httpd
httpd

$ sudo podman rm -a
b85600da6d86cdd9cce0edf782025718de4e3fa9c3203005c579418ec9c99737

$ sudo ./create_web.sh
7b932bbe6367b2af96d2d7e4dc059d56873737d1e4b1c343912e10574f6ce8cc

The container is now running again, and it's using the updated image:

$ sudo podman ps
CONTAINER ID  IMAGE                           COMMAND           CREATED        STATUS            PORTS                 NAMES
7b932bbe6367  docker.io/library/httpd:latest  httpd-foreground  5 seconds ago  Up 4 seconds ago  0.0.0.0:8081->80/tcp  httpd

To verify that it’s true, check the newly running container for the HTTPD_VERSION environment variable:

$ sudo podman inspect httpd --format "{{.Image}} {{.ImageName}} {{.Config.Env}}"
dabbfbe0c57b6e5cd4bc089818d3f664acfad496dc741c9a501e72d15e803b34 docker.io/library/httpd:latest [PATH=/usr/local/apache2/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin TERM=xterm container=podman HTTPD_VERSION=2.4.52 HTTPD_SHA256=0127f7dc497e9983e9c51474bed75e45607f2f870a7675a86dc90af6d572f5c9 HTTPD_PATCHES= HTTPD_PREFIX=/usr/local/apache2 HOME=/root HOSTNAME=7b932bbe6367]

Jackpot! Now the container is running with the HTTPD_VERSION=2.4.52 environment variable, which means Apache should be running with this version. I'll confirm it by running curl against it again:

$ sudo curl -v http://localhost:8081
*   Trying 127.0.0.1:8081...
* Connected to localhost (127.0.0.1) port 8081 (#0)
> GET / HTTP/1.1
> Host: localhost:8081
> User-Agent: curl/7.79.1
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Date: Tue, 18 Jan 2022 18:23:04 GMT
< Server: Apache/2.4.52 (Unix)
< Last-Modified: Tue, 07 Dec 2021 21:29:58 GMT
< ETag: "74-5d295133b0ae6"
< Accept-Ranges: bytes
< Content-Length: 116
< Content-Type: text/html
<
<html>
  <header>
    <title>Enable SysAdmin</title>
  </header>
  <body>
    <p>Hello World!</p>
  </body>
</html>
* Connection #0 to host localhost left intact

As the Server: Apache/2.4.52 (Unix) field shows, the container is finally updated and running the latest httpd image version. And that's the whole process for a quick manual image update.

You might say, "This is good, but it's error-prone. Is there any automatic way to run all of this?" You bet there is! And for that, I recommend two excellent articles from Enable Sysadmin community members: Pulling podman images from a container repository and How to use auto-updates and rollbacks in Podman.

Keep things current

Keeping your container images current is essential for operating and managing a containerized environment. There are several benefits:

  • It enables your applications to have the latest versions of certain packages and tools.
  • It also ensures that you can make desired changes to the application at the image level.
  • It improves the environment's security by keeping the images with the most recent security patches and bug fixes.

My next article will show how to specify Arch when pulling images. Stay tuned!

Check out these related articles on Enable Sysadmin

Topics:   Podman   Containers  
Author’s photo

Alexon Oliveira

Alexon has been working as a Senior Technical Account Manager at Red Hat since 2018, working in the Customer Success organization focusing on Infrastructure and Management, Integration and Automation, Cloud Computing, and Storage Solutions. More about me

Red Hat Summit 2022: On Demand

Get the latest on Ansible, Red Hat Enterprise Linux, OpenShift, and more from our virtual event on demand.

Related Content

OUR BEST CONTENT, DELIVERED TO YOUR INBOX