Работа с контейнерами#

Контейнеры представляют собой запущенный или остановленный процесс, созданный из файлов, расположенных в распакованном образе.

Команда podman run#

Команда podman run запускает процесс в новом контейнере на основе образа. Если образ еще не загружен, то podman run извлекает его со всеми зависимостями из репозитория, запуская podman pull image. Контейнерный процесс имеет свою собственную файловую систему, сеть и изолированное дерево процессов.

Пример команды podman run:

podman run [options] image [command [arg ...]]

К основным опциям относятся:

  • --detach (-d) - запускает контейнер в фоновом режиме и выводит на экран ID нового контейнера;

  • --attach (-a) - запускает контейнер в приоритетном режиме;

  • name (-n) - присваивает имя контейнеру. Если имя не присвоено с помощью --name, то генерирует случайное. Опция работает для всех контейнеров (в фоновом и приоритетном режиме);

  • --rm - автоматически удаляет контейнер при выходе. Обратите внимание, что контейнер не удалится, если его не удалось создать или запустить;

  • --tty (-t) - выделяет псевдотерминал и присоединяет его к стандартному входу контейнера;

  • --interactive (-i) - используется для интерактивных процессов. Чтобы выделить терминал для процесса контейнера, используйте -i и -t. Разрешено написание -it.

Управление командами в контейнере с хоста#

  1. Отобразите тип операционной системы контейнера на основе образа example.registry.ru/ubi9/ubi с помощью команды cat /etc/os-release:

    podman run --rm registry.ru/ubi9/ubi cat /etc/os-release
    

    Пример вывода команды:

    NAME="SberLinux"
    ...
    ID="slo"
    ...
     HOME_URL="https://www.sberlinux.example.ru/"
     BUG_REPORT_URL="https://sberlogs.example.ru/"
    
    SLO_BUG_PRODUCT=" SberLinux 9"
    ...
    
  2. Опционально: Выведите список всех контейнеров:

    podman ps
    

    Пример вывода команды:

    CONTAINER ID  IMAGE   COMMAND  CREATED  STATUS  PORTS   NAMES
    

    Из-за опции --rm контейнер не отобразится, так как будет удален.

Управление командами внутри контейнера#

Чтобы управлять командами внутри контейнера, выполните следущий сценарий:

  1. Запустите контейнер с именем myubi на основе образа example.registry.ru/ubi9/ubi:

    podman run --name=myubi -it example.registry.ru/ubi9/ubi /bin/bash
    [root@6ccffd0f6421 /]#
    

    Где:

    • Опция -i создает интерактивный сеанс. Без опции -t оболочка остается открытой, но пользователь ничего не сможет в нее ввести.

    • Опция -t открывает сеанс терминала. Без опции -i оболочка открывается, а затем завершается.

  2. Установите пакет procps-ng, содержащий набор системных утилит (например, ps, top, up time):

    [root@6ccffd0f6421 /]# dnf install procps-ng
    
  3. Используйте команду ps -ef для вывода списка текущих процессов:

    ps -ef
    

    Пример вывода команды:

    UID PID PPID C STIME TTY TIME CMD
    root 1 0 0 12:55 pts/0 00:00:00 /bin/bash
    root 31 1 0 13:07 pts/0 00:00:00 ps -ef
    
  4. Введите exit, чтобы выйти из контейнера и вернуться к хосту:

    exit
    
  5. Опционально: Раскройте список всех контейнеров:

    podman ps
    

    Пример вывода команды:

    CONTAINER ID  IMAGE                               COMMAND    CREATED         STATUS                     PORTS   NAMES
    1984555a2c27  example.registry.ru/ubi9/ubi:latest  /bin/bash  21 minutes ago  Exited (0) 21 minutes ago          myubi
    

    Состояние контейнера отобразится как Exited.

Список контейнеров#

Для раскрытия списка контейнеров выполните следующие шаги:

  1. Запустите контейнер на основе образа example.registry.ru/slo9/rsyslog:

    podman run -d example.registry.ru/slo9/rsyslog
    
  2. Выведите список всех контейнеров:

    • Для вывода списка всех запущенных контейнеров введите:

      podman ps
      

      Пример вывода команды:

      CONTAINER ID IMAGE              COMMAND         CREATED       STATUS            PORTS NAMES
      74b1da000a11 slo9/rsyslog /bin/rsyslog.sh 2 minutes ago Up About a minute       musing_brown
      
    • Для вывода списка всех контейнеров введите:

      podman ps -a
      

      Пример вывода команды:

      CONTAINER ID IMAGE         COMMAND    CREATED    STATUS                PORTS NAMES     IS INFRA
      d65aecc325a4 ubi9/ubi      /bin/bash  3 secs ago Exited (0) 5 secs ago peaceful_hopper false
      74b1da000a11 slo9/rsyslog rsyslog.sh 2 mins ago Up About a minute     musing_brown    false
      

Если незапущенные контейнеры не были удалены, они могут быть перезапущены.

Запуск контейнеров#

Если после запуска остановить контейнер, то он сохранится в пользовательской локальной системе. Для повторного запуска контейнера используйте команду podman start. Можно указать контейнеры по ID или имени.

  1. Запустите контейнер myubi:

    • В неинтерактивном режиме используйте команду:

      podman start myubi
      

      В качестве альтернативы можно использовать podman start 1984555a2c27.

    • В интерактивном режиме используйте опции -a (--attach) и -i (--interactive) для работы с контейнерной оболочкой bash:

      podman start -a -i myubi
      

      В качестве альтернативы можно использовать podman start -a -i 1984555a2c27.

  2. Введите exit, чтобы выйти из контейнера и вернуться к хосту:

    [root@6ccffd0f6421 /]# exit
    

Проверка контейнеров со стороны хоста#

Используйте команду podman inspect для проверки метаданных существующего контейнера в формате JSON. Можно указывать контейнеры по ID или имени.

  • Проверьте контейнер под ID 64ad95327c74.

    • Для получения всех метаданных введите:

      podman inspect 64ad95327c74
      

      Пример вывода команды:

      [
         {
            "Id": "64ad95327c740ad9de468d551c50b6d906344027a0e645927256cd061049f681",
            "Created": "2021-03-02T11:23:54.591685515+01:00",
            "Path": "/bin/rsyslog.sh",
            "Args": [
                "/bin/rsyslog.sh"
            ],
            "State": {
               "OciVersion": "1.0.2-dev",
               "Status": "running",
               ...
      
    • Для получения определенных элементов из файла JSON, например, временной метки StartedAt, введите:

      podman inspect --format='{{.State.StartedAt}}' 64ad95327c74
      2021-03-02 11:23:54.945071961 +0100 CET
      

Информация хранится в виде иерархии. Для просмотра временной метки контейнера StartedAt (находится в разделе State), используйте опцию --format и ID или имя контейнера.

Примеры других элементов, которые можно проверить:

  • .Path - команда, выполняемая с контейнером;

  • .Args - аргументы команды;

  • .Config.ExposedPorts - порты TCP или UDP, предоставленные из контейнера;

  • .State.Pid - просмотр идентификатора процесса контейнера;

  • .HostConfig.PortBindings - сопоставление портов от контейнера к хосту.

Размещение каталога на локальном хосте в контейнер#

Чтобы сделать log-файлы из контейнера доступными для хост-системы, поместите устройство хоста /dev/log внутрь самого контейнера.

  1. Запустите контейнер с именем log_test и установите хост-устройство /dev/log внутри контейнера:

    podman run --name="log_test" -v /dev/log:/dev/log --rm \
    example.registry.ru/ubi9/ubi logger "Testing logging to the host"
    

    Опция --rm удаляет контейнер при закрытии.

  2. Используйте утилиту journalctl для отображения log-файлов:

    journalctl -b | grep Testing
    

    Пример вывода команды:

    Dec 25 16:55:00 localhost.localdomain root[14634]: Testing logging to the host
    

Размещение файловой системы контейнера#

Команда podman mount помещает корневую файловую систему рабочего контейнера в место, доступное с хоста.

  1. Запустите контейнер с именем mysyslog:

    podman run -d --name=mysyslog example.registry.com/slo9/rsyslog
    
  2. Опционально: Выведите список всех контейнеров:

    podman ps -a
    

    Пример вывода команды:

    CONTAINER ID  IMAGE                                    COMMAND          CREATED         STATUS                     PORTS   NAMES
    c56ef6a256f8  registry.example.io/rhel9/rsyslog:latest  /bin/rsyslog sh  20 minutes ago  Up 20 minutes ago                  mysyslog
    
  3. Переместите контейнер при помощи mysyslog:

    podman mount mysyslog
    

    Пример вывода команды:

    /var/lib/containers/storage/overlay/990b5c6ddcdeed4bde7b245885ce4544c553d108310e2b797d7be46750894719/merged
    
  4. Выведите содержимое точки перемещения с помощью команды ls:

    ls /var/lib/containers/storage/overlay/990b5c6ddcdeed4bde7b245885ce4544c553d108310e2b797d7be46750894719/merged
    

    Пример вывода команды:

    bin  boot  dev  etc  home  lib  lib64  lost+found  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var
    
  5. Отобразите версию ОС:

    cat /var/lib/containers/storage/overlay/990b5c6ddcdeed4bde7b245885ce4544c553d108310e2b797d7be46750894719/merged/etc/os-release
    

    Пример вывода команды:

    NAME="SberLinux"
    VERSION="9"
     ID="slo"
     ID_LIKE="fedora"
    ...
    

Запуск службы в качестве демона со статическим IP-адресом#

В данном примере служба rsyslog запускается в фоновом режиме в качестве процесса демона. Опция --ip устанавливает сетевой интерфейс контейнера на определенный IP-адрес. После этого можно запустить команду podman inspect, чтобы проверить, правильно ли установлен IP-адрес.

  1. Установите для сетевого интерфейса контейнера IP-адрес xx.xx.xx.xx:

    podman run -d --ip=xx.xx.xx.xx example.registry.ru/slo9/rsyslog
    

    Пример вывода команды:

    efde5f0a8c723f70dd5cb5dc3d5039df3b962fae65575b08662e0d5b5f9fbe85
    
  2. Убедитесь, что IP-адрес задан корректно:

    podman inspect efde5f0a8c723 | grep xx.xx.x.xx
    

    Пример вывода команды:

    "IPAddress": "xx.xx.xx.xx",
    

Выполнение команд внутри запущенного контейнера#

Podman exec позволяет выполнять команду в запущенном контейнере и проверять его. podman exec, в отличие от podman run, проверяет запущенный контейнер, не прерывая его работу.

  1. Введите команду rpm -qa внутри контейнера myrsyslog, чтобы вывести список всех установленных пакетов:

    podman exec -it myrsyslog rpm -qa
    

    Пример вывода списка пакетов:

    tzdata-2023d-1.el8.noarch
    python3-pip-wheel-9.0.3-18.el8.noarch
    sberlinux-release-9.3-1.0.el8.x86_64
    filesystem-3.8-3.el8.x86_64
    
  2. Запустите /bin/bash в контейнере myrsyslog:

    podman exec -it myrsyslog /bin/bash
    
  3. Установите пакет procps-ng, включающий набор системных утилит (например, ps, top, uptime):

    dnf install procps-ng
    
  4. Проверьте контейнер:

    • Для получения списка всех процессов системы используйте:

      ps -ef
      

      Пример списка процессов:

      UID          PID    PPID  C STIME TTY          TIME CMD
      root           1       0  0 10:23 ?        00:00:01 /usr/sbin/rsyslogd -n
      root           8       0  0 11:07 pts/0    00:00:00 /bin/bash
      root          47       8  0 11:13 pts/0    00:00:00 ps -ef
      
    • Для отображения использованного дискового пространства файловой системы введите:

      df -h
      

      Пример вывода команды:

      Filesystem      Size  Used Avail Use% Mounted on
      fuse-overlayfs   27G  7.1G   20G  27% /
      tmpfs            64M     0   64M   0% /dev
      tmpfs           269M  936K  268M   1% /etc/hosts
      shm              63M     0   63M   0% /dev/shm
      
    • Для вывода системной информации используйте:

      uname -r
      

      Пример вывода команды:

      4.18.0-240.10.1.el8_3.x86_64
      
    • Для отображения объема свободной и используемой памяти в мегабайтах введите:

      free --mega
      

      Пример вывода команды:

      total        used        free      shared  buff/cache   available
      Mem:       2818         615        1183          12         1020        1957
      Swap:      3124           0        3124
      

Обмен файлами между двумя контейнерами#

Том — это папка, которая хранится на хост-машине. Том может использоваться совместно контейнером и хостом. Они применяются для хранения данных, даже если контейнер удален, и для обмена данными между несколькими контейнерами.

Основные преимущества томов:

  • Совместное использование контейнерами;

  • Упрощенное резервное копирование или перенос;

  • Не увеличивающийся размер контейнеров.

Сценарий#

Для обмена файлами между контейнером и хостом выполните следующие действия:

  1. Создайте том:

    podman volume create hostvolume
    
  2. Выведите информацию о нем:

    podman volume inspect hostvolume
    

    Пример вывода команды:

    [
          {
             "name": "hostvolume",
              "labels": {},
              "mountpoint": "/home/username/.local/share/containers/storage/volumes/hostvolume/_data",
              "driver": "local",
              "options": {},
              "scope": "local"
          }
    ]
    

    Примечание

    Обратите внимание, что том создается в каталоге volumes. Можно сохранить путь к точке монтирования в переменной для упрощения действия: $ mntPoint=$(podman volume inspect hostvolume --format {{.Mountpoint}}).

    Примечание

    Обратите внимание, что при запуске sudo podman volume create hostvolume точка монтирования изменится на /var/lib/containers/storage/volumes/hostvolume/_data.

  3. Создайте текстовый файл внутри каталога, используя путь, который хранится в переменной mntPoint:

    echo "Hello from host" >> $mntPoint/host.txt
    
  4. Выведите список всех файлов, который определяется переменной mntPoint:

    ls $mntPoint/
    

    Пример вывода команды:

    host.txt
    
  5. Запустите контейнер с именем myubi1 и сопоставьте каталог, указанный именем тома hostvolume на хосте, с каталогом /containervolume1 в контейнере:

    podman run -it --name myubi1 -v hostvolume:/containervolume1 example.registry.com/ubi9/ubi /bin/bash
    

    Примечание

    Обратите внимание, если используется путь к тому, который определен переменной mntPoint (-v $mntPoint:/containervolume1), то при выполнении команды podman volume prune данные могут быть утеряны. Команда удаляет неиспользуемые тома. Поэтому рекомендуется использовать -v hostvolume_name:/containervolume_name.

  6. Отобразите список файлов в общем томе контейнера:

    ls /containervolume1
    

    В выводе появится файл host.txt, который создался на хосте.

  7. Создайте текстовый файл внутри каталога /containervolume1:

    echo "Hello from container 1" >> /containervolume1/container1.txt
    
  8. Отсоединитесь от контейнера при помощи сочетания клавиш CTRL+p и CTRL+q;

  9. Выведите список файлов в общем томе на хосте:

    ls $mntPoint
    

    Должно отобразиться два файла:

    container1.rxt  host.txt
    

    После этого файлы станут общими для контейнера и хоста. Чтобы сделать файлы общими для двух контейнеров, запустите другой контейнер с именем myubi2.

  10. Запустите контейнер с именем myubi2 и сопоставьте каталог, указанный именем тома hostvolume на хосте, с каталогом /containervolume2 в контейнере:

    podman run -it --name myubi2 -v hostvolume:/containervolume2 example.registry.ru/ubi9/ubi /bin/bash
    
  11. Выведите список файлов в общем томе контейнера:

    ls /containervolume2
    

    Пример вывода команды:

    container1.txt host.txt
    

    Появятся два файла: host.txt, созданный на хосте, и container1.txt, созданный внутри контейнера myubi1.

  12. Создайте текстовый файл внутри каталога /containervolume2:

    echo "Hello from container 2" >> /containervolume2/container2.txt
    
  13. Отсоединитесь от контейнера с помощью CTRL+p и CTRL+q;

  14. Отобразите список файлов в общем томе:

    ls $mntPoint
    

    На хосте появятся три файла: container1.rxt, container2.txt, host.txt.

Экспорт и импорт контейнеров#

Используйте команду podman export для экспорта файловой системы запущенного контейнера в tar-архив на локальной пользовательской машине.

Также команда может экспортировать текущий snapshot запущенного контейнера в tar-архив или импортировать tar-архив и сохранить его как образ файловой системы. Этот образ файловой системы станет доступным для запуска или использования в качестве слоя для других образов.

  1. Запустите контейнер myubi на основе образа registry.access.../ubi9/ubi:

    podman run -dt --name=myubi example.registry.КГ/9/ubi
    
  2. Опционально: раскройте список всех контейнеров:

    podman ps -a
    

    Пример вывода команды:

    CONTAINER ID  IMAGE                                    COMMAND          CREATED     STATUS         PORTS   NAMES
    a6a6d4896142  registry.example.ru/9:latest   /bin/bash        7 seconds ago  Up 7 seconds ago          myubi
    
  3. Присоединитесь к контейнеру myubi:

    podman attach myubi
    
  4. Создайте файл с именем testfile:

    echo "hello" > testfile
    
  5. Отсоединитесь от контейнера с помощью комбинации клавиш CTRL+p и CTRL+q;

  6. Экспортируйте файловую систему myubi в качестве myubi-container.tar на локальной машине:

    podman export -o myubi.tar a6a6d4896142
    
  7. Опционально: Выведите текущее содержимое каталога:

    ls -l
    -rw-r--r--. 1 user user 210885120 Apr  6 10:50 myubi-container.tar
    ...
    
  8. Опционально: Введите следующие команды:

    • Создайте каталог с именем myubi-container:

      mkdir myubi-container
      
    • Извлеките все файлы из архива myubi-container.tar:

      mkdir myubi-container
      tar -xf myubi-container.tar -C myubi-container
      
    • Выведите содержимое каталога myubi в древовидном формате:

      tree -L 1 myubi-container
      

      Пример вывода команды:

        ├── bin -> usr/bin
        ├── boot
        ├── dev
        ├── etc
        ├── home
        ├── lib -> usr/lib
        ├── lib64 -> usr/lib64
        ├── lost+found
        ├── media
        ├── mnt
        ├── opt
        ├── proc
        ├── root
        ├── run
        ├── sbin -> usr/sbin
        ├── srv
        ├── sys
        ├── testfile
        ├── tmp
        ├── usr
        └── var
      
        20 directories, 1 file
      

    После этого появится информация, что файл myubi-container.tar содержит файловую систему контейнера.

  9. Импортируйте файл myubi.tar и сохраните его как образ файловой системы:

    podman import myubi.tar myubi-imported
    

    Пример вывода команды:

    Getting image source signatures
    Copying blob 277cab30fe96 done
    Copying config c296689a17 done
    Writing manifest to image destination
    Storing signatures
    c296689a17da2f33bf9d16071911636d7ce4d63f329741db679c3f41537e7cbf
    
  10. Раскройте список всех образов:

    podman images
    

    Пример списка образов:

    REPOSITORY                              TAG     IMAGE ID      CREATED         SIZE
    docker.io/library/myubi-imported       latest  c296689a17da  51 seconds ago  211 MB
    
  11. Отобразите содержимое тестового файла file:

    podman run -it --name=myubi-imported docker.io/library/myubi-imported cat testfile
    hello
    

Остановка контейнеров#

Используйте команду podman stop, чтобы остановить запущенный контейнер. Можно указывать ID или имена контейнеров:

  • При использовании имени контейнера введите:

    podman stop myubi
    
  • При использовании ID контейнера введите:

    podman stop 1984555a2c27
    

Команда exit останавливает запущенный контейнер, подключенный к сеансу терминала. Вводится внутри контейнера.

Команда podman stop отправляет сигнал SIGTERM для завершения работы запущенного контейнера. Если контейнер не останавливается по истечении определенного периода времени (по умолчанию 10 секунд), Podman отправляет сигнал SIGKILL.

Команда podman kill «уничтожает» контейнер (SIGKILL) или отправляет другой сигнал в контейнер.

Отправка сигнала SIGHUP в контейнер (если поддерживается) заставляет приложение повторно считывать свои файлы конфигурации:

podman kill --signal="SIGHUP" 74b1da000a11

Удаление контейнеров#

Используйте команду podman rm для удаления контейнеров по ID или имени.

  1. Выведите список всех контейнеров:

    podman ps -a
    

    Пример вывода команды:

    CONTAINER ID IMAGE         COMMAND    CREATED    STATUS                PORTS NAMES     IS INFRA
    d65aecc325a4 ubi9/ubi      /bin/bash  3 secs ago Exited (0) 5 secs ago peaceful_hopper false
    74b1da000a11 rhel9/rsyslog rsyslog.sh 2 mins ago Up About a minute     musing_brown    false
    
  2. Удалите контейнеры:

    • Чтобы удалить контейнер peaceful_hopper, введите:

      podman rm peaceful_hopper
      

      Обратите внимание, что контейнер peaceful_hopper находился в состоянии Exited. Он остановлен и ничто не препятствует удалению.

    • Чтобы удалить контейнер musing_brown, сначала остановите его с помощью команды:

      podman stop musing_brown
      

      Затем удалите его:

      podman rm musing_brown
      
    • Дополнительно:

      • Для удаления нескольких контейнеров используйте:

        podman rm clever_yonath furious_shockley
        
      • Для удаления всех контейнеров из пользовательской локальной системы используйте:

        podman rm -a  
        

Настройка hooks предварительного выполнения в Podman#

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

Примечание

Файл /etc/containers/podman_preexec_hooks.txt должен быть создан пользователем с административными полномочиями и может быть пустым. Если /etc/containers/podman_preexec_hooks.txt не существует, скрипты плагинов выполняться не будут.

К плагин скриптам применимы следующие правила:

  • Принадлежат пользователю с административными полномочиями и недоступны для записи;

  • Располагаются в каталогах /usr/libexec/podman/pre-exec-hooks и /etc/containers/pre-exec-hooks;

  • Выполняются последовательно и в алфавитно-цифровом порядке;

  • Выполняется команда podman, если все плагин скрипты возвращают нулевое значение.

Если хоть один из скриптов плагина не возвращает нулевое значение, это указывает на сбой. Команда podman завершает работу и возвращает ненулевое значение первого скрипта, при выполнении которого возник сбой.

Рекомендуется использовать следующее соглашение по присвоению имен для выполнения скриптов в правильном порядке: DDD_name.lang.

Где:

  • DDD - десятичное число, указывающее порядок выполнения скрипта. При необходимости используйте один или два начальных нуля;

  • name - название скрипта плагина;

  • Lang (опционально) - расширение файла для данного языка программирования. Например, название скрипта плагина может иметь вид: 001-check-groups.sh.

Примечание

Скрипты плагина действуют на момент создания. Контейнеры, созданные ранее, не затрагиваются.

Сценарий#

Создайте скрипт плагина с именем 001-check-groups.sh.:

Пример создания:

!/bin/bash
if id -nG "$USER" 2> /dev/null | grep -qw "$GROUP" 2> /dev/null ; then
    exit 0
else
    exit 1
fi

Скрипт проверяет, входит ли пользователь в указанную группу.

USER и GROUP - это переменные среды, заданные Podman.

Код завершения, предоставленный скриптом 001-check-groups.sh, будет передан двоичному файлу podman.

Команда podman завершает работу и возвращает ненулевое значение первого скрипта, при выполнении которого возник сбой.

Проверка#

Проверьте корректную работу скрипта 001-check-groups.sh:

podman run image

Если пользователь не находится в нужной группе, появится ошибка:

external preexec hook /etc/containers/pre-exec-hooks/001-check-groups.sh failed