Работа с systemd-nspawn
Значит
в один день мне захотелось поднять Ubuntu для деб-сервера в каком нибудь роде контейнере. Тогда я решил, что использовать chroot - не то. Мне нужно было обойтись без виртуализации, и в то же время получить возможность работы с systemd и её systemctl. Тогда я начал гуглить, и первой ссылкой в гугле по запросу "systemd in chroot" оказалась статья на ArchWiki про systemd-nspawn. Там прямым языком говорилось, что systemd-nspawn - chroot на стеройдах. Я прочитал несколько строчек и охренел насколько же легко им пользоваться. Но обо всём по порядку. Для начала, давайте вообще попробуем создать контейнер для будущего использования. Если у вас уже есть система, установленная как chroot-контейнер, можете пропустить инструкцию по созданию. И так, давайте сделаем контейнер с убунту, используя Arch Linux(можете команды с пакетным менеджером заменить на подобные-свои.)
После, войдем под рутом и сделаем папку с нашим будущим контейнером
После создания папки, установим в неё систему.
Процесс может быть длинным. У меня это заняло 10 минут.
После установки системы, можем сразу одной командой запускать наш контейнер. Для более легкого процесса, я подготовил свой собственный скрипт - nctl
который вы можете найти в самом низу статьи. Скопируйте его и поместите в /usr/bin/nctl
Далее установим текстовый редактор, и починим логин от рута
Добавим в конец файла pts/0 до pts/9, а затем сохраним, используя Ctrl+X Y Enter
После этого зададим пароль рута
passwd root
выйдем из машины через Ctrl+]]] (быстро нажать), и на этот раз сделаем в неё загрузку systemd как PID 1
nctl -b ubuntu или systemd-nspawn -b -D ubuntu
Далее создадим нового пользователя, зададим ему пароль и добавим в группу.
groupadd myusers
useradd -m -g myusers name
passwd name
Установим sudo
apt install sudo
EDITOR=nano visudo
Добавим строчку
name ALL=(ALL:ALL) ALL
Перезагрузим систему и войдем от нового пользователя.
poweroff
nctl -b ubuntu
Логинимся от нашего созданного пользователя.
Теперь, отредачим репозитории, что бы были не только версии программ на момент выхода Ubuntu 18.04, но и появились обновления.
sudo nano /etc/apt/sources.list
Теперь давайте выключим стандартный systemd-resolved для сети. Так как он будет мешать нам получать DNS адреса, соответственно интернет работать не будет.
sudo systemctl disable --now systemd-resolved
sudo rm /etc/resolv.conf
sudo touch /etc/resolv.conf && sudo echo 8.8.8.8 >> /etc/resolv.conf && sudo chattr +i /etc/resolv.conf
Далее обновляем базу репозиториев и обновим программы.
sudo apt update && sudo apt upgrade
Ну вот и всё! У вас теперь есть система в контейнере. Если хочется запускать систему в фоне, то тут уже понадобиться использовать machinectl
. Но стоп, для начала надо написать для него .nspawn файл, иначе не будет работать сеть и похерятся права на файлы. У вас будет не что то вроде anatoliy users, а 19274610 19274610. И так, выйдем из машины используя Ctrl+]]], или откроя терминал и написав там nctl -k ubuntu
cd /etc/systemd && mkdir nspawn && nano nspawn/ubuntu.nspawn
Файл должен быть вот такого содержания:
Теперь, запустим наш контейнер.
machinectl start ubuntu
(через nctl -k можно также выключать и контейнеры, запущенные через machinectl)
Что бы зайти в контейнер под каким либо пользователем, введите
machinectl shell name@ubuntu
Готово! Теперь у вас есть контейнер system-nspawn. Можно использовать какой либо дистрибутив в контейнере, имея при этом доступ к функциям systemd. Спасибо за прочтение.
Скрипт
#!/bin/bash
if [ -z "$1" ]; then
echo "-b / --boot
-s / --start
-k / --kill
-l / --list"
exit
else
true
fi
case "$1" in
-b|--boot)
if [ -z "$2" ]; then
echo "Type machine you need to boot"
exit
else
true
fi
if [ -z "$($0 back-list- | grep -x $2)" ]; then
true
else
echo "Machine is already running"
exit
fi
if [ "$(systemctl is-active systemd-nspawn@$2.service)" == active ]; then
echo -e "Machine is already running using \e[4mmachinectl\e[0m systemd-nspawn service"
exit
else
true
fi
su -c "systemd-nspawn -b -D /var/lib/machines/$2"
;;
-s|--start)
if [ -z "$2" ]; then
echo "Type machine you need to start"
exit
else
true
fi
if [ -z "$($0 back-list- | grep -x $2)" ]; then
true
else
echo "Machine is already running"
exit
fi
if [ "$(systemctl is-active systemd-nspawn@$2.service)" == active ]; then
echo -e "Machine is already running using \e[4mmachinectl\e[0m systemd-nspawn service"
exit
else
true
fi
su -c "systemd-nspawn -D /var/lib/machines/$2"
;;
-k|--kill)
if [ -z "$(systemctl | grep "machine-\|systemd-nspawn@")" ]; then
echo "Nothing started"
exit
else
true
fi
if [ -z "$2" ]; then
echo "Type machine you need to kill"
exit
else
true
fi
if [ "$(systemctl is-active systemd-nspawn@$2.service)" == active ]; then
su -c "systemctl stop systemd-nspawn@$2.service"
exit
else
true
fi
if [ -z "$($0 back-list- | grep -x $2)" ]; then
echo "Machine with this name isn't running"
exit
else
true
fi
su -c "systemctl stop machine-$2.scope"
;;
back-list-)
if [ -z "$(systemctl | grep "machine-")" ]; then
echo "No machines are running"
exit
else
true
fi
systemctl | grep "machine-" | cut -c1-50 | sed "s/.*-//" | cut -d '.' -f -1
;;
-l|--list)
if [ -z "$(systemctl | grep "machine-\|systemd-nspawn@")" ]; then
echo "No machines are running"
exit
else
true
fi
systemctl | grep "machine-" | cut -c1-50 | sed "s/.*-//" | cut -d '.' -f -1
if [ -z "$(systemctl | grep "systemd-nspawn@")" ]; then true; else
echo -e "\e[95m machinectl:\e[m\e[1;92m"
fi
systemctl | grep "systemd-nspawn@" | cut -c1-50 | sed "s/.*@//" | cut -d '.' -f -1
;;
*)
echo "-b / --boot
-s / --start
-k / --kill
-l / --list"
;;
esac