C++ -- очень капризный язык с точки зрения создания рабочего окружения. Сколько мне известно, нет простого и удобного способа сделать python -m venv <path>
/ cargo init <path>
. Самое лучшее в мире Linux, что у нас есть -- это пакетный менеджер самой системы. Но такой подход не позволяет сделать несколько рабочих окружений в одной системы.
Зато контейнеры -- позволяют. На данный момент существует несчётное количество систем контейнеризации, от древнего и максимально простого chroot'а, до довольно продвинутых ОС-подобных контейнеров LXC/LXD или контейнеров-как-приложений вроде Docker.
Уже сколько-то времени для работы я и коллеги пользуемся контейнерами systemd-nspawn. Система не получила высокую известность, и, в отличии от Docker'а, плохо приспособлена для запуска и настройки контейнеров-сервисов, а также, в отличии от от LXC, почти невозможно настроить для работы в системах без systemd. Но если нужно сделать контейнер-как-ОС, то systemd-nspawn позволяет это сделать с минимальными затратами времени.
И в этом гайде будет показано, как с помощью systemd-nspawn сделать относительно удобное переносное рабочее место C++-программиста
Обычно при настройке контейнеров внимание большое внимание уделяется безопасности и как накрутить её побольше. Но для рабочего места удобство кратно важнее дополнительной безопасности. Особенно если вы работаете с реальным железом, доступ к которому внутри контейнеров закрыт по-умолчанию. Это в том числе касается работы с видеокартой, звуком и другой перефирией.
Так что если вы считаете, что контейнеры должны быть максимально заизолированы -- можно дальше не читать.
На данный момент я работаю в Ubuntu 22.04, так что контейнер будет сделан на базе этой ОС. Если вы предпочитаете NixOS, Arch или другую экзотику, попробуйте найти аналоги установочных пакетов в своих системах. Вещи вроде make
или git
скорее всего будут одинаковыми где угодно.
sudo apt update && sudo apt install systemd-containerd arch-install-scripts
Не пугайтесь, arch-install-scripts
здесь для удобной работы с chroot
.
Контейнеры проживают по пути /var/lib/machines
. Если ваша система расположена на brtfs, то сама папка будет создана как подтом btrfs:
sudo btrfs subvolume list / | grep var/lib/machines
# ID 256 gen 37180 top level 5 path var/lib/machines
Systemd-nspawn активно использует возможности btrfs, в частности снапшоты, для быстрого создания копий этих машин (включая временные копии для экспорта этих машин)
Поэтому, если есть возможность, создайте папку с будущим контейнером так:
sudo su
cd /var/lib/machines
btrfs subvolume create devcont
Если же вы на другой ФС, то просто создайте папку:
sudo su
cd /var/lib/machines
mkdir devcont
Теперь, наполняем папку с контейнером реальным содержимым
debootstrap jammy devcont http://ru.archive.ubuntu.com/ubuntu/
После того, как команда отработана, игнорируем ненужные пакеты (не обязательно, но зачем нам они в контейнере):
tee devcont/etc/apt/preferences.d/ignored-packages << 'EOF'
Package: grub-common grub2-common grub-pc grub-pc-bin grub-gfxpayload-lists lilo
Pin: release *
Pin-Priority: -1
Package: cloud-init landscape-common popularity-contest
Pin: release *
Pin-Priority: -1
EOF
И подключаем полный пакет репозиториев Ubuntu 22.04
tee devcont/etc/apt/sources.list << 'EOF'
# See http://help.ubuntu.com/community/UpgradeNotes for how to upgrade to
# newer versions of the distribution.
deb http://ru.archive.ubuntu.com/ubuntu/ jammy main restricted
# deb-src http://ru.archive.ubuntu.com/ubuntu/ jammy main restricted
## Major bug fix updates produced after the final release of the
## distribution.
deb http://ru.archive.ubuntu.com/ubuntu/ jammy-updates main restricted
# deb-src http://ru.archive.ubuntu.com/ubuntu/ jammy-updates main restricted
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team. Also, please note that software in universe WILL NOT receive any
## review or updates from the Ubuntu security team.
deb http://ru.archive.ubuntu.com/ubuntu/ jammy universe
# deb-src http://ru.archive.ubuntu.com/ubuntu/ jammy universe
deb http://ru.archive.ubuntu.com/ubuntu/ jammy-updates universe
# deb-src http://ru.archive.ubuntu.com/ubuntu/ jammy-updates universe
## N.B. software from this repository is ENTIRELY UNSUPPORTED by the Ubuntu
## team, and may not be under a free licence. Please satisfy yourself as to
## your rights to use the software. Also, please note that software in
## multiverse WILL NOT receive any review or updates from the Ubuntu
## security team.
deb http://ru.archive.ubuntu.com/ubuntu/ jammy multiverse
# deb-src http://ru.archive.ubuntu.com/ubuntu/ jammy multiverse
deb http://ru.archive.ubuntu.com/ubuntu/ jammy-updates multiverse
# deb-src http://ru.archive.ubuntu.com/ubuntu/ jammy-updates multiverse
## N.B. software from this repository may not have been tested as
## extensively as that contained in the main release, although it includes
## newer versions of some applications which may provide useful features.
## Also, please note that software in backports WILL NOT receive any review
## or updates from the Ubuntu security team.
deb http://ru.archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
# deb-src http://ru.archive.ubuntu.com/ubuntu/ jammy-backports main restricted universe multiverse
## Uncomment the following two lines to add software from Canonical's
## 'partner' repository.
## This software is not part of Ubuntu, but is offered by Canonical and the
## respective vendors as a service to Ubuntu users.
# deb http://archive.canonical.com/ubuntu jammy partner
# deb-src http://archive.canonical.com/ubuntu jammy partner
deb http://security.ubuntu.com/ubuntu jammy-security main restricted
# deb-src http://security.ubuntu.com/ubuntu jammy-security main restricted
deb http://security.ubuntu.com/ubuntu jammy-security universe
# deb-src http://security.ubuntu.com/ubuntu jammy-security universe
deb http://security.ubuntu.com/ubuntu jammy-security multiverse
# deb-src http://security.ubuntu.com/ubuntu jammy-security multiverse
EOF
Теперь настраиваем будущую ОС с помощью arch-chroot
arch-chroot devcont
Теперь мы находимся как бы внутри терминала ОС, с полным доступом к железу, но без запущенных сервисов. Для начала немного оживим наш терминал
cd /root
# Делаем приглашающую строку в терминале чуть более цветной
sed -i 's/#force_color_prompt=yes/force_color_prompt=yes/' /root/.bashrc
. /root/.bashrc
tee -a /root/.bashrc <<'EOF'
if [ -f /etc/bash_completion ] && ! shopt -oq posix; then
. /etc/bash_completion
fi
EOF
apt update && apt -y full-upgrade
# Не все эти программы могут вам понадобиться, но они могут сделать жизнь слегка приятнее
# bash-completion -- дополнение команд терминала по tab
#
# command-not-found -- добавляет в терминал сообщения вида
# Команда «compsize» не найдена, но может быть установлена с помощью:
# sudo apt install btrfs-compsize
# language-pack-ru -- русская локализация по мере сил и возможностей
# mc -- неплохой консольный файловый менеджер
# python-is-python3 -- прописывает в PATH символьную ссылку на python3
# с именем python
# rsync -- утилита для синхронизации папок по сети и локально
# curl и wget -- консольные файлокачалки
# linux-headers-generic -- для компиляции программ, которым нужны системные
# интерфейсы linux
apt install -y nano bash-completion command-not-found language-pack-ru \
man-db manpages python-is-python3 mc rsync curl wget \
linux-headers-generic
# Если вы пользуетесь терминалом kitty
apt install kitty-terminfo
. /root/.bashrc
# ненужно
apt remove netplan.io xdg-user-dirs
# для command-not-found
apt update
Теперь нужно настроить локали, таймзоны и прочее
dpkg-reconfigure locales # Выбрать en_US.UTF8, ru_RU.UTF8 и C.UTF8
dpkg-reconfigure tzdata # Выбрать Москву
dpkg-reconfigure keyboard-configuration # Выбрать Alt+Shift
localectl set-locale LANG=ru_RU.UTF-8
update-locale LANG=ru_RU.UTF-8
# Применяем изменения в настройках
exit
arch-chroot devcont
Отключаем лишнее, создаём нового пользователя (devuser, желательно, чтобы он не был назван как любой из ваших пользователей)
# Отключаем лишние сервисы
sudo systemctl disable dmesg.service e2scrub_reap.service networkd-dispatcher.service rsyslog.service setvtrgb.service systemd-network-generator.service systemd-networkd-wait-online.service systemd-networkd.service systemd-pstore.service systemd-resolved.service systemd-timesyncd.service ua-reboot-cmds.service systemd-networkd.socket e2scrub_all.timer fstrim.timer
# Убираем сообщение о платном плане с обновлениями безопасности Ubuntu ESM
rm /etc/apt/apt.conf.d/20apt-esm-hook.conf
# Если этого не сделать, то при входе в контейнер удалятся файлы внутри /dev/shm
# Кстати, это верно и для основной системы и входе в неё по SSH
sed -i 's/#RemoveIPC=yes/RemoveIPC=no/' /etc/systemd/logind.conf
# Создаём пользователя, который не root
useradd --create-home --password $(python3 -c 'import crypt; print(crypt.crypt("your uber password"))') --shell /bin/bash devuser
# Добавляем в sudoers и в доступ к железу
usermod -a -G sudo,dialout,audio,video,adm,plugdev,render devuser
# Делаем терминал пользователя чутка цветнее
sed -i 's/#force_color_prompt=yes/force_color_prompt=yes/' /home/devuser/.bashrc
exit
Отлично, минимальный образ создан, время запускать его как контейнер
Для запуска потребуется создать два файла. Файл с описанием самой машины, и небольшую правку сервиса запуска контейнера с большим доступом к железу, чем по-умолчанию
Итак, настройка контейнера:
sudo tee /etc/systemd/nspawn/devcont.nspawn << 'EOF'
[Exec]
# Контейнер в режиме "как бы виртуальная машина"
Boot=1
# снаружи контейнера номера пользователей те же, что внутри
PrivateUsers=false
[Files]
# Для адекватной работы сети
BindReadOnly=/etc/resolv.conf
BindReadOnly=/etc/hostname
BindReadOnly=/etc/hosts
# Для графики
BindReadOnly=/tmp/.X11-unix
# для устройств, включая терминалы
Bind=/dev
# Необязательно, нужно для доступа к дискам из контейнера
Bind=/mnt
# Необязательно, нужно для доступа к дискам из контейнера
Bind=/media
# для локальных имён файлов
BindReadOnly=/etc/hosts
# для звука
BindReadOnly=/run/user/1000/pulse:/var/run/pulse
# /tmp становится tmpfs нужного размера. Можно менять
TemporaryFileSystem=/tmp:size=6g
# Файлы nVidia нужны только если у вас установлены драйвера
# nVidia, и осторожнее, нужно будет заменить пути с версии
# 535.104.05 на нужную. Если какого-то из этих файлов нет,
# контейнер не запустится.
# Возможно, будет проще установить драйвера нвидии внутрь контейнера
# через apt. Если сделаете так, убедитесь, что версии драверов
# внутри и снаружи контейнера совпадают
# Если вам не требуются шейдеры в частности и аппаратное ускорение видео
# В целом, можете вообще не париться
### Огромный пласт файлов драйверов nVidia
# папки
# BindReadOnly=/usr/lib/firmware/nvidia
# BindReadOnly=/usr/lib/nvidia
# BindReadOnly=/usr/lib/nvidia/32
# BindReadOnly=/usr/lib/x86_64-linux-gnu/nvidia
# BindReadOnly=/usr/share/doc/NVIDIA_GLX-1.0
# BindReadOnly=/usr/share/nvidia
# BindReadOnly=/var/lib/nvidia
# Важные файлы для поиска opengl и vulkan-совместимых устройств
# BindReadOnly=/etc/vulkan/icd.d/nvidia_icd.json
# BindReadOnly=/etc/vulkan/implicit_layer.d/nvidia_layers.json
# BindReadOnly=/etc/OpenCL/vendors/nvidia.icd
# Программы и утилитки
# BindReadOnly=/usr/bin/nvidia-bug-report.sh
# BindReadOnly=/usr/bin/nvidia-installer
# BindReadOnly=/usr/bin/nvidia-modprobe
# BindReadOnly=/usr/bin/nvidia-sleep.sh
# BindReadOnly=/usr/bin/nvidia-smi
# BindReadOnly=/usr/bin/nvidia-debugdump
# BindReadOnly=/usr/bin/nvidia-cuda-mps-control
# BindReadOnly=/usr/bin/nvidia-cuda-mps-server
# BindReadOnly=/usr/bin/nvidia-persistenced
# BindReadOnly=/usr/bin/nvidia-powerd
# BindReadOnly=/usr/bin/nvidia-xconfig
# BindReadOnly=/usr/bin/nvidia-settings
# BindReadOnly=/usr/bin/nvidia-ngx-updater
# 32-битные библиотеки
# BindReadOnly=/usr/lib/i386-linux-gnu/libcuda.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-ptxjitcompiler.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-ml.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-nvvm.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-opencl.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libGLX_nvidia.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-glcore.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-tls.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-glvkspirv.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-glsi.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/vdpau/libvdpau_nvidia.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvcuvid.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/vdpau/libvdpau_nvidia.so.1
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-encode.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-eglcore.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libEGL.so.1.1.0
# BindReadOnly=/usr/lib/i386-linux-gnu/libEGL_nvidia.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libGLESv2_nvidia.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libGLESv1_CM_nvidia.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-fbc.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-allocator.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-opticalflow.so.535.104.05
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-ptxjitcompiler.so.1
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-ptxjitcompiler.so
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-ml.so.1
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-ml.so
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-nvvm.so.4
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-nvvm.so
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-opencl.so.1
# BindReadOnly=/usr/lib/i386-linux-gnu/libGLX_nvidia.so.0
# BindReadOnly=/usr/lib/i386-linux-gnu/libvdpau_nvidia.so
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-encode.so.1
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-encode.so
# BindReadOnly=/usr/lib/i386-linux-gnu/libEGL_nvidia.so.0
# BindReadOnly=/usr/lib/i386-linux-gnu/libGLESv2_nvidia.so.2
# BindReadOnly=/usr/lib/i386-linux-gnu/libGLESv1_CM_nvidia.so.1
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-fbc.so.1
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-fbc.so
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-allocator.so.1
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-allocator.so
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-opticalflow.so.1
# BindReadOnly=/usr/lib/i386-linux-gnu/libnvidia-opticalflow.so
# 64-битные библиотеки
# BindReadOnly=/usr/lib/x86_64-linux-gnu/vdpau/libvdpau_nvidia.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/vdpau/libvdpau_nvidia.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-ml.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-ptxjitcompiler.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-nvvm.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-api.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-glcore.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-tls.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-glsi.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-glvkspirv.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-eglcore.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libEGL_nvidia.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libGLESv2_nvidia.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libGLESv1_CM_nvidia.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-egl-wayland.so.1.1.11
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-vulkan-producer.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-egl-gbm.so.1.1.0
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-gtk2.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-gtk3.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-wayland-client.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-cfg.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-allocator.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-rtcore.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvoptix.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-ngx.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-fbc.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvcuvid.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-encode.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-opticalflow.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-pkcs11.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-pkcs11-openssl3.so.535.104.05
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-ml.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-ml.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-opencl.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-ptxjitcompiler.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-ptxjitcompiler.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-nvvm.so.4
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-nvvm.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libGLX_nvidia.so.0
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libEGL_nvidia.so.0
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libGLESv2_nvidia.so.2
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libGLESv1_CM_nvidia.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-vulkan-producer.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-cfg.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-cfg.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libvdpau_nvidia.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-allocator.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-allocator.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/gbm/nvidia-drm_gbm.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-fbc.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-fbc.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-encode.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-encode.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-opticalflow.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-opticalflow.so
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-ngx.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-egl-gbm.so.1
# BindReadOnly=/usr/lib/x86_64-linux-gnu/libnvidia-egl-wayland.so.1
# Прочие файлы, из разряда "пусть будут"
# BindReadOnly=/usr/share/glvnd/egl_vendor.d/10_nvidia.json
# BindReadOnly=/usr/share/icons/hicolor/128x128/apps/nvidia-settings.png
# BindReadOnly=/usr/share/man/man1/nvidia-installer.1.gz
# BindReadOnly=/usr/share/man/man1/nvidia-modprobe.1.gz
# BindReadOnly=/usr/share/man/man1/nvidia-smi.1.gz
# BindReadOnly=/usr/share/man/man1/nvidia-cuda-mps-control.1.gz
# BindReadOnly=/usr/share/man/man1/nvidia-persistenced.1.gz
# BindReadOnly=/usr/share/man/man1/nvidia-xconfig.1.gz
# BindReadOnly=/usr/share/man/man1/nvidia-settings.1.gz
# BindReadOnly=/usr/share/egl/egl_external_platform.d/10_nvidia_wayland.json
# BindReadOnly=/usr/share/egl/egl_external_platform.d/15_nvidia_gbm.json
### Конец Bind'ов nVidia
[Network]
# Чтобы не приходилось настраивать сеть внутри контейнера,
# Мы делаем её общей с основной системой
Private=false
EOF
sudo tee /etc/systemd/system/systemd-nspawn@.service.d/override.conf << 'EOF'
[Service]
# Для разрешения вообще всех системных вызовов. Работает только на systemd 245+
# В Ubuntu 22.04 249. Так что сработает
Environment="SYSTEMD_SECCOMP=0"
# Доступ к https://ru.wikipedia.org/wiki/Direct_Rendering_Infrastructure
DeviceAllow=/dev/dri rw
# Возможность создавать общую память. Не уверен, что это нужно, не не повредит
DeviceAllow=/dev/shm rw
#cat /proc/devices to get aliases like "alsa" or "video4linux"
#"char-" means "character device"
# Проброс сырых usb-устройств
DeviceAllow=char-usb_device rwm
# проброс HID-устройств (мышеклавы, геймпады)
DeviceAllow=char-input rwm
# проброс звуковых устройств
DeviceAllow=char-alsa rwm
# проброс видеокамер
DeviceAllow=char-video4linux rwm
# проброс COM-портов
DeviceAllow=char-ttyUSB rwm
# Только для владельцев nvidia
DeviceAllow=char-nvidia-frontend
DeviceAllow=char-drm
DeviceAllow=char-nvidia-uvm
DeviceAllow=char-nvidia-nvswitch
DeviceAllow=char-nvidia-nvlink
DeviceAllow=char-nvidia-caps
# Для работы непосредственно с дисками внутри контейнера
# Позволяет запускать вещи вроде sudo dd /dev/sda
# Включать на свой страх и риск
# DeviceAllow=block-sd
# сигналим, что мы хотим перезаписать ExecStart=
ExecStart=
# --console=pipe
# Терминал берётся непосредственно из /dev/console
# Обязательно нужно, если пробрасываем папку /dev в контейнер
# --capability=all
# всё верно, чтобы контейнер мог всё
# --quiet
# без этого флага в консоль шли бы строки ещё и самого сервиса
# в придачу к строкам программ внутри контейнера
# --keep-unit
# служебная вещь для запуска из сервиса
# --link-journal=no
# логи контейнера не видны снаружи контейнера
# --settings=override
# настройки в /etc/systemd/nspawn могут перезаписывать параметры командной
# строки чуть ниже
ExecStart=systemd-nspawn --capability=all --console=pipe --quiet --keep-unit --boot --link-journal=no --settings=override --machine=%i
EOF
И наконец, обновляем настройки демона запуска, запускаем контейнер и заходим в него
sudo systemctl daemon-reload
sudo machinectl start devcont
sudo machinectl shell devuser@devcont
Если всё сделано правильно появится надпись:
Connected to machine devcont. Press ^] three times within 1s to exit session.
devuser@vrpc:~$
Как видите, настроить systemd-nspawn как таковой довольно просто, основные трудности -- это настроить сам контейнер.
Уже внутри контейнера, под обычным, не рутовым пользователем делаем вот это:
# Накидываем полезные репозитории
## cmake
wget -O - https://apt.kitware.com/keys/kitware-archive-latest.asc 2>/dev/null | gpg --dearmor - | sudo tee /usr/share/keyrings/kitware-archive-keyring.gpg >/dev/null
echo 'deb [signed-by=/usr/share/keyrings/kitware-archive-keyring.gpg] https://apt.kitware.com/ubuntu/ jammy main' | sudo tee /etc/apt/sources.list.d/kitware.list >/dev/null
## VsCode
wget -qO- https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > packages.microsoft.gpg
sudo install -D -o root -g root -m 644 packages.microsoft.gpg /etc/apt/keyrings/packages.microsoft.gpg
sudo sh -c 'echo "deb [arch=amd64,arm64,armhf signed-by=/etc/apt/keyrings/packages.microsoft.gpg] https://packages.microsoft.com/repos/code stable main" > /etc/apt/sources.list.d/vscode.list'
rm -f packages.microsoft.gpg
# boost 1.81
sudo add-apt-repository ppa:mhier/libboost-latest
И сразу ставим clang последней версии
# Clang Repo
wget https://apt.llvm.org/llvm.sh
sudo chmod +x llvm.sh
sudo ./llvm.sh
И кучу других программ, чисто за компанию. Тут намешано много ненужного, так что можете пропустить этот шаг или повыцепляйте то, что нужно именно вам. Тот же qtbase5-dev
тут только для будущей компиляции Gittyup, а *icon-theme*
-- для беспроблемного запуска графических программ независимо от того, какие им требуются иконки.
sudo apt install \
*icon-theme* apt-transport-https bash-completion bison btrfs-progs \
build-essential ca-certificates ccache checkinstall clang-18 \
clang-format-18 clang-tidy-18 clang-tools-18 clangd-18 cmake code \
command-not-found curl debconf-utils desktop-file-utils doxygen \
flex g++ gawk gcc gettext git gnupg \
gobject-introspection gpg htop hunspell hunspell-en-gb \
hunspell-en-us hunspell-ru \
kcachegrind language-pack-ru \
libcairo2-dev libcrypto++-dev libcurlpp-dev \
libgirepository1.0-dev \
libgmp-dev libgraphviz-dev \
libhunspell-dev libjsoncpp-dev \
liblz4-dev libmpc-dev libmpfr-dev libpq-dev \
libssl-dev libssl3 \
libtar-dev libtinyxml2-dev \
libyaml-dev libzip-dev \
libzstd-dev llvm-18-dev llvm-18-linker-tools \
llvm-18-runtime llvm-18-tools lsof man-db manpages mc meld \
nano openssh-server pkg-config psmisc python-is-python3 \
python3-cairo-dev python3-pip qt5-qmake qtbase5-dev qtcreator \
qttools5-dev ripgrep rsync ruby software-properties-common \
texinfo tmux tree valgrind wget x11-apps zlib1g-dev fonts-firacode \
qt5-image-formats-plugins aspell aspell-ru
# Без этого программы на GTK могут запускаться почти 10 секунд
# Не могу сказать, по какой причине
sudo apt remove dbus-user-session
sudo apt autoremove
Для clang потребуется вручную поставить алиасы, чтобы clang
был по-умолчанию clang-18
, clang++
-> clang++-18
и так далее
tee update-alternatives-clang.sh << 'EOF'
#!/usr/bin/env bash
# --slave /usr/bin/$1 $1 /usr/bin/$1-\${version} \\
function register_clang_version {
local version=$1
local priority=$2
update-alternatives \
--install /usr/bin/llvm-config llvm-config /usr/bin/llvm-config-${version} ${priority} \
--slave /usr/bin/llvm-ar llvm-ar /usr/bin/llvm-ar-${version} \
--slave /usr/bin/llvm-as llvm-as /usr/bin/llvm-as-${version} \
--slave /usr/bin/llvm-bcanalyzer llvm-bcanalyzer /usr/bin/llvm-bcanalyzer-${version} \
--slave /usr/bin/llvm-cov llvm-cov /usr/bin/llvm-cov-${version} \
--slave /usr/bin/llvm-diff llvm-diff /usr/bin/llvm-diff-${version} \
--slave /usr/bin/llvm-dis llvm-dis /usr/bin/llvm-dis-${version} \
--slave /usr/bin/llvm-dwarfdump llvm-dwarfdump /usr/bin/llvm-dwarfdump-${version} \
--slave /usr/bin/llvm-extract llvm-extract /usr/bin/llvm-extract-${version} \
--slave /usr/bin/llvm-link llvm-link /usr/bin/llvm-link-${version} \
--slave /usr/bin/llvm-mc llvm-mc /usr/bin/llvm-mc-${version} \
--slave /usr/bin/llvm-nm llvm-nm /usr/bin/llvm-nm-${version} \
--slave /usr/bin/llvm-objdump llvm-objdump /usr/bin/llvm-objdump-${version} \
--slave /usr/bin/llvm-ranlib llvm-ranlib /usr/bin/llvm-ranlib-${version} \
--slave /usr/bin/llvm-readobj llvm-readobj /usr/bin/llvm-readobj-${version} \
--slave /usr/bin/llvm-rtdyld llvm-rtdyld /usr/bin/llvm-rtdyld-${version} \
--slave /usr/bin/llvm-size llvm-size /usr/bin/llvm-size-${version} \
--slave /usr/bin/llvm-stress llvm-stress /usr/bin/llvm-stress-${version} \
--slave /usr/bin/llvm-symbolizer llvm-symbolizer /usr/bin/llvm-symbolizer-${version} \
--slave /usr/bin/llvm-tblgen llvm-tblgen /usr/bin/llvm-tblgen-${version}
update-alternatives \
--install /usr/bin/clang clang /usr/bin/clang-${version} ${priority} \
--slave /usr/bin/clang++ clang++ /usr/bin/clang++-${version} \
--slave /usr/bin/asan_symbolize asan_symbolize /usr/bin/asan_symbolize-${version} \
--slave /usr/bin/c-index-test c-index-test /usr/bin/c-index-test-${version} \
--slave /usr/bin/clang-check clang-check /usr/bin/clang-check-${version} \
--slave /usr/bin/clang-cl clang-cl /usr/bin/clang-cl-${version} \
--slave /usr/bin/clang-cpp clang-cpp /usr/bin/clang-cpp-${version} \
--slave /usr/bin/clang-format clang-format /usr/bin/clang-format-${version} \
--slave /usr/bin/clang-format-diff clang-format-diff /usr/bin/clang-format-diff-${version} \
--slave /usr/bin/clang-include-fixer clang-include-fixer /usr/bin/clang-include-fixer-${version} \
--slave /usr/bin/clang-offload-bundler clang-offload-bundler /usr/bin/clang-offload-bundler-${version} \
--slave /usr/bin/clang-query clang-query /usr/bin/clang-query-${version} \
--slave /usr/bin/clang-rename clang-rename /usr/bin/clang-rename-${version} \
--slave /usr/bin/clang-reorder-fields clang-reorder-fields /usr/bin/clang-reorder-fields-${version} \
--slave /usr/bin/clang-tidy clang-tidy /usr/bin/clang-tidy-${version} \
--slave /usr/bin/lldb lldb /usr/bin/lldb-${version} \
--slave /usr/bin/lldb-server lldb-server /usr/bin/lldb-server-${version}
update-alternatives \
--install /usr/bin/clangd clangd /usr/bin/clangd-${version} ${priority}
}
register_clang_version $1 $2
EOF
chmod +x update-alternatives-clang.sh
sudo ./update-alternatives-clang.sh 18 9999
Опционально можно можно сразу настроить clangd для vscode
# Убираем ошибки, связанные с анализом `compile_commands.json`
# Сделанным GCC, но используемым в clangd
mkdir -p ~/.config/clangd/
tee ~/.config/clangd/config.yaml << 'EOF'
CompileFlags:
Remove: [-flto*, -fopenmp]
Add: [
-ferror-limit=0,
-fconstexpr-backtrace-limit=0,
-Weverything,
-Wno-c++98-compat,
-Wno-exit-time-destructors,
-Wno-padded,
-Wno-unsafe-buffer-usage,
-Wno-unknown-warning-option,
-Wno-c99-designator,
-Wno-c++98-compat-pedantic,
-Wno-covered-switch-default,
-Wno-unused-macros,
-Wno-implicit-int-float-conversion,
-Wno-ctad-maybe-unsupported,
-Wno-weak-vtables,
-Wno-switch-enum,
-Wno-global-constructors,
-Wno-gnu-anonymous-struct,
-Wno-undefined-func-template
]
EOF
Моя настройки VSCode по-умолчанию. Это уже совсем-совсем необязательно
# "Стандартные" инструменты для работы с python и CMake
code --install-extension ms-python.python
code --install-extension ms-vscode.cmake-tools
# Автодополнение кода CMake
code --install-extension josetr.cmake-language-support-vscode
# Работа с CSV как будто в Excel
code --install-extension janisdd.vscode-edit-csv
# Цветовое выделение столбцов CSV в редакторе
code --install-extension mechatroner.rainbow-csv
# Работа с C++. Используется clangd вместо IntelliSense,
# она обычно быстрее и стабильнее, но ей требуется код, который
# clang сможет переварить.
code --install-extension llvm-vs-code-extensions.vscode-clangd
code --install-extension vadimcn.vscode-lldb
# Закладки
code --install-extension alefragnani.Bookmarks
# Конверсия табов в пробелы (вручную)
code --install-extension ilich8086.Untabify
# Проверка правописания
# Потребует вручную добавить все имена переменных в список исключений,
# Но после этого будет норм ловить опечатки в комментариях
code --install-extension streetsidesoftware.code-spell-checker
code --install-extension streetsidesoftware.code-spell-checker-russian
Мои настройки (ещё менее обязательные, чем расширения):
- Стандарт по-умолчанию стал c++20
- Шрифт -- Fira Code с включенными лигатурами
- IntelliSense вырублен
- Сlangd ищет
compile_commands.json
в${workspaceFolder}/build
- Вкладки в несколько строк вместо проматывания
- При сохранении удаляются лишние строки в конце файла и лишние проблемы в конце строки
- В XML/HTML, если набран открывающий тэг, закрывающий будет автонабран
- Проверка орфографии для русского и английского языков
tee ~/.config/Code/User/settings.json <<'EOF'
{
"C_Cpp.default.cppStandard": "c++20",
"C_Cpp.default.cStandard": "c17",
"git.openRepositoryInParentFolders": "never",
"editor.fontFamily": "Fira Code",
"editor.fontLigatures": true,
"C_Cpp.intelliSenseEngine": "Disabled",
"clangd.checkUpdates": true,
"clangd.path": "/usr/bin/clangd",
"clangd.arguments": [
"--compile-commands-dir=${workspaceFolder}/build",
"--completion-style=detailed",
"--header-insertion=never",
"--clang-tidy"
],
"editor.linkedEditing": true,
"workbench.editor.wrapTabs": true,
"files.trimFinalNewlines": true,
"files.trimTrailingWhitespace": true,
"cSpell.language": "en,ru"
}
EOF
Минимальные изменения в .bashrc, чтобы запустить VSCode
tee ~/.bashrc -a <<'EOF'
# Для проброса к x-серверу. Пока не знаю, как пробросить через Wayland.
# XWayland в помощь
export DISPLAY=:0
# Для запуска некоторых программ
export XDG_CONFIG_HOME="$HOME/.config"
EOF
Необязательные вещи для ~/.bashrc
tee ~/.bashrc -a <<'EOF'
# В основном для запуска скриптов, ставящихся через
# pip install
export PATH=~/.local/bin:$PATH
export PYTHONPATH="$PYTHONPATH:/home/devuser/lib/python3.10/site-packages"
# Для поиска по истории запросов в bash
alias higrep='history | grep '
# Удаляет все локальные папки, которые были удалены с апстрима
alias gpurge='git fetch -p && for branch in $(git for-each-ref --format "%(refname) %(upstream:track)" refs/heads | awk "\$2 == \"[gone]\" {sub(\"refs/heads/\", \"\", \$1); print \$1}"); do git branch -D $branch; done'
EOF
Проверяем, vscode должен запуститься
source ~/.bashrc
code
Все ещё внутри контейнера, выполняем следующее
# Уж собирать, так собирать под свою архитектуру
export CFLAGS="-O3 -march=native -ftree-vectorize"
export CXXFLAGS="-O3 -march=native -ftree-vectorize"
mkdir -p ~/custom-builds/binutils
Binutils -- это набор программ и библиотек для работы с объектными файлами, включая ассемблер и линкеры. Ставим самую последнюю компилируемую версию на момент написания статьи
cd ~/custom-builds/binutils
git clone --recurse-submodules git://sourceware.org/git/binutils-gdb.git
cd ~/custom-builds/binutils/binutils-gdb
# Версия binutils-2_42 не компилируется
git checkout binutils-2_41-release
mkdir -p ~/custom-builds/binutils/binutilsbuild
cd ~/custom-builds/binutils/binutilsbuild
../binutils-gdb/configure \
--enable-gold=yes --enable-ld=yes --enable-gprofng \
--enable-compressed-debug-sections=all \
--enable-default-compressed-debug-sections-algorithm=zstd \
--enable-libssp --enable-lto --with-system-zlib --with-zstd
make -j$(nproc)
# Отвечайте n, custombinutils, <Enter>, n, y
sudo checkinstall --pkgversion=9999 --pkgrelease=1 \
--pkglicense=GPL --pkgname=custombinutils
mkdir -p ~/custom-builds/gcc13
cd ~/custom-builds/gcc13
wget https://ftp.gnu.org/gnu/gcc/gcc-13.2.0/gcc-13.2.0.tar.xz
tar -xf gcc-13.2.0.tar.xz
mkdir -p ~/custom-builds/gcc13/gccbuild
cd ~/custom-builds/gcc13/gccbuild
../gcc-13.2.0/configure --enable-languages=c,c++,lto --disable-multilib
make -j$(nproc)
# Отвечайте n, customgcc13, <Enter>, n, y
sudo checkinstall --pkgversion=9999 --pkgrelease=1 --pkglicense=GPL --pkgname=customgcc13
sudo update-alternatives --install /usr/bin/cc cc /usr/local/bin/gcc 9999
sudo update-alternatives --install /usr/bin/c++ c++ /usr/local/bin/g++ 9999
sudo ln -sfn /usr/local/libexec/gcc/x86_64-pc-linux-gnu/13.2.0/liblto_plugin.so /usr/local/lib/bfd-plugins/liblto_plugin.so
sudo rm -rf ~/custom-builds/{binutils/binutilsbuild,gcc13/gccbuild}
cd
Diffuse -- это достаточно неплохой инструмент слияния при конфликтах. Показывает сразу четыре версии конфликтного файла: конфликтный документ, LOCAL(изменения из ветки, куда идёт слияние), REMOTE (изменения из ветки, которую вливают в текущую), BASE(версия документа до разделения веток)
cd ~/custom-builds/
git clone --recurse-submodules https://github.com/MightyCreak/diffuse.git
cd diffuse
# meson, в apt слишком старый
pip3 install meson
sudo pip3 install meson
pip3 install -r requirements.txt
meson build
# Отвечайте n, customdiffuse, <Enter>, n, y
sudo checkinstall --pkgversion=9999 --pkgrelease=1 --pkglicense=GPLv2 meson install -C build #Нужно будет поотвечать на вопросики
Gittyup -- Довольно простой, но неплохой GUI для git с возможностью стейджить не только файлы целиком, но и отдельные кусочки (hunks) или отдельные строчки
cd ~/custom-builds/
git clone --recurse-submodules https://github.com/Murmele/Gittyup.git
cd ~/custom-builds/Gittyup
patch << 'EOF'
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 3b1d8f3..6d72884 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -53,7 +53,7 @@ set(BUILD_SHARED_LIBS OFF)
option(FLATPAK "Building for flatpak" OFF)
option(DEBUG_FLATPAK "Building but using flatpak urls for testing" OFF)
option(ENABLE_UPDATE_OVER_GUI "Enable updating from the Gittyup gui" ON)
-option(USE_SYSTEM_OPENSSL "Use the system-wide OpenSSL installation" OFF)
+option(USE_SYSTEM_OPENSSL "Use the system-wide OpenSSL installation" ON)
option(
USE_SYSTEM_LIBGIT2
"Use the system-wide libgit2 installation (Gittyup requires the current development branch)"
EOF
mkdir -p ~/custom-builds/gittyup-build
cd ~/custom-builds/gittyup-build
cmake -G Ninja -DCMAKE_BUILD_TYPE=Release ../Gittyup
ninja
# Отвечайте n, customgittyup, <Enter>, n, y
sudo checkinstall --pkgversion=9999 --pkgrelease=1 --pkglicense=MIT ninja install
sudo apt remove gittyup # Да, эта строка должна быть. Это не ошибка
mkdir debtmp
sudo dpkg-deb -R gittyup_9999-1_amd64.deb debtmp
sudo rm -rf debtmp/usr/local/{include,lib,share/man}
sudo dpkg-deb -b debtmp gittyup-pkg.deb
sudo apt install ./gittyup-pkg.deb
По-умолчанию, /var/lib/machines
создана с такими правами, что даже список папок не посмотреть, не то что перейти внутрь. И символьные ссылки на эту папку и подпапки точно также будут выдавать ошибку доступа. Так что самый простой способ получить доступ -- использовать mound --bind
папки /var/lib/machines/devcont/home/devuser
-> /home/devuser
. Хотя создавать свои папки в /home
и не принято, если так сделать, все символьные ссылки вида /home/devuser/foo/bar
будут работать и внутри, и снаружи контейнера, и это удобно
Для начала небольшая проверка. Мы неявно предполагаем, что в системе есть только один пользователь, созданный в момент установки. Для проверки введите
id
Должна появится строка вроде
uid=1000(yourusename) gid=1000(yourusename)
группы=1000(yourusename),4(adm),20(dialout),27(sudo),
29(audio),44(video),46(plugdev),110(render)
И если uid
и gid
не равны 1000
, скорее всего с доступом будут проблемы. Уверен, что номер пользователя, созданного в контейнере, можно поменять, но в этой инструкции и так слишком много текста, а шанс на такое события очень невелик.
Итак, делаем автопроброс /home/devuser
из контейнера в основную систему
cd /home
sudo mkdir devuser
sudo chown -R 1000:1000 devuser
sudo tee -a /etc/fstab << 'EOF'
/var/lib/machines/devcont/home/devuser /home/devuser none bind 0 0
EOF
# монтируем все диски, прописанные в /etc/fstab
# к этому моменту всё уже должно быть смонтировано,
# кроме новой строки
sudo mount -a
В теории, мы могли бы сделать автозапуск через
sudo machinectl enable devcont
sudo machinectl start devcont
И если проброс графики или звука в систему не нужен, то этим можно и обойтись. Дело в том, что включение контейнера будет происходить до включения X-сервера (или XWayland), поэтому сокет /tmp/.X11-unix/X0
банально не появится. Это тем более верно для /run/user/1000/pulse/
, который не появится раньше, чем пользователь войдёт в систему.
Поэтому можно прописать "Ярлык" в "автозагрузку", который будет выполнятся только после входа пользователя в систему:
sudo tee /etc/xdg/autostart/devcont-launch.desktop << 'EOF'
[Desktop Entry]
Type=Application
Name=ContainerAutostart
Exec=sudo machinectl start devcont
EOF
Запускаем sudo visudo
и докидываем в конец файла эти строки
ALL ALL=NOPASSWD: /usr/bin/machinectl shell devuser@devcont*
ALL ALL=NOPASSWD: /usr/bin/machinectl start devcont
ALL ALL=NOPASSWD: /usr/bin/machinectl stop devcont
Для простоты, можем добавить алиас на вход в контейнер
tee -a ~/.bashrc << 'EOF'
alias cont='sudo /usr/bin/machinectl shell devuser@devcont '
EOF
. ~/.bashrc
По-умолчанию, в Ubuntu 22.04 кордампы не создаются в виде файлов, а обрабатываются штатной службой Apport.
Это адекватное решение, если нет нужды в отладке упавших программ, но при разработке кордампы могут помочь достаточно сильно, чтобы их игнорировать.
Вот инструкция по их включению. В основной системе:
# Удаляем Apport, чтобы он не мешал делать кордампы
sudo apt remove apport-symptoms apport
# Включаем возможность создания core-файлов
sudo tee -a /etc/sysctl.conf << 'EOF'
# Описание всех подстановок тут
# https://www.kernel.org/doc/Documentation/sysctl/kernel.txt
# В примере использованы
# %e -- имя исполняемого файла
# %u -- uid пользователя, который запустил программу
# %s -- номер сигнала, приведшего к дампу. Обычно SIGSEGV (11) или SIGABRT (6)
# %p -- id процесса, pid
# %t -- Unix timestamp момента создания дампа
kernel.core_pattern=core.%e.%u.%s.%p.%t
EOF
И в контейнере снимаем все лимиты на размер дампа
sudo tee -a /etc/security/limits.conf << 'EOF'
* soft core -1
EOF
Можно сделать то же самое и снаружи контейнера, тогда дампы будут создаваться по всей системе
Если вы вдруг захотите, чтобы некий сервис Systemd тоже делал дампы, то нужно прописать ему примерно такую строку:
# ...
[Service]
LimitCORE=infinity
# ...
Более детально о соотнесении limits.conf
с настройками сервисов можно найти здесь.
Признаться, адекватно простого способа сделать .desktop
файл я не нашёл. Зато нашёл неадекватно мудрёный, но рабочий вариант.
Внутри контейнера создаём некоторый аналог .bashrc
, который фактически запускает программу. Как-бы изнутри контейнера его запускает скрипт снаружи контейнера.
И уже этот скрипт запускается в .desktop
-файле. Ниже пример для ярлыка запуска VSCode внутри контейнера.
Для начала, нужно пройти к "Вход в контейнер без пароля" и сделать все инструкции в этом пункте. После этого, снаружи контейнера (при условии, что имя пользователя выбрано devuser)
cd /home/devuser/
tee runvscode.rc << 'EOF'
. /home/devuser/.bashrc
code
exit 0
EOF
mkdir -p ~/fordevcontdesktops
cd ~/fordevcontdesktops
tee vscoderun.sh << 'EOF'
#!/bin/bash
/usr/bin/sudo machinectl shell devuser@devcont /bin/bash --rcfile /home/devuser/runvscode.rc
EOF
# Нужно настроить вход в контейнер без пароля
# sudo visudo
# ALL ALL=NOPASSWD: /usr/bin/machinectl shell devuser@devcont*
chmod +x vscoderun.sh
# Запуск уже должен сработать
# ./vscoderun.sh
cd ~/Desktop/
tee vscodecontainer.desktop << 'EOF'
[Desktop Entry]
Type=Application
Exec=/bin/sh -c $HOME/fordevcontdesktops/vscoderun.sh
Name=VSCode in a container
EOF
Теперь двойной клик по vscodecontainer.desktop
должен сработать как надо, возможно, потребуется "одобрить" этот ярлык разными способами.
Этот метод точно работает для Cinnamon, и скорее всего сработает в остальных окружениях рабочего стола.
Для экспорта:
sudo machinectl export-tar devcont ./devcont.tar.gz # .xz или .bz2 тоже можно
cp /etc/systemd/nspawn/devcont.nspawn .
Для импорта:
sudo machinectl import-tar ./devcont.tar.gz devcont
cp ./devcont.nspawn /etc/systemd/nspawn/
Для клонирования:
sudo machinectl clone devcont experiment
Для удаления:
sudo machinectl remove experiment
Список всех запущенных контейнеров:
sudo machinectl list
Список всех запущенных образов:
sudo machinectl list-images
Надеюсь, эти инструкции кому-то да и помогут. Если будут вопросы -- пишите, постараюсь отвечать не реже раза в день, скорее чаще, но гарантий дать не могу.