Изображение Hessel Visser с сайта Pixabay
Поддержание образов в актуальном состоянии является стандартной процедурой при эксплуатации и управлении контейнерной средой. Далее мы рассмотрим, как следует это делать.
Podman — это daemon-less движок для разработки, управления и запуска контейнеров, соответствующих Open Container Initiative (OCI). Это одна из серии статей об использовании Podman, основанная на том, что я делаю в своей реальной рабочей среде. Ранее я показывал, как отображать сетевую информацию с помощью Podman, включая контейнеры и IP-адреса подов.
В данной же статье показано, как обновлять образы контейнеров. Очень важно поддерживать запущенные контейнеры и поды в актуальном состоянии с самыми последними обновлениями образа. Прежде чем следовать этой статье, вы можете сначала запустить shell-скрипты, которые я использовал в одной из предыдущих статей, в разделе "Первичная настройка".
Вы можете ознакомиться со всеми моими предыдущими материалами из цикла статей про Podman здесь:
- Быстрое, простое и легко воспроизводимое создание контейнеров с помощью Podman и shell-скриптов
- Как использовать Podman для получения информации о ваших контейнерах
- Как Podman может извлечь внешний IP-адрес контейнера
Проверяйте образы перед обновлением
Перед обновлением любых образов важно понять, что именно изменилось в одной версии образа по сравнению с другой. Отслеживание этих изменений позволит вам понять их влияние на вашу инфраструктуру. В определённых сценариях может быть полезно использовать более глубокие инструменты проверки, такие как Skopeo, который позволяет проверить «удалённый образ, показывая его свойства, включая слои, без необходимости переносить образ на хост». Вы также можете проверить Dockerfile образа, чтобы получить информацию об обновлении. Однако только интерфейс командной строки (CLI) Podman может помочь вам собрать некоторую часть этой информации.
В этом примере показаны образы, которые я использовал с момента публикации первой статьи:
$ 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
Для этой демонстрации я буду использовать образ httpd. В колонке CREATED Podman сообщает, что образ с последней меткой был создан шесть недель назад. Чтобы проверить, что было сделано с этим образом при его создании, можно получить историю образа:
$ 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
Обратите внимание на переменную окружения HTTPD_VERSION=2.4.51. Чтобы получить более подробную информацию об этом образе, рассмотрим его с помощью подкоманды inspect
. Вывод очень многословен, поэтому здесь я его сократил:
$ 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/
[...]
Далее приступаем к обновлению образа.
Ручное обновление образов контейнеров
Чтобы обновить образ, выполним ту же команду, которая используется для извлечения образа, podman pull
. Её синтаксис следующий:
podman pull [options] IMAGE [IMAGE...]
Чтобы запустить определённую версию образа, установим нужный тег образа. В данной демонстрации я буду запускать последнюю версию для образа httpd, поэтому Podman извлечет самую новую версию httpd, используя тег latest.
Если вы не укажете никакого тега, Podman по умолчанию извлечет образ, используя самый последний тег:
$ 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
Теперь, когда вы снова проверите свои извлечённые образы, вы увидите, что образ httpd изменил свой ID, а в колонке CREATE указано, что он был создан «4 недели назад». Это означает, что новый извлечённый образ имеет двухнедельные отличия в обновлениях по сравнению с предыдущей версией:
$ 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
Но что изменилось между одним образом и другим? Проверим историю образа, чтобы узнать это:
$ 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
Помните переменную окружения HTTPD_VERSION=2.4.51, на которую я просил вас обратить внимание? Вы можете видеть, что она была изменена в этом обновлённом образе на HTTPD_VERSION=2.4.52, что означает, что между версиями был обновлён Apache.
Но этот обновлённый образ не используется ни одним запущенным контейнером. Что произойдёт, если я обновлю образ уже запущенного контейнера? Проверим это.
Ручное применение обновлений образа к работающему контейнеру
Я буду использовать тот же образ httpd, взятый из реестра docker.io, что и выше. Я запущу его как контейнер rootfull, чтобы снова использовать старый образ, так как раньше я использовал его для пользователя root. Вот старый извлечённый образ:
$ 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
Вот запущенный контейнер rootfull, использующий старый образ:
$ 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
Простой curl
к запущенному веб-серверу контейнера показывает версию Apache, предоставленную этим образом:
$ 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
Сервер: Apache/2.4.51 (Unix) показывает ту же версию, что и в переменной окружения HTTPD_VERSION=2.4.51 для этого образа, подтверждая, что он всё ещё работает со старым образом. Я ещё раз проверю последнюю версию образа, пока контейнер работает:
$ 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
В колонке UP видно, что контейнер не остановился ни на один момент, что хорошо, потому что веб-сервер продолжил обеспечивать работу своих служб:
$ 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
Проверяем, что образ httpd был обновлён, изменил свой IMAGE ID и показывает в колонке CREATED, что он был создан «4 недели назад». Это означает, что теперь у меня самая последняя версия образа:
$ 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
Но когда я снова запускаю простой curl относительно запущенного контейнера, я вижу, что версия Apache не изменилась вообще:
$ 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
При рассмотрении запущенного контейнера httpd можно увидеть, что он всё ещё отображает переменную окружения HTTPD_VERSION=2.4.51, что объясняет, почему он продолжает использовать версию Apache 2.4.51:
$ 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]
Это происходит потому, что простое извлечение и обновление образов контейнеров не приводит к автоматическому обновлению запущенных контейнеров, использующих эти образы. Для этого требуется отдельная операция. Чтобы вручную заставить запущенный контейнер использовать обновлённый образ, остановите контейнер и запустите его снова. Я создал сценарий create_web.sh
в этом примере в первой статье этого цикла:
$ sudo podman stop httpd
httpd
$ sudo podman rm -a
b85600da6d86cdd9cce0edf782025718de4e3fa9c3203005c579418ec9c99737
$ sudo ./create_web.sh
7b932bbe6367b2af96d2d7e4dc059d56873737d1e4b1c343912e10574f6ce8cc
Теперь контейнер снова запущен, и он использует обновлённый образ:
$ 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
Чтобы убедиться в этом, проверяем только что запущенный контейнер на наличие переменной окружения HTTPD_VERSION:
$ 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]
Джекпот! Теперь контейнер работает с переменной окружения HTTPD_VERSION=2.4.52, что означает, что Apache должен работать с этой версией. Я проверю это, запустив curl
снова:
$ 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
Как показывает поле Server: Apache/2.4.52 (Unix), контейнер наконец-то обновлён и работает с последней версией образа httpd. Вот и весь процесс быстрого обновления образа вручную.
Вы можете сказать: «Это, конечно, хорошо, но чревато ошибками. Может быть, есть какой-нибудь автоматический способ всё это запустить?». Конечно, есть! И для этого я рекомендую две отличные статьи от членов сообщества «Извлечение образов podman из репозитория контейнера» и «Как использовать автообновление и восстановление в Podman».
Поддерживайте актуальность
Поддерживать образы контейнеров в актуальном состоянии необходимо для работы и управления контейнерной средой. Такой подход даёт несколько главных преимуществ:
- Это позволяет вашим приложениям иметь последние версии определённых пакетов и инструментов.
- Это также гарантирует, что вы сможете вносить необходимые изменения в приложение на уровне образа.
- Это повышает безопасность вашей инфраструктуры, поскольку образы всегда будут содержать самые последние исправления безопасности и багфиксы.
НЛО прилетело и оставило здесь промокоды для читателей нашего блога:
— 15% на все тарифы VDS (кроме тарифа Прогрев) — HABRFIRSTVDS.
— 20% на выделенные серверы AMD Ryzen и Intel Core — HABRFIRSTDEDIC.
Автор:
1shaman