Виртуализация и контейнеризация. Замена масла и свеч в Docker.

Виртуализация и контейнеризация
⚠️ предупреждение!

Термин виртуализация является перегруженным и может использоваться не только в контексте виртуализированного оборудования. Например, виртуализация на уровне операционной системы (контейнеризация) — это связанный, но принципиально другой набор технологий. Сегодня мы разберёмся в этих различиях!

Аппаратная виртуализация

Возможность запуска нескольких изолированных операционных систем на одной физической машине. Программное обеспечение для виртуализации распределяет ресурсы процессора, памяти и ввода-вывода между гостевыми ОС. С точки зрения пользователя, каждая виртуальная машина работает как полноценный физический сервер.

Гипервизоры (Hypervisors)

Гипервизор (монитор виртуальной машины) — это программный слой, который выступает посредником между виртуальными машинами и физическим оборудованием:

Типы гипервизоров

Type 1 (Bare-Metal)

Гипервизор 1 типа

Работает непосредственно на аппаратном уровне без хостовой ОС. По сути представляет собой минимальную операционную систему. Примеры: VMware ESXi, Microsoft Hyper-V, KVM.

Type 2 (Хостовый)

Гипервизор 2 типа

Работает как приложение внутри основной операционной системы. Примеры: VMware Workstation, Oracle VirtualBox, Microsoft Virtual PC.

Контейнеризация

Контейнеризация — это принципиально иной подход к изоляции, который не использует гипервизоры. Вместо этого применяются механизмы ядра операционной системы:

Что такое контейнер?

  • Это изолированный процесс со своим окружением
  • Использует общее ядро хостовой системы
  • Включает все необходимые зависимости и библиотеки

Из книги "Ядро Linux" Роберта Лава:

Процесс — это программа в состоянии выполнения, которая включает набор ресурсов: открытые файлы, сигналы, состояние процессора, адресное пространство памяти. В Linux это структура task_struct.

Механизмы изоляции

  • cgroups — контроль потребления ресурсов:
    • Память (Memory)
    • ЦПУ (CPU)
    • Сеть (Network)
    • Ввод-вывод (I/O)
  • namespaces — изоляция пространств имён:
    • pid, network, ipc, mount
    • uts, user, cgroup
  • capabilities — ограничение прав процессов

Архитектура Docker

Архитектура Docker

Docker Client

Интерфейс для взаимодействия пользователя с Docker. Позволяет управлять контейнерами без глубокого погружения в детали реализации.

docker run --name test -it busybox
docker ps
docker stop test && docker rm test

Docker Daemon

Фоновый процесс, который управляет Docker-объектами (образами, контейнерами, сетями, томами).

systemctl status docker.service
pstree | grep dockerd

containerd

Высокоуровневый рантайм для управления жизненным циклом контейнеров. Отвечает за:

  • Загрузку образов из реестров
  • Хранение образов
  • Передачу работы runc

runc

Низкоуровневый инструмент для создания и запуска контейнеров согласно спецификации OCI.

mkdir ~/runc-examples && cd ~/runc-examples
runc spec
cat config.json

Пример конфигурации runc (config.json)

{
    "ociVersion": "1.0.2-dev",
    "process": {
        "capabilities": {
            "bounding": [
                "CAP_AUDIT_WRITE",
                "CAP_KILL",
                "CAP_NET_BIND_SERVICE"
            ]
        },
        "rlimits": [
            {
                "type": "RLIMIT_NOFILE",
                "hard": 1024,
                "soft": 1024
            }
        ]
    },
    "root": {
        "path": "rootfs",
        "readonly": true
    },
    "hostname": "runc",
    "namespaces": [
        { "type": "pid" },
        { "type": "network" },
        { "type": "ipc" },
        { "type": "uts" },
        { "type": "mount" },
        { "type": "cgroup" }
    ]
}

Практический пример

Скрипт для автоматической установки Docker и тестирования работы контейнера:

#!/bin/bash
set -e

check_docker_installed() {
    if ! command -v docker &> /dev/null; then
        echo "Starting installation..."
        install_docker
    else
        echo "✓ Docker is installed!"
        docker --version
    fi
}

install_docker() {
    echo "Installing Docker for Ubuntu"
    sudo apt-get update 
    sudo apt-get install -y ca-certificates curl
    sudo install -m 0755 -d /etc/apt/keyrings
    sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
              -o /etc/apt/keyrings/docker.asc
    sudo chmod a+r /etc/apt/keyrings/docker.asc

    sudo apt-get install -y docker-ce \
                        docker-ce-cli \
                        containerd.io \
                        docker-buildx-plugin \
                        docker-compose-plugin
    
    sudo systemctl start docker
    sudo usermod -aG docker $USER
    newgrp docker
    
    echo "✓ Docker installed successfully!"
    docker --version
}

run_test_container() {
    echo "=== Starting test container ==="
    docker run -d --name test-nginx -p 8080:80 nginx:alpine
    
    if docker ps | grep -q test-nginx; then
        echo "✓ Container is running"
        sleep 2
        
        if curl -s http://localhost:8080 | grep -q "Welcome to nginx"; then
            echo "✓ Nginx is working correctly!"
        else
            echo "✗ Error: Nginx is not responding"
            exit 1
        fi
    fi
}

cleanup() {
    echo "=== Cleaning up ==="
    docker stop test-nginx &> /dev/null
    docker rm test-nginx &> /dev/null
    echo "✓ Container removed"
    
    echo "=== System info ==="
    docker ps -a
    docker images
}

main() {
    check_docker_installed
    run_test_container
    cleanup
}

main