Конвертация контейнера в виртуальную машину

    Команда Simple-Server
    03.06.2026
    12 мин

    Материал подготовлен командой Simple-Server для администраторов VPS и выделенных серверов. Команды и пути проверяйте на тестовой машине перед production.

    Конфигурация будущей виртуальной машины

    Предлагаю начать этот увлекательный путь с создания контейнера. Для этого мы воспользуемся Docker. Если он у вас всё ещё не установлен, установите его с помощью команды, приведенной ниже (перед этим может потребоваться обновить список доступных пакетов — sudo apt update).

    sudo apt install docker.io -y

    Создайте контейнер на основе минимального образа alpine и прикрепитесь к его командной оболочке

    sudo docker run --name test -it alpine sh

    Установите с помощью пакетного менеджера apk необходимые программы, которые вы планируете использовать в будущей виртуальной машине. Вам не обязательно ограничиваться пакетами из стандартного репозитория Alpine — вы также можете добавить другие репозитории, а при необходимости скачать или собрать пакеты прямо в контейнере.

    apk add tmux busybox-extras openssh-client openssh-server iptables dhclient ppp socat tcpdump vim openrc mkinitfs grub grub-bios

    Вот список минимально необходимых пакетов:

    • tmux — консольный мультиплексор. Он пригодится для сохранения пользовательской сессии и контекста выполняемых процессов в случае разрыва сетевого соединения.

    • busybox-extras — расширенная версия BusyBox, которая включает в себя дополнительные утилиты, но по-прежнему остается компактным дистрибутивом стандартных инструментов.

    • openssh-client и openssh-server — клиент и сервер OpenSSH, необходимые для организации удаленных подключений.

    • iptables — утилита для настройки правил фильтрации IP-пакетов.

    • dhclient — DHCP-клиент, автоматизирующий конфигурацию сетевых настроек.

    tmux — консольный мультиплексор. Он пригодится для сохранения пользовательской сессии и контекста выполняемых процессов в случае разрыва сетевого соединения.

    busybox-extras — расширенная версия BusyBox, которая включает в себя дополнительные утилиты, но по-прежнему остается компактным дистрибутивом стандартных инструментов.

    openssh-client и openssh-server — клиент и сервер OpenSSH, необходимые для организации удаленных подключений.

    iptables — утилита для настройки правил фильтрации IP-пакетов.

    dhclient — DHCP-клиент, автоматизирующий конфигурацию сетевых настроек.

    • ppp — пакет для реализации канального протокола Point-to-Point.

    ppp — пакет для реализации канального протокола Point-to-Point.

    • socat — программа для создания туннелей, аналогичная netcat, с поддержкой шифрования и функционалом интерактивной командной оболочки.

    • tcpdump — утилита для захвата трафика, может пригодиться для отладки сетевых неисправностей.

    • vim — консольный текстовый редактор с богатыми возможностями кастомизации. Популярен среди опытных пользователей ОС Linux.

    • openrc — система инициализации, основанная на управлении зависимостями, работающая в связке с SysVinit. Один из ключевых компонентов, необходимых для превращения контейнера в виртуальную машину, поскольку контейнеры не имеют ее по умолчанию.

    • mkinitfs — пакет для генерации initramfs, позволяющий собрать необходимые драйверы и модули, загружаемые на начальном этапе инициализации системы.

    • grub и grub-bios — загрузчик ОС. В данном случае нас интересует именно создание загрузчика для систем с BIOS, использующих таблицу разделов MBR.

    socat — программа для создания туннелей, аналогичная netcat, с поддержкой шифрования и функционалом интерактивной командной оболочки.

    tcpdump — утилита для захвата трафика, может пригодиться для отладки сетевых неисправностей.

    vim — консольный текстовый редактор с богатыми возможностями кастомизации. Популярен среди опытных пользователей ОС Linux.

    openrc — система инициализации, основанная на управлении зависимостями, работающая в связке с SysVinit. Один из ключевых компонентов, необходимых для превращения контейнера в виртуальную машину, поскольку контейнеры не имеют ее по умолчанию.

    mkinitfs — пакет для генерации initramfs, позволяющий собрать необходимые драйверы и модули, загружаемые на начальном этапе инициализации системы.

    grub и grub-bios — загрузчик ОС. В данном случае нас интересует именно создание загрузчика для систем с BIOS, использующих таблицу разделов MBR.

    Задайте пароль суперпользователю:

    export PASSWORD=<ваш секретный пароль> echo "root:$PASSWORD" | chpasswd

    Создайте пользователя. В дальнейшем он понадобится для удаленного подключения по SSH:

    export USERNAME=<имя пользователя> adduser -s /bin/sh $USERNAME

    Установите SUID-бит на исполняемый файл busybox. Это нужно для того, чтобы пользователь мог запускать команды с правами суперпользователя:

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

    cat <<EOF > /etc/local.d/init.start #!/bin/sh dmesg -n 1 mount -o remount,rw / ifconfig lo 127.0.0.1 netmask 255.0.0.0 dhclient eth0 # ifconfig eth0 172.16.0.200 netmask 255.255.255.0 # route add -net default gw 172.16.0.1 busybox-extras telnetd EOF

    Рассмотрим скрипт построчно:

    • dmesg -n 1 — выводит критические сообщения из буфера ядра Linux, чтобы при запуске можно было обнаружить возможные неполадки.

    • mount -o remount,rw / — перемонтирует корневую ФС (/) с параметром rw (чтение и запись). Эта манипуляция позволит изменять ФС после загрузки.

    • ifconfig lo 127.0.0.1 netmask 255.0.0.0 — настраивает интерфейс loopback (lo) с IP-адресом 127.0.0.1 и маской подсети 255.0.0.0. Это необходимо для обеспечения внутренней сетевой связи на машине.

    • dhclient eth0 — запускает DHCP-клиент для интерфейса eth0, чтобы автоматически получить настройки IP-адреса и другие параметры сети от DHCP-сервера.

    • # ifconfig eth0 172.16.0.200 netmask 255.255.255.0 — эта строка закомментирована, но при раскомментировании задаст статический IP-адрес 172.16.0.200 и маску подсети 255.255.255.0 для интерфейса eth0. Я добавил эту строку в скрипт на случай, если потребуется статическая конфигурация сети.

    • # route add -net default gw 172.16.0.1 — эта строка тоже закомментирована, но при раскомментировании добавит маршрут по умолчанию с шлюзом 172.16.0.1. Это определяет, как пакеты будут маршрутизироваться в сеть за пределами локальной сети.

    • busybox-extras telnetd — запускает Telnet-сервер. Обратите внимание, что использование протокола Telnet в продуктивных средах не рекомендуется из-за отсутствия шифрования при передаче данных.

    dmesg -n 1 — выводит критические сообщения из буфера ядра Linux, чтобы при запуске можно было обнаружить возможные неполадки.

    mount -o remount,rw / — перемонтирует корневую ФС (/) с параметром rw (чтение и запись). Эта манипуляция позволит изменять ФС после загрузки.

    ifconfig lo 127.0.0.1 netmask 255.0.0.0 — настраивает интерфейс loopback (lo) с IP-адресом 127.0.0.1 и маской подсети 255.0.0.0. Это необходимо для обеспечения внутренней сетевой связи на машине.

    dhclient eth0 — запускает DHCP-клиент для интерфейса eth0, чтобы автоматически получить настройки IP-адреса и другие параметры сети от DHCP-сервера.

    # ifconfig eth0 172.16.0.200 netmask 255.255.255.0 — эта строка закомментирована, но при раскомментировании задаст статический IP-адрес 172.16.0.200 и маску подсети 255.255.255.0 для интерфейса eth0. Я добавил эту строку в скрипт на случай, если потребуется статическая конфигурация сети.

    # route add -net default gw 172.16.0.1 — эта строка тоже закомментирована, но при раскомментировании добавит маршрут по умолчанию с шлюзом 172.16.0.1. Это определяет, как пакеты будут маршрутизироваться в сеть за пределами локальной сети.

    busybox-extras telnetd — запускает Telnet-сервер. Обратите внимание, что использование протокола Telnet в продуктивных средах не рекомендуется из-за отсутствия шифрования при передаче данных.

    Сделайте скрипт исполняемым:

    chmod +x /etc/local.d/init.start

    Добавьте скрипт автоматической настройки в автозапуск:

    Добавьте демон OpenSSH-сервера в автозапуск. Это понадобится для того, чтобы в дальнейшем подключаться к облачному серверу по SSH:

    rc-update add sshd default

    Установите DNS-сервер по умолчанию:

    echo nameserver 8.8.8.8 > /etc/resolv.conf

    Открепитесь от терминала с помощью команды exit или комбинации клавиш CRTL+D. На следующем этапе нам нужно сохранить файловую систему контейнера на хосте в виде архива, что также можно сделать с помощью Docker. В моем случае конечный артефакт занимает всего 75 мегабайт.

    sudo docker export test > test.tar

    Трансформация Docker-образа в образ для виртуальной машины

    Контейнеры представляют собой Linux-специфичную технологию, поскольку они не имеют своего ядра и используют абстракции хостового ядра Linux для обеспечения изоляции и управления ресурсами. К основным абстракциям относятся:

    • namespaces — изоляция относительно пространств имен: USER, TIME, PID, NET, MOUNT, UTS, IPC, CGROUP.

    • cgroups — ограничение относительно ресурсов: CPU, RAM, I/O.

    • capabilities — набор возможностей для выполнения определенных, в том числе привилегированных, операций без прав суперпользователя.

    namespaces — изоляция относительно пространств имен: USER, TIME, PID, NET, MOUNT, UTS, IPC, CGROUP.

    cgroups — ограничение относительно ресурсов: CPU, RAM, I/O.

    capabilities — набор возможностей для выполнения определенных, в том числе привилегированных, операций без прав суперпользователя.

    Эти компоненты ядра Linux делают Docker и другие контейнерные технологии тесно связанными с Linux, что делает невозможной их нативную работу на других операционных системах, таких как Windows, macOS или BSD*.

    Для работы на Windows, macOS и BSD* существует Docker Desktop, который представляет собой виртуальную машину с минимальной операционной системой на основе ядра Linux. Внутри этой виртуальной машины установлен и запущен Docker Engine, который позволяет пользователям управлять контейнерами и образами Docker в привычной среде.

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

    Создайте файл-образ, с которым мы будем работать дальше:

    truncate -s 200M test.img

    С помощью fdisk создайте раздел на образе test.img.

    echo -e "n\np\n1\n\n\nw" | fdisk test.img
    • n — создание нового раздела
    • p — указание того, что это будет основной (primary) раздел
    • 1 — номер нового раздела
    • \n\n — использование значений по умолчанию для начального и конечного секторов
    • w — запись изменений

    Теперь свяжите файл-образ test.img с устройством /dev/loop3, начиная со смещения 2048 блоков по 512 байт каждый (1 МБ):

    sudo losetup -o $[2048*512] /dev/loop3 test.img

    Обратите внимание, что устройство /dev/loop3 может быть уже задействовано — часто первые несколько loop-интерфейсов уже используются. Вы можете проверить занятые устройства с помощью следующей команды:

    Отформатируйте раздел, связанный с /dev/loop3, в файловую систему EXT4:

    sudo mkfs.ext4 /dev/loop3

    Смонтируйте /dev/loop3 в директорию /mnt:

    sudo mount /dev/loop3 /mnt

    Разархивируйте предварительно созданный Docker-образ test.tar в директорию /mnt:

    sudo tar xvf test.tar -C /mnt

    Создайте директорию /mnt/boot для размещения файлов загрузчика и ядра:

    Скачайте исходный код ядра Linux:

    wget https://cdn.kernel.org/pub/linux/kernel/v6.x/linux-6.8.9.tar.xz

    Разархивируйте исходный код ядра Linux в текущую директорию:

    tar xf linux-6.8.9.tar.xz

    Установите необходимые пакеты для сборки ядра Linux:

    sudo apt install git fakeroot build-essential ncurses-dev xz-utils libssl-dev bc flex libelf-dev bison -y

    Перейдите в директорию c исходным кодом и создайте конфигурационный файл для сборки по умолчанию:

    cd linux-6.8.9 make defconfig

    Добавьте необходимые параметры в файл конфигурации (вы также можете воспользоваться menuconfig — sudo make menuconfig):

    echo -e "CONFIG_BRIDGE=y\nCONFIG_TUN=y\nCONFIG_PPP=y\nCONFIG_PPP_ASYNC=y\nCONFIG_PPP_DEFLATE=y" >> .config
    • CONFIG_BRIDGE=y — поддержка сетевых мостов для объединения нескольких сетевых интерфейсов в один.

    • CONFIG_TUN=y — поддержка виртуальных сетевых интерфейсов TUN/TAP. Может пригодиться, если понадобится использовать VPN.

    • CONFIG_PPP=y — поддержка протокола Point-to-Point Protocol (PPP).

    • CONFIG_PPP_ASYNC=y — обеспечение работы асинхронного режима PPP для последовательных портов.

    • CONFIG_PPP_DEFLATE=y — сжатие данных PPP с помощью алгоритма DEFLATE.

    CONFIG_BRIDGE=y — поддержка сетевых мостов для объединения нескольких сетевых интерфейсов в один.

    CONFIG_TUN=y — поддержка виртуальных сетевых интерфейсов TUN/TAP. Может пригодиться, если понадобится использовать VPN.

    CONFIG_PPP=y — поддержка протокола Point-to-Point Protocol (PPP).

    CONFIG_PPP_ASYNC=y — обеспечение работы асинхронного режима PPP для последовательных портов.

    CONFIG_PPP_DEFLATE=y — сжатие данных PPP с помощью алгоритма DEFLATE.

    Подготовьте исходный код, создайте вспомогательные скрипты, соберите сжатый образ ядра (bzImage) и модули ядра. На этапе выбора параметров оставьте все значения по умолчанию

    make prepare -j4 make scripts -j4 make bzImage -j4 make modules -j4

    Установите собранное ядро и модули в директорию, где находится ФС нашего образа — /mnt/boot.

    sudo make INSTALL_PATH=/mnt/boot install sudo make INSTALL_MOD_PATH=/mnt modules_install

    Установите загрузчик GRUB для образа test.img в директорию /mnt/boot (убедитесь, что вы находитесь в директории с образом test.img):

    sudo grub-install --target=i386-pc --boot-directory=/mnt/boot --modules='part_msdos' /dev/loop3

    Смонтируйте директории хостовой системы /proc, /sys и /dev в /mnt. Это понадобится для создания initramfs:

    sudo mount --bind /proc /mnt/proc/ sudo mount --bind /sys /mnt/sys/ sudo mount --bind /dev /mnt/dev/

    Произведите chroot — прикрепитесь к ФС, находящейся в /mnt, с помощью оболочки командной строки sh:

    mkinitfs -k -o /boot/initrd.img-6.8.9 6.8.9

    Сгенерируйте конфигурацию загрузчика GRUB:

    grub-mkconfig -o /boot/grub/grub.cfg

    Создание образа завершено. В результате мы получили артефакт в виде небольшого образа для виртуальной машины

    Локальная проверка собранного образа

    Для локальной проверки работоспособности наиболее удобно использовать QEMU. Этот пакет доступен для Windows, macOS и Linux. Установите его, следуя инструкции для вашей ОС на официальном сайте, если он еще не установлен.

    Конвертируйте test.img в формат qcow2. Это позволит уменьшить размер итогового образа с 200 МБ до 134 МБ.

    qemu-img convert test.img -O qcow2 test.qcow2

    Запустите образ с помощью QEMU.

    qemu-system-x86_64 -hda test.qcow2

    Если все шаги были выполнены корректно, процесс инициализации пройдет успешно, и появится интерактивное меню для ввода логина и пароля.

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

    Создание виртуальной машины в Simple-Server

    Перейдите в раздел «Облачные серверы» и начните процесс создания нового сервера. В качестве образа для сервера выберите только что подготовленный и проверенный образ. Для этого сначала добавьте его в список доступных образов. В качестве поддерживаемых форматов доступны: iso, qcow2, vmdk, vhd, vhdx, vdi, raw, img.

    Загрузите образ одним из доступных вариантов: с компьютера или по ссылке.

    Обратите внимание, что после загрузки образ также становится доступен по URL.

    Продолжите создание облачного сервера и укажите остальные параметры его конфигурации. Так как образ минимальный, то и запустить его можно будет на самой маленькой конфигурации.

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

    Виртуальная машина создана и работает корректно.

    Поскольку мы добавили в автозагрузку демон OpenSSH заранее, теперь возможно установить полноценное удаленное подключение к серверу с помощью имени пользователя, IP-адреса и пароля.


    Нужен сервер для практики? Арендуйте VPS/VDS в России — root-доступ, NVMe, DDoS-защита и поддержка 24/7.

    VPS для проекта

    VPS с root-доступом, NVMe и поддержкой 24/7 на Simple-Server.

    StarterVDS

    490₽

    в месяц

    1 ядро

    1 ГБ RAM

    20 ГБ NVMe

    • 1 IPv4
    • KVM
    • Root-доступ
    • Безлимитный трафик
    Заказать VPS
    Рекомендуем

    PerformanceVDS

    1190₽

    в месяц

    2 ядра

    4 ГБ RAM

    60 ГБ NVMe

    • 1 IPv4
    • KVM
    • Root-доступ
    • Базовая DDoS-защита
    Заказать VPS

    Нужна другая конфигурация или чистый VPS без панели?

    Все тарифы VPS

    Похожие статьи, которые могут быть вам интересны