Изображение Hessel Visser с сайта Pixabay

Поддержание образов в актуальном состоянии является стандартной процедурой при эксплуатации и управлении контейнерной средой. Далее мы рассмотрим, как следует это делать.

Podman — это daemon-less движок для разработки, управления и запуска контейнеров, соответствующих Open Container Initiative (OCI). Это одна из серии статей об использовании Podman, основанная на том, что я делаю в своей реальной рабочей среде. Ранее я показывал, как отображать сетевую информацию с помощью Podman, включая контейнеры и IP-адреса подов.

В данной же статье показано, как обновлять образы контейнеров. Очень важно поддерживать запущенные контейнеры и поды в актуальном состоянии с самыми последними обновлениями образа. Прежде чем следовать этой статье, вы можете сначала запустить shell-скрипты, которые я использовал в одной из предыдущих статей, в разделе "Первичная настройка".

Вы можете ознакомиться со всеми моими предыдущими материалами из цикла статей про Podman здесь:


Проверяйте образы перед обновлением


Перед обновлением любых образов важно понять, что именно изменилось в одной версии образа по сравнению с другой. Отслеживание этих изменений позволит вам понять их влияние на вашу инфраструктуру. В определённых сценариях может быть полезно использовать более глубокие инструменты проверки, такие как 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.

Комментарии (2)


  1. Nicknnn
    10.03.2022 09:00
    +1

    Но зачем sudo для curl?


  1. Needle11
    11.03.2022 15:40

    Спасибо за полезную инфу