📱 Подписаться
IT и цифровая трансформация

Docker как контейнер-песочница, v2

📰 Habr 👁️ 4 просмотров

JBFW1 час назад

Docker как контейнер-песочница, v2

Время на прочтение5 минОхват и читатели2.3KНастройка Linux*Иногда бывает нужно запустить рабочие программы так, чтобы отделить их от ОС (не устанавливать поверх системы, использовать другие библиотеки, сформировать portable пакет и т.д.). Например, защитить от нежелательного обновления, или наоборот, потестировать обновление перед тем как применить его в работу.

Простейшее решение - устанавливать и запускать их внутри контейнера docker.

docker run -ti \
--name test \
debianи устанавливай что хочешь.Если контейнер будет многоразовый - полезно сразу добавить в него скрипт инициализации, например так:

docker run -ti \
--name test \
debian \
/etc/startupПосле создания контейнер не запустится, потому что скрипта /etc/startup нет. Его можно добавить, хотя бы минимальный:

#!/bin/sh

/bin/bashchmod 700 startup
docker cp startup test:/etc/startup
docker start testВ работающий контейнер можно зайти рутом, и подготовить всё к установке:

docker exec -ti test /bin/bash
apt update
apt upgrade
apt install ...Так как запускать прикладные программы от рута - не самая лучшая идея, лучше создать отдельного юзера, и работать под ним:

apt install adduser
adduser myuser
su -l myuserВ этом случае пользователь входит так, как если бы выполнялся нормальный логин в систему, с обработкой всяких там .profileМожно сразу логиниться в контейнер юзером:

docker exec -ti test su -l myuserЕсть похожий способ, но это не логин в систему, это просто запуск конкретной программы под конкретным пользователем.Это другое, переменные окружения юзера не устанавливаются:

docker exec -ti --user myuser test /bin/bashВ любом случае - это консольный вход. Текстовый редактор, работа с файлами, скрипты, обработка данных - вполне удобно.Но в случае с графическими программами есть две дополнительные сложности:

Во-первых, нужен графический режим. Это не очень сложно, потому что X Window System изначально разработана с возможностью работы через сеть или через UNIX-socket. Но во-вторых, некоторые программы требуют еще и работу с чем-то типа MESA/OpenGL.

Для проброса Иксов будем использовать UNIX-socket, часто он находится как /tmp/.X11-unix/X0 Для этого при создании контейнера добавим проброс файла:

docker run -ti \
-v /tmp/.X11-unix:/tmp/.X11-unix \
--name test \
debian \
/etc/startupВ типовом случае, если вы единственный пользователь на компьютере, и программы запускаются под единственным пользователем в контейнере - скорее всего будет достаточно просто указать переменную DISPLAY и запустить программу:

su -l myuser
export DISPLAY=:0
prognameУдобнее просто добавить "export DISPLAY=:0" в .profile, именно поэтому и используется вход через su -l myuser.

Пояснение, почему так: X-сервер на хосте проверяет подключение через сокет по списку разрешений. Посмотреть текущий список на хосте можно так:

xhost
access control enabled, only authorized clients can connect
SI:localuser:myuserВ данном случае доступ разрешен локальному юзеру myuser, причем юзер тут определяется по UID соответствующему UID myuser в таблице пользователей.

Что это значит: Если в контейнере создать нового пользователя с UID, соответствующим UID пользователя myuser хоста - у него будет доступ к X-серверу. Имя пользователя роли не играет, хоть lopata - лишь бы UID совпадал.

Но кроме того, права на файл UNIX-сокета обычно также выдаются на текущего юзера хоста:

ls -l /tmp/.X11-unix/X0
srwxr-xr-x 1 myuser myuser 0 Mar 15 17:31 /tmp/.X11-unix/X0То есть, кроме списка авторизации проверяются обычные права на файл.Поскольку права также привязаны на UID/GID - для доступа к сокету в этом случае у пользователя в контейнере должен быть такой же UID как у пользователя myuser хоста.

Как правило, первый пользовательский UID - 1000, поэтому по умолчанию всё работает, так как UID и там и там совпадает. Но если на хосте или в контейнере почему-то несколько пользователей, то для того чтобы дать возможность работать с графикой им всем - нужно внести их в списки разрешенных и дать нужные права на сокет. Для этого на хосте выполнить команду:

xhost +local:
или
xhost +SI:localuser:other_user(причем other_user должен существовать на хосте, с таким же UID, который будет у нужного юзера внутри контейнера).А права на сокет поменять либо на "доступ для всех":

chmod 777 /tmp/.X11-unix/X0либо на "доступ для группы" и внести нужного пользователя в группу, владеющую сокетом

ls -l /tmp/.X11-unix/X0
srwxr-xr-x 1 myuser myuser 0 Mar 6 17:31 /tmp/.X11-unix/X0
chmod 775 /tmp/.X11-unix/X0
usermod -a -G myuser other_userи сделать это можно прямо внутри контейнера.Причем есть нюанс: сокет может пересоздаваться при рестарте хоста, соответственно права на него будут возвращаться к первоначальному состоянию, именно поэтому может пригодиться скрипт /etc/startup:

#!/bin/sh

chmod 775 /tmp/.X11-unix/X0

/bin/bashНо это только обычные Иксы, без аппаратного ускорения. Для работы графических ускорителей нужно подключить устройство, которое за это отвечает.Оно может находиться в системе примерно тут:

ls -l /dev/dri
total 0
drwxr-xr-x 2 root root 100 Mar 15 16:17 by-path
crw-rw---- 1 root video 226, 0 Mar 15 16:17 card0
crw-rw---- 1 root video 226, 1 Mar 15 16:17 card1
crw-rw---- 1 root render 226, 128 Mar 15 16:17 renderD128Кроме того, может потребоваться доступ к shared memory. Чтобы всё это сделать - изменяем скрипт создания контейнера:

docker run -ti \
--device /dev/dri \
--ipc host \
-v /tmp/.X11-unix:/tmp/.X11-unix \
--name test \
debian \
/etc/startupНо прежде чем можно будет этим пользоваться - нужно проверить доступы внутри контейнера:

ls -l /dev/dri
total 0
drwxr-xr-x 2 root root 100 Mar 15 16:17 by-path
crw-rw---- 1 root video 226, 0 Mar 15 16:17 card0
crw-rw---- 1 root video 226, 1 Mar 15 16:17 card1
crw-rw---- 1 root 105 226, 128 Mar 15 16:17 renderD128Например, тут можно видеть, что группа video распозналась, т.к. она есть в системе контейнера, а группа с GID 105 - не распознана.Значит, ее надо создать (возьмем то же имя render, но это непринципиально):

groupadd -a 105 render
ls -l /dev/dri
total 0
drwxr-xr-x 2 root root 100 Mar 15 16:17 by-path
crw-rw---- 1 root video 226, 0 Mar 15 16:17 card0
crw-rw---- 1 root video 226, 1 Mar 15 16:17 card1
crw-rw---- 1 root render 226, 128 Mar 15 16:17 renderD128Теперь остается включить нужного пользователя в группы video и render:

usermod -a -G video myuser
usermod -a -G render myuserТеперь, если приложение корректно установить внутри контейнера - оно будет работать в том числе и с 3D-ускорителем (если конечно он есть).Итак, оно запускается, работает, но работает почти как в виртуальной машине, в своей изолированной файловой системе.

А что, если нужно обмениваться документами с хостом? Перекидывать их по сети неудобно, поэтому нужно добавить разделяемый каталог, еще немного усложнив создание контейнера:

docker run -ti \
--device /dev/dri \
--ipc host \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v /home/myuser/shared:/shared \
--name test \
debian \
/etc/startupВот теперь программы на хосте и в контейнере работают с одним и тем же каталогом shared.

Остается только сделать простейший скрипт входа в контейнер под нужным пользователем, чтобы не заморачиваться с вводом ключей:

#!/bin/sh

docker exec -ti test su -l myuserили запускать окно терминала примерно так:

xterm -e 'docker exec -ti test su -l myuser'тогда окно терминала будет сразу открываться в контексте контейнера.

Настроенный контейнер с установленными программами можно сохранить, на случай переноса на другую машину или для восстановления:

docker commit test test_image
docker save test_image | gzip > test_image.gzНенужный больше контейнер можно удалить:

docker stop test
docker rm testПри этом удаляются все зависимости и изменения в ОС внутри контейнера.

Такую песочницу, например, удобно использовать, когда для выполнения конкретной работы требуется несколько программ, работающих вместе, и их можно таскать с собой в виде пакета с компьютера на компьютер, не беспокоясь о том, что после очередного обновления ОС хоста изменятся версии, нарушится совместимость, или программа вообще пропадет из репозитария по какой-то причине.Теги:• linux
• docker
• рабочее местоХабы:• Настройка Linux

Получайте больше инсайтов о систематизации бизнеса

Подписывайтесь на Telegram-канал Business Operations — ежедневные материалы о бизнес-процессах, операционном управлении и повышении эффективности

💬 Подписаться на канал