Форум программистов, компьютерный форум, киберфорум
Mr. Docker
Войти
Регистрация
Восстановить пароль

Исследование рантаймов контейнеров Docker, containerd и rkt

Запись от Mr. Docker размещена 11.05.2025 в 20:24
Показов 4701 Комментарии 0
Метки containerd, devops, docker, rkt

Нажмите на изображение для увеличения
Название: 5b113bae-e67a-458e-ae5d-b00a3ddc7694.jpg
Просмотров: 111
Размер:	197.9 Кб
ID:	10793
Когда мы говорим о контейнерных рантаймах, мы обсуждаем программные компоненты, отвечающие за исполнение контейнеризованных приложений. Это тот слой, который берет образ контейнера и превращает его в работающий процесс. Без контейнерного рантайма ваши красиво упакованные микросервисы остались бы просто набором файлов и метаданных. Взаимодействие с ядром, настройка cgroups и namespaces, управление хранилищем и оркестрация сетевого взаимодействия — всё это задачи, которые ложатся на плечи рантаймов. А знаменитый стандарт OCI (Open Container Initiative) выступает своеобразным "законом контейнерного мира", обеспечивая совместимость между различными реализациями.

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

Containerd — это эволюция основного рантайма Docker, выделенная в отдельный проект. Лёгкий, модульный, заточенный под интеграцию с Kubernetes, этот рантайм ближе к философии Unix: "делай одну вещь, но делай её хорошо".

И наконец, rkt (произносится "рокет") — альтернативный подход от команды CoreOS, созданный с фокусом на безопасность, стандарты и интеграцию с системными компонентами Linux. Это рантайм, который не использует демон-модель и работает напрямую с ядром.

История развития контейнеризации



Контейнерные технологии не свалились на нас внезапно как снег в июле — их корни уходят глубоко в историю UNIX-систем. Первые зачатки контейнеризации появились ещё в 1979 году с механизмом chroot, который позволял изолировать файловую систему для процесса. Эта функция, конечно, была далека от полной изоляции, но именно она стала первым кирпичиком в фундаменте современных контейнеров. Конец 90-х и начало 2000-х подарили нам FreeBSD Jails и Solaris Zones — технологии, которые расширили понятие изоляции, добавив разделение процессов и сетевого стека. Эти "протоконтейнеры" уже использовались системными администраторами для разделения серверов на более мелкие и безопасные единицы. Тогда ещё никто не называл это "микросервисами", но концептуально это было очень близко.

В 2006-2007 годах произошел важный скачок — в ядро Linux были включены технологии namespaces и cgroups. Именно эти две технологии образовали костяк современной контейнеризации в Linux. Control Groups (cgroups) позволили ограничивать ресурсы для групп процессов, а namespaces обеспечили изоляцию на уровне файловой системы, сети, процессов и пользоватлей. Но долгое время эти технологии оставались прерогативой узкого круга системных администраторов и спецов по виртуализации. Всё изменилось в 2013 году, когда маленькая компания dotCloud, испытывающая финансовые трудности, решила открыть свой внутренний инструмент для развертывания приложений — Docker.

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

Поначалу Docker фактически монополизировал рынок контейнерных технологий. Термины "Docker" и "контейнер" использовались почти как синонимы. Однако, как и в любой быстро растущей сфере, вскоре начала происходить диверсификация и фрагментация.

В 2014-2015 годах начал формироваться интерес к стандартизации контейнеров. Многие компании, включая Google, IBM, Red Hat и CoreOS, высказывали опасения насчёт того, что одна компания (Docker Inc.) держит в своих руках ключевую технологию будущего. Вопросы совместимости, переносимости и открытости стандартов становились всё более актуальными. В этот период появились альтернативные реализации, самой заметной из которых стал rkt от CoreOS. Разработчики rkt заявили о своём намерении создать более безопасную, совместимую с Unix и открытую альтернативу Docker. Они критиковали монолитную архитектуру Docker и его зависимость от привилегированного демона. Rkt предлагал иную архитектуру, где не было центрального демона, и каждый контейнер запускался как отдельный процесс.

В 2015 году произошло важное событие — формирование Open Container Initiative (OCI) под эгидой Linux Foundation. Это был ответ на растущие опасения по поводу "войны контейнерных форматов". Docker, CoreOS и другие крупные игроки технологической индустрии согласились работать над совместимым стандартом. Так появились спецификации OCI: runtime-spec и image-spec, которые описывали, как должен выглядеть контейнер и контейнерный образ. Параллельно с этим шло развитие инструментов оркестрации контейнеров. Запустить один контейнер просто, но как управлять сотнями и тысячами контейнеров, распределёнными по десяткам серверов? Как обеспечить их надёжное взаимодействие, масштабирование, самовосстановление? На эти вопросы отвечали инструменты вроде Kubernetes, Docker Swarm и Apache Mesos.

Особенно интересной оказалась история Kubernetes. Этот проект, начатый в Google как открытая реализация их внутренней системы Borg, быстро стал стандартом де-факто для оркестрации контейнеров. И хотя изначально Kubernetes был заточен под работу с Docker, его архитектура предусматривала возможность использования разных контейнерных рантаймов через интерфейс Container Runtime Interface (CRI). Эта особенность Kubernetes сыграла важную роль в дальнейшей эволюции контейнерных рантаймов. Теперь у разработчиков была мотивация создавать более легковесные, специализированные рантаймы, которые могли встраиваться в экосистему Kubernetes. Началась эпоха декомпозиции и специализации в мире контейнеризации.

К 2016 году стало очевидно, что монолитная архитектура Docker — с централизованным демоном, отвечающим за все аспекты работы контейнеров — не идеально подходит для крупных распределённых систем и нужд оркестрации. Начался процесс "разборки" Docker на отдельные компоненты, каждый из которых решал строго определённую задачу. Так на свет появился containerd — отдельный рантайм, извлечённый из недр Docker.

Docker, (Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?)
До появления ошибки работал с Docker, запускал контейнеры, останавливал и удалял их. Но внезапно в...

Запуск linux контейнеров Docker в windows без Docker Desktop
Всем доброго времени суток! Пытаюсь разворачивать локальный веб-сервер на ПК С ОС windows с...

Создание контейнеров docker
Нужно создать три контейнера docker: 1. Nginx 2. php-fpm 3. Mysql И развернуть коробку...

Где хранятся данные docker контейнеров?
Привет! Пользуюсь Docker Desktop for Windows, Docker Engine v19.03.8. До вчера я думал, что...


Переходный период: от монолитного Docker к модульной архитектуре



Docker изначально задумывался как цельный инструмент, который должен был решать все задачи контейнеризации из коробки. Это было разумное решение на этапе становления технологии — пользователям не приходилось думать о взаимодействии множества компонентов, всё работало "как по волшебству". Однако к 2016 году монолитность Docker начала преврашаться из преимущества в существенный недостаток. Проблемы проявились в нескольких аспектах. Во-первых, тесная связь компонентов затрудняла независимую эволюцию отдельных частей системы. Во-вторых, Docker-демон имел привилегированный доступ к системе, что создавало потенциальные риски безопасности. В-третьих, для крупномасштабных развертываний, особенно в контексте Kubernetes, требовался более легкий и специализированный компонент для управления контейнерами.

Реакцией на эти вызовы стал планомерный процесс разделения монолита на специализированые компоненты. Docker Inc. начала вычленять ключевые функциональные части своего продукта в самостоятельные проекты. Первым таким "трансплантатом" стал containerd — низкоуровневый рантайм, ответственный за управление жизненным циклом контейнеров. За ним последовали и другие компоненты: runc для непосредственного запуска контейнеров на уровне ядра, libnetwork для управления сетевым взаимодействием, buildkit для сборки образов. Архитектура Docker превратилась из монолита в многослойную систему, где каждый уровень решал строго определённую задачу.

Результаты этой декомпозиции оказались весьма положительными. Независимые компоненты стало проще поддерживать, тестировать и развивать. Сторонние разработчики получили возможность использовать отдельные части Docker в своих проектах. А сообщество оркестрации контейнеров обрело гибкость в выборе компонентов для своих систем. Этот переход от монолитной к модульной архитектуре стал важным уроком для всей индустрии, показав преимущества принципа "разделяй и властвуй" в сложных программных системах. Для конечных пользователей обновленная архитектура принесла более стабильную платформу с лучшей производительностью и повышеной безопасностью.

Docker: первопроходец контейнеризации



Docker не просто создал технологию — он создал целое движение. Появившись в 2013 году, он совершил настоящую революцию в мире разработки и эксплуатации программного обеспечения. Если раньше разработчики тратили дни на настройку окружения, то теперь достаточно было написать компактный Dockerfile и всё — среда разработки, тестирования и продакшена становилась идентичной.

Архитектурно Docker представляет собой многослойную систему. На самом нижнем уровне лежит runc — легковесный исполнитель контейнеров, отвечающий за взаимодействие с ядром Linux через namespaces и cgroups. Поверх него работает containerd — демон, управляющий жизненным циклом контейнеров. А уже над ним располагается собственно Docker Engine — комплекс из API, CLI и демона dockerd, предоставляющий высокоуровневые абстракции и удобный интерфейс для работы с контейнерами.

Одна из ключевых концепций Docker — слоистая файловая система. В отличие от виртуальных машин, где каждый экземпляр содержит полную копию операционной системы, Docker-образы используют систему наложений (overlay filesystem). Это позволяет образам наследовать и переиспользовать слои друг друга, что существенно экономит дисковое пространство и ускоряет загрузку.

Bash
1
2
3
4
5
6
7
FROM ubuntu:20.04
WORKDIR /app
COPY . /app
RUN apt-get update && apt-get install -y python3 python3-pip
RUN pip3 install -r requirements.txt
EXPOSE 8000
CMD ["python3", "app.py"]
Этот простой Dockerfile показывает ещё одну сильную сторону Docker — декларативный подход к созданию окружения. Разработчику не нужно вникать в тонкости системного администрирования или написать скрипт настройки окружения — достаточно описать жклаемое состояние системы.

Экосистема инструментов, выросшая вокруг Docker, сделала его по-настоящему полноценной платформой для разработки. Docker Compose позволяет координировать запуск множества взаимозависимых контейнеров. Docker Hub стал первым крупным публичным репозиторием контейнерных образов, где можно найти практически любое программное обеспечение — от простейшего nginx до сложных распределённых систем. А Docker Registry дал возможность организациям создавать приватные репозитории для хранения внутренних образов. По мере роста популярности микросервисной архитектуры появилась потребность в оркестрации множества контейнеров. Docker ответил на этот вызов созданием Docker Swarm — собственного инструмента для управления кластерами контейнеров. Docker Swarm позволяет объединять несколько физических или виртуальных машин в единый пул ресурсов, на котором можно запускать и масштабировать контейнерезированные приложения.

Несмотря на все преимущества, Docker не лишен и ограничений. Его архитектура с привилегированным демоном вызывает вопросы с точки зрения безопасности. Производительность в некоторых сценариях уступает другим рантаймам. А высокий уровень абстракции, который так удобен для разработчиков, иногда скрывает важные детали функционирования системы, что усложняет отладку. Важной особенностью Docker стал подход к хранению данных. Будучи эфемерными по своей природе, контейнеры теряют все данные при перезапуске. Эта особенность гарантирует идентичность среды исполнения при каждом запуске, но создаёт проблемы с хранением состояния приложения. Для решения этой задачи Docker предлагает несколько механизмов: volumes, bind mounts и tmpfs mounts.

Volumes — наиболее предпочтительный способ сохранения данных. Они полностью управляются Docker, изолированы от основной файловой системы и могут использоваться несколькими контейнерами одновременно. Bind mounts, напротив, привязывают директорию на хост-машине к директории внутри контейнера, что удобно для разработки, но менее безопасно. Tmpfs mounts хранят данные только в памяти, что идеально для чувствительной информации, которая не должна сохраняться на диске.

Сетевая подсистема Docker тоже заслуживает внимания. Из коробки доступны несколько типов сетей: bridge (для взаимодействия контейнеров на одном хосте), host (для предоставления контейнеру прямого доступа к сети хоста), overlay (для взаимодействия контейнеров на разных хостах) и macvlan (для прямого подключения контейнеров к физической сети).

Bash
1
2
3
4
5
# Создание пользовательской сети
docker network create --driver overlay --attachable my_network
 
# Подключение контейнера к сети
docker run --network=my_network -d my_app
С ростом популярности Docker появилась потребность в более тонком управлении ресурсами. Docker позволяет ограничивать использование CPU, памяти, дискового ввода-вывода и других ресурсов на уровне отдельных контейнеров, что критично важно в высоконагруженных средах.

Bash
1
2
# Ограничение использования памяти и CPU
docker run -d --memory="2g" --cpus="1.5" nginx
Несмотря на первенство Docker в популяризации контейнеров, со временем его доминирование на рынке стало уменьшаться. Появление альтернативных рантаймов и рост популярности Kubernetes, который постепенно снижал зависимость от Docker, привели к тому, что Docker Inc. пришлось переосмыслить свою бизнес-модель и сфокусироваться на создании инструментов для разработчиков, а не на инфраструктурных решениях.

Docker Engine API и его значение для экосистемы инструментов



Одним из самых недооцененных аспектов Docker является его API — гибкий, выразительный интерфейс, открывший дорогу целой экосистеме сторонних инструментов. Docker Engine API — это RESTful API, который позволяет программно взаимодействовать со всеми компонентами Docker: контейнерами, образами, сетями, волюмами и т.д. Фактически, даже стандартный Docker CLI является всего лишь клиентом этого API. Благодаря наличию документированного API произошел настоящий взрыв разнообразия инструментов вокруг Docker. Появились графические интерфейсы (Portainer, Rancher), инструменты непрерывной интеграции (Jenkins с плагинами для Docker), платформы мониторинга (Prometheus с экспортёром метрик Docker) и даже комплексные решения для управления кластерами (тот же Kubernetes долгое время использовал Docker API через специальный шим).

Python
1
2
3
4
5
6
7
8
9
10
11
12
13
14
import docker
 
# Подключение к Docker Engine API
client = docker.from_env()
 
# Получение списка запущеных контейнеров
containers = client.containers.list()
 
# Создание и запуск нового контейнера
container = client.containers.run(
    "nginx:latest", 
    detach=True,
    ports={'80/tcp': 8080}
)
Стандартизация API оказала огромное влияние на всю экосистему контейнерных технологий. Разработчики получили возможность создавать инструменты, которые работали с Docker без необходимости глубоко погружаться в детали его реализации. Это существенно снизило барьер входа для новых участников рынка и ускорило инновации в области контейнерных технологий.

Интересная особенность Docker API — его версионирование. С самого начала API проектировался с учетом обратной совместимости, что позволяло сохранять работоспособность существующих интеграций при обновлении Docker Engine. Эта особенность сыграла ключевую роль в создании стабильной экосистемы вокруг Docker.

Управление ресурсами и ограничения безопасности в Docker



Docker предоставляет мощные средства для управления системными ресурсами, что критически важно в продакшн-средах. Через механизм cgroups контейнеры могут получать чётко лимитированное количество CPU, памяти и других ресурсов. Эта возможность не просто прихоть перфекциониста — она защищает от классической проблемы "шумного соседа", когда один разбушевавшийся контейнер может положить всю систему.

Bash
1
2
3
4
5
# Жёсткое ограничение в 512MB памяти с запретом использования swap
docker run --memory=512m --memory-swap=512m redis
 
# Выделение 30% процессорного времени и максимум 80% одного ядра
docker run --cpu-shares=307 --cpu-period=100000 --cpu-quota=80000 nginx
Однако настройка ресурсов — только вершина айсберга. Docker изначально поднимает серьёзные вопросы безопасности: запуск приложений в контейнерах не обеспечивает такого же уровня изоляции, как виртуальные машины. Контейнеры используют общее ядро с хост-системой, и компрометация этого ядра может привести к компрометации всех контейнеров. Особую опасность представляет запуск Docker-демона с правами root. В случае взлома демона атакующий может получить полный доступ к хост-системе. Для снижения рисков Docker предлагает несколько механизмов защиты: запуск контейнеров в режиме без привилегий, использование пространств имён пользователей (user namespaces), применение аппарата возможностей Linux (capabilities) для тонкой настройки привилегий.

Bash
1
2
# Запуск с ограниченными возможностями и правами непривилегированного пользователя
docker run --cap-drop=ALL --cap-add=NET_BIND_SERVICE --user=1000:1000 my_app
Не стоит забывать и о seccomp-профилях, которые позволяют ограничить набор системных вызовов, доступных контейнеру, что существено снижает поверхность атаки. По умолчанию Docker использует довольно либеральный профиль, но его можно (и нужно) ужесточать для критических приложений.

containerd: отделившийся наследник



Когда индустрия контейнеров начала взрослеть, стало очевидно, что монолитная архитектура Docker не идеальна для всех сценариев использования. Особенно это касалось энтерпрайз-систем, где требовалась максимальная гибкость и эффективность. В этой атмосфере на сцену вышел containerd — рантайм, который изначально был частью Docker, но обрел самостоятельность и со временем превратился в отдельный проект под эгидой Cloud Native Computing Foundation (CNCF).

Самое интересное в containerd — его минимализм. В отличие от Docker с его полным набором инструментов "от и до", containerd фокусируется исключительно на управлении контейнерами: загрузке образов, настройке хранилищ, запуске контейнеров и управлении их жизненным циклом. Никаких графических интерфейсов, никаких встроенных оркестраторов, никаких инструментов для сборки образов — только чистая механика контейнеров.

Bash
1
2
3
# Базовая работа с containerd через CLI-клиент ctr
ctr images pull docker.io/library/alpine:latest
ctr run --rm docker.io/library/alpine:latest test echo "Hello from containerd!"
Эта аскетичность — не баг, а фича. Разработчики containerd сознательно отказались от высокоуровневых функций в пользу того, чтобы создать стабильный, производительный и узконаправленный компонент, который будет хорошо интегрироваться с другими инструментами. Это полностью соответствует философии Unix: "Делай что-то одно, но делай это хорошо". Большой плюс такого подхода — сниженая поверхность атаки. Чем меньше код, тем меньше в нём потенциальных уязвимостей. А для безопасности контейнеров это критично важно. Технически containerd тоже работает как демон, но его привилегии строго ограничены, и область его ответственности точно определена. Особенно важной оказалась интеграция containerd с Kubernetes. Kubernetes, изначално построенный на Docker, начал отходить от прямой зависимости от него к более абстрактной модели через Container Runtime Interface (CRI). И containerd с его modular-first подходом идеально вписался в эту стратегию. Для взаимодействия с Kubernetes был разработан плагин cri-containerd, который позднее был интегрирован непосредственно в сам containerd.

Архитектурно containerd представляет собой многоуровневую систему. На верхнем уровне располагается gRPC API, через который клиенты взаимодействуют с демоном. Ниже находятся разлчные сервисы: управление образами, управление контейнерами, управление метаданными и т.д. А на самом нижнем уровне располагается OCI-совместимый рантайм (обычно runc), который непосредственно запускает контейнеры. Интересное архитектурное решение containerd — его модульность и расширяемость. Система плагинов позволяет легко добавлять новые функциональные возможности без изменения ядра containerd. Это открыло дорогу для целой экосистемы расширений: от альтернативных реализацией управления хранилищем до экзотических сетевых решений.

Еще одним важным аспектом containerd стала его производительность. Избавившись от многочисленных высокоуровневых функций Docker, containerd смог значительно снизить потребление ресурсов и повысить скорость запуска контейнеров. Это особенно заметно в высоконагруженных средах, где счёт контейнеров идет на тысячи, а эффективность использования ресурсов напрямую влияет на экономику инфраструктуры. Переход на containerd — это как пересесть с навороченного внедорожника на спортивный болид. Меньше комфорта, но гораздо больше отдачи и чистого удовольствия для тех, кто действительно понимает, что делает. И многие крупные игроки уже совершили этот переход: Amazon EKS, Google Kubernetes Engine, Microsoft AKS и другие облачные платформы используют containerd в качестве основного контейнерного рантайма.

Для тех, кто привык к высокоуровневым инструментам Docker, переход на containerd может показаться шагом назад. Команды более низкоуровневые, нет привычной экосистемы инструментов, всё очень аскетично. Но это было сознательным выбором разработчиков — предоставить базовый механизм, поверх которого другие инструменты могут строить свои абстракции.

Bash
1
2
3
4
# Создание и запуск контейнера с namepace и ограничениями
ctr run --rm --memory-limit 100M --cpu-shares 512 \
  --mount type=bind,src=/host/path,dst=/container/path,options=rbind:ro \
  docker.io/library/redis:alpine redis-test
Рост популярности containerd показывает, что индустрия движется в сторону более гранулярных, специализированных инструментов вместо монолитных решений. Это соответствует общему тренду в облачных технологиях — от больших неделимых монолитов к микросервисам и фукциям-как-сервис (FaaS), где каждый компонент выполняет строго определённую задачу и делает её максимально эффективно.

Жизненный цикл контейнера в containerd



В мире containerd контейнеры проходят четко определенный жизненный цикл, напоминающий водный поток: от истока (создания) до устья (уничтожения). В отличие от более высокоуровневого Docker, здесь каждый шаг прозрачен и доступен для непосредственного управления. Жизнь контейнера начинается с операции создания, когда из образа формируется нетронутый снимок среды исполнения. На этом этапе containerd готовит все необходимые файловые системы, настраивает namespace'ы и cgroups, но пока не запускает процессы.

Bash
1
2
# Создание контейнера без его запуска
ctr container create docker.io/library/nginx:latest web-server
Следующий этап — собственно запуск контейнера. Здесь containerd использует runc для преобразования подготовленного окружения в живой процесс. Создаётся init-процесс контейнера, который становится родителем для всех остальных процессов внутри.

Bash
1
2
# Запуск созданного контейнера
ctr task start web-server
В отличие от Docker, containerd разделяет понятия "контейнер" и "задача" (task). Контейнер — это статический набор ресурсов и конфигураций, а задача — запущенный процесс, использующий эти ресурсы. Такое разделение делает архитектуру более чистой и гибкой. После запуска контейнер можно приостанавливать, возобновлять и останавливать. Остановка может быть как постепенной (с отправкой SIGTERM и последующим SIGKILL), так и мгновенной. А завершающий этап жизненного цикла — удаление, когда освобождаются все выделенные контейнеру ресурсы.

Плагинная система containerd и возможности расширения



Важнейшее архитектурное решение containerd — его плагинная система, которая превращает рантайм из монолитного приложения в гибкий конструктор. Эта модульность — не просто дань моде на микросервисы, а практичный ответ на разнообразие требований современных инфраструктур. Разработчики containerd изначално предусмотрели, что невозможно создать универсальное решение для всех сценариев использования, поэтому сделали ставку на расширяемость.

Плагинная система containerd построена на принципе слабого связывания компонентов. Каждый плагин работает как независимый модуль со своим жизненным циклом и API. В архитектуре containerd выделяется несколько типов плагинов: сервисные (предоставляют gRPC-интерфейсы), метаданные (управляют хранением информации), хранилища (отвечают за слои образов), рантаймы (непосредственно запускают контейнеры).

Go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// Пример регистрации кастомного плагина в Go
func init() {
    plugin.Register(&plugin.Registration{
        Type: plugin.ServicePlugin,
        ID:   "my-custom-service",
        Requires: []plugin.Type{
            plugin.MetadataPlugin,
        },
        InitFn: func(ic *plugin.InitContext) (interface{}, error) {
            // Инициализация плагина
            return &myServicePlugin{}, nil
        },
    })
}
Эта архитектура позволяет разработчикам заменять стандартные компоненты containerd на собственные реализации или добавлять совершенно новую функциональность. Хотите использовать ZFS вместо overlayfs для хранения образов? Есть плагин для этого. Нужна интеграция с экзотической системой аутентификации? Можно написать плагин. Требуется поддержка особых форматов образов? И для этого тоже место найдётся. В экосистеме containerd уже существует множество плагинов для различных задач: от поддержки различных файловых систем до интеграции с системами мониторинга. Особенно выделяется плагин CRI (Container Runtime Interface), который обеспечивает совместимость containerd с Kubernetes и превращает его в полноценный рантайм для оркестрации контейнеров.

Низкоуровневое взаимодействие containerd с ядром Linux



Вся магия containerd раскрывается на уровне его взаимодействия с ядром Linux. В отличие от высокоуровневых инструментов, скрывающих техническе детали, containerd предоставляет тонкий, почти прозрачный слой над ядерными механизмами контейнеризации. Этот минималистичный подход позволяет ему быть одновременно эффективным и гибким. Ключевое взаимодействие с ядром происходит через системные вызовы, которые настраивают пространства имён (namespaces) и контрольные группы (cgroups). Пространства имён обеспечивают изоляцию процессов, сетевых стеков, точек монтирования и других ресурсов, а cgroups ограничивают потребление системных ресурсов. Интересная деталь: containerd не взаимодейтвует с ядром напрямую для запуска контейнеров, а делегирует это низкоуровневому исполнителю (обычно runc). Это разделение обязанностей — яркий пример философии Unix: каждый инструмент должен делать одну вещь, но делать её хорошо. Runc специализируется исключительно на создании и запуске контейнеров с использованием низкоуровневых функций ядра, а containerd занимается всем остальным.

При работе с сетью containerd не включает собственную сетевую модель, а полагается на внешние плагины через интерфейс Container Network Interface (CNI). Это позволяет гибко выбирать сетевые решения — от простого bridge-режима до сложных оверлейных сетей в распределённых кластерах.

Секрет эффективности containerd частично кроется в его асинхронной природе. Благодаря использованию событийно-ориентированной модели и грамотной работе с горутинами (в Go), он может обрабатывать множество запросов параллельно, минимизируя блокировки и ожидания.

rkt: альтернативный подход



В то время как Docker и containerd шли по пути централизованной демон-модели, команда CoreOS предложила совершенно иную философию контейнеризации, воплощенную в проекте rkt (произносится "рокет"). Появившись в 2014 году как реакция на архитектурные и безопасностные ограничения Docker, rkt изначально позиционировался как более безопасная, проще интегрируемая и ближе к Unix-принципам альтернатива. Главное архитектурное отличие rkt — отсутствие централизованного демона. Каждый запуск контейнера происходит как отдельный процесс, напрямую инициируемый пользователем или системой инициализации (systemd). Эта архитектурная особенность сразу решает множество проблем с безопасностью, связанных с привилегированными демонами, и упрощает интеграцию с системными компонентами Linux.

Bash
1
2
# Запуск контейнера в rkt
rkt run docker://nginx --port=http:80 --insecure-options=image
Еще одна интересная особенность rkt — нативная поддержка концепции "подов" (pods), которая позже стала краеугольным камнем архитектуры Kubernetes. Под в rkt — это группа контейнеров, которые разделяют одно сетевое пространство имён и могут напрямую взаимодействовать друг с другом через localhost.

Философия rkt строится вокруг трёх ключевых принципов: композируемость (возможность встраивания в различные системы), безопасность (строгая верификация образов, минимальные привилегии) и открытость (поддержка стандартов и отказ от проприетарных форматов).

Несмотря на технические преимущества, популярность rkt никогда не достигала уровня Docker. Сказалось и позднее появление на рынке, и меньшая дружелюбность к начинающим пользователям, и ограниченные ресурсы на развитие проекта по сравнению с конкурентами. Интересно, что хотя rkt не достиг коммерческого успеха Docker, его технические идеи оказали заметное влияние на развитие контейнерных технологий в целом. Концепция подов из rkt перекочевала в Kubernetes и стала там центральной абстракцией. А безопасностные практики, такие как верификация образов и разделение привилегий, постепенно проникли и в другие рантаймы.

В техническом плане rkt имеет несколько уникальных характеристик. Трёхфазный жизненный цикл контейнера (выборка, верификация, выполнение) обеспечивает высокую степень безопасности. Система "сцен" (stages) позволяет тонко настраивать переходы между фазами запуска контейнера. А модульная архитектура, где ключевые компоненты работают независимо друг от друга, обеспечивает гибкость и возможность замены компонентов.

Bash
1
2
# Запуск контейнера с ограничениями по изоляции
rkt run --insecure-options=image --net=host --dns=8.8.8.8 docker://alpine --exec=/bin/sh
В 2020 году проект rkt был официально прекращен и перемещен в архив CNCF. Причиной стало смещение интереса сообщества в сторону OCI-совместимых рантаймов и консолидация вокруг containerd и CRI-O. Тем не менее, наследие rkt живёт в архитектурных паттернах современных контейнерных систем и напоминает, что иногда технически превосходные решения проигрывают более простым и доступным альтернативам из-за факторов экосистемы и рыночной динамики.

Модель безопасности pod в rkt и её преимущества



Изначальное понимание безопасности в rkt строилось вокруг концепции pod — очень символично, что даже название проекта "rocket" (ракета) подразумевало запуск не отдельных контейнеров, а целых космических "капсул". В отличие от Docker, где каждый контейнер — самостоятельная единица, в rkt pod — фундаментальный строительный блок, внутри которого могут существовать один или несколько изолированных приложений. Безопасностное преимущество этой модели наглядно демонстрируется при запуске нескольких взаимосвязанных сервисов. Вместо организации сложных сетевых правил между изолированными контейнерами, rkt позволяет разместить компоненты в едином поде с общим сетевым пространством имён. Приложения внутри пода общаются через localhost без лишних прыжков через сетевой стек, что не только повышает производительность, но и сокращает поверхность атаки.

Bash
1
2
3
# Создание пода с несколькими контейнерами, имеющими общее сетевое пространство
rkt run --pod=my-pod docker://backend:latest --name=api \
  docker://redis:latest --name=cache
Важное преимущество модели pod — более чёткий контроль над жизненным циклом группы связанных контейнеров. При аварийном завершении одного из контейнеров rkt может автоматически перезапускать его внутри того же пода, сохраняя общие ресурсы и связи. Этот механизм устойчивости повышает не только надёжность, но и безопасность системы, предотвращая возможную рассинхронизацию компонентов приложения.

Еще одна уникальная характеристика безопасности rkt — детальная система разграничения привилегий внутри пода. Администратор может точно указать, какие возможности ядра Linux (capabilities) доступны каждому приложению, при этом некоторые контейнеры внутри пода могут работать в привилегированном режиме, а другие — с минимальными правами.

Система верификации образов в rkt и ее отличие от конкурентов



Один из самых выдающихся аспектов rkt — его принципиальный подход к проверке целостности и подлинности запускаемых контейнеров. В отличие от Docker, где верификация образов долгое время была опциональной функцией, rkt изначально проектировался с упором на криптографическую верификацию образов как неотъемлемую часть процесса запуска.

Основу системы верификации составляет технология "доверенных ключей" (trust keys). Перед запуском любого контейнера rkt проверяет цифровую подпись образа, гарантируя, что он не был модифицирован после создания и действительно происходит от заявленного источника. Эта процедура интегрирована непосредственно в последовательность запуска контейнера и не требует дополнительных действий от пользователя.

Bash
1
2
3
4
5
# Добавление доверенного GPG ключа
rkt trust --prefix=coreos.com/etcd
 
# Запуск контейнера с обязательной верификацией
rkt run coreos.com/etcd:v3.1.0
Интересная деталь: rkt поддерживает концепцию "префиксов доверия", позволяя администраторам гибко настраивать политику безопасности. Можно доверять всем образам от определенного издателя или только конкретным версиям приложений. Фактически, это воплощение принципа "наименьших привилегий" на уровне жизненного цикла контейнера.

В отличе от Docker Content Trust, который появился значительно позже основного продукта, система верификации rkt не выглядит как дополнение, а органично вплетена в общую архитектуру и рабочий процесс. А в сравнении с containerd, который полагается на внешние механизмы проверки подлиности, подход rkt обеспечивает более целостное и бесшовное решение проблемы безопасности контейнерных образов.

Интеграция rkt с системными компонентами Linux



Одно из ключевых преимуществ rkt — его естественная интеграция с системными компонентами Linux, особенно с systemd. В отличие от Docker, который требует отдельного демона и своего собственного мира управления процессами, rkt органично вписывается в существующую системную архитектуру Linux. Наиболее заметное проявление этой интеграции — нативная поддержка юнитов systemd. Каждый контейнер rkt может быть напрямую запущен и управляем через systemd, что делает мониторинг, логирование и управление контейнерами естественным продолжением системного администрирования.

Bash
1
2
3
4
5
6
7
8
9
10
11
12
# Примером systemd-юнита для rkt может служить:
[Unit]
Description=MyApp Container
After=network.target
 
[Service]
ExecStart=/usr/bin/rkt run --insecure-options=image docker://myapp:latest
KillMode=mixed
Restart=always
 
[Install]
WantedBy=multi-user.target
Архитектурная особенность rkt как без-демонного рантайма идеально соответствует философии systemd: каждый запущенный под становится полноценным наследником init-системы, а не скрытым процессом внутри другого демона. Это позволяет напрямую применять существующие инструменты мониторинга и управления процессами — от простейшего ps до сложных систем отслеживания ресурсов.

rkt также отличается от конкурентов своей прямой интеграцией с cgroups. Вместо создания собственной абстракцией над cgroups, rkt может напрямую использовать иерархию групп, созданную systemd, что усиливает прозрачность и контроль над ресурсами системы.

Производительность и эффективность



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

Docker, как самый "толстый" из трёх рантаймов, предсказуемо проигрывает в чистой производительности. Его многослойная архитектура и обилие высокоуровневых функций делают его более ресурсоёмким. Особенно это заметно при массовом запуске контейнеров — daemon-модель создаёт узкое горлышко при обработке множества параллельных запросов.

Bash
1
2
3
4
# Бенчмарк запуска 100 контейнеров в Docker
time for i in {1..100}; do 
  docker run --rm alpine echo "hello world" >/dev/null
done
Containerd, будучи более "поджарым", демонстрирует лучшую производительность, особенно в сценариях с высокой плотностью контейнеров. Отсутствие лишних абстракций и узкая специализация позволяют ему эффективнее использовать ресурсы хост-системы. Исследования показывают, что при одинаковой нагрузке containerd потребляет на 15-20% меньше оперативной памяти, чем полноценный Docker.

Rkt, с его без-демонной архитектурой, показывает интересные результаты. С одной стороны, отсутствие постоянно работающего демона снижает простой расход ресурсов. С другой стороны, каждый запуск контейнера требует инициализации нового процесса rkt, что может замедлять развёртывание в сценариях, требующих быстрого масштабирования.

Для иллюстрации разницы, вот интересные цифры: в типичном сценарии запуска веб-сервера время холодного старта (от команды до готовности принимать HTTP-запросы) составляет около 1.2 секунды для Docker, 0.9 секунды для containerd и 1.1 секунды для rkt. При горячем запуске (когда образы уже загружены) containerd опережает конкурентов почти на 30%.

Что касается использования CPU, Docker снова оказывается наиболее прожорливым из трёх, особенно в части общесистемных затрат на управление контейнерами. Демон dockerd может потреблять заметное количество процессорного времени даже в состоянии простоя, тогда как containerd остаётся практически незаметным до момента активной работы с контейнерами.

Учитывая эти факторы, неудивительно, что крупные платформы оркестрации, такие как Kubernetes, постепенно перешли с Docker на более легковесные рантаймы. В среде, где счёт контейнеров идёт на тысячи, даже небольшой выигрыш в эффективности на уровне отдельного контейнера транслируется в серьёзную экономию ресурсов в масштабе всего кластера.

Интересный аспект, часто упускаемый при сравнении рантаймов — эффективность работы сетевой подсистемы. Docker использует собственный слой абстракции с bridge-сетями и внутренним DNS-сервером, что удобно, но создаёт дополнительные накладные расходы. При интенсивном сетевом взаимодействии между контейнерами производительность может падать на 5-8% по сравнению с нативными сетевыми возможностями containerd с плагинами CNI.

Еще одна важная метрика — скорость остановки контейнеров. Сценарий, когда необходимо быстро освободить ресурсы, критичен для динамических сред с автомасштабированием. Здесь rkt часто демонстрирует лучшую производительность — его бездемонная модель позволяет избежать "подвисания" контейнеров при остановке, что иногда наблюдается в Docker при большой нагрузке. Эфективность использования дискового пространства тоже различается. Docker и containerd используют слоистую файловую систему, что экономит место при наличии множества похожих образов. Rkt же традиционно был менее эффективен в этом аспекте, хотя в поздних версиях ситуация улучшилась.

Виртуальные машины и контейнеры часто сравнивают как конкурирующие технологии, но на практике разница в производительности между ними зависит от конкретного сценария использования. Интересно, что некоторые тесты показывают: в определённых случаях правильно настроеный rkt может приближаться по производительности к "голому железу", обгоняя другие рантаймы на IO-интенсивных операциях.

Мой опыт эксплуатации всех трёх рантаймов на высконагруженных системах подсказывает: оптимальный выбор зависит от конкретных требований. Для разработки и однопользовательских систем Docker по-прежнему выигрывает благодаря удобству. Для больших кластеров containerd показывает лутчший баланс производительности и функциональности. А rkt остаётся отличным вариантом для систем с повышенными требованиями к безопасности и изоляции.

Методология сравнительного анализа рантаймов в производственных средах



Вопрос "какой рантайм лучше?" звучит обманчиво простым, но в реальных условиях превращается в многофакторное уравнение, решение которого зависит от десятка переменных. Когда дело доходит до боевого тестирования контейнерных рантаймов, методология имеет решающее значение — неверный подход к сравнению может привести к неверным выводам и дорогостоящим ошибкам. Правильный сравнительный анализ начинается с определения чётких метрик — не просто "производительность" в абстрактном понимании, а конкретные измеримые показатели: время старта контейнера, расход памяти в состоянии покоя, пиковое потребление CPU при параллельном запуске сотни контейнеров, латентность сетевых операций между контейнерами и т.д.

Bash
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# Пример скрипта для замера времени старта контейнера
#!/bin/bash
for runtime in docker containerd rkt; do
  echo "Testing $runtime..."
  start=$(date +%s%N)
  case $runtime in
    docker)
      docker run --rm alpine echo "test" >/dev/null
      ;;
    containerd)
      ctr run --rm docker.io/library/alpine:latest test echo "test" >/dev/null
      ;;
    rkt)
      rkt run --insecure-options=image docker://alpine --exec echo -- "test" >/dev/null
      ;;
  esac
  end=$(date +%s%N)
  echo "$runtime startup: $((($end - $start)/1000000)) ms"
done
Ключевое правило адекватного сравнения — максимальная репрезентативность тестовой среды. Синтетические бенчмарки на голых серверах дают показатели, которые часто не имеют ничего общего с тем, как рантаймы ведут себя под реальной нагрузкой, с реальным сетевым трафиком и конкурентным доступом к ресурсам. Эталонная методология включает тестирование в среде, максимально приближеной к продакшену — с тем же железом, теми же типами нагрузки и теми же паттернами использования.

Особенности работы с хранилищами и volumes в разных рантаймах



Хранение данных — ахиллесова пята контейнерных технологий. По своей природе контейнеры эфемерны, но данные должны жить дольше, чем контейнер. Это фундаментальное противоречие каждый рантайм решает по-своему.

Docker предлагает наиболее развитую и понятную систему работы с томами. Три основных механизма — volumes, bind mounts и tmpfs — охватывают практически все сценарии использования. Docker-volumes полностью управляются демоном Docker, изолированы от основной файловой системы и предлагают надёжную абстракцию. Весь арсенал драйверов (local, nfs, vsphere) позволяет адаптировать хранилища под конкретные задачи.

Bash
1
2
3
# Создание именованного тома в Docker и монтирование в контейнер
docker volume create my_data
docker run -v my_data:/app/data nginx
Containerd, верный своей минималистичной философии, не предлагает высокоуровневых абстракций для хранилищ. Вместо этого он обеспечивает базовый функционал монтирования директорий и опирается на внешние решения для более продвинутых сценариев. CSI-плагины (Container Storage Interface) расширяют эти возможности, позволяя интегрировать любые хранилища — от локальных дисков до распределённых файловых систем.

Bash
1
2
# Монтирование директории хоста в containerd
ctr run --mount type=bind,src=/host/path,dst=/container/path,options=rbind:ro docker.io/library/alpine:latest test
Rkt, с его без-демонной архитектурой, предлагает принципиально иной подход. Механизм volumes в rkt тесно интегрирован с концепцией подов. Тома могут быть "пустыми" (empty), "host" (с файловой системы хоста) или даже "tmpfs" (в памяти). Контроль доступа к томам настраивается на уровне конкретных приложений внутри пода, что обеспечивает тонкую гранулярность прав.

Каждый подход имеет свои компромиссы. Docker делает ставку на простоту использования, containerd — на гибкость и минимализм, а rkt — на безопасность и интеграцию с системой. Выбор зависит не только от технических характеристик, но и от того, какие приоритеты важнее в вашем конкретном случае.

Сравнительный анализ сетевой производительности контейнерных рантаймов



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

Docker использует многослойную архитектуру сетевого взаимодействия с собственным DNS-резолвером и различными драйверами (bridge, host, overlay). Эта универсальность оборачивается дополнительными накладными расходами — передача пакетов между контейнерами через docker0 мост может создавать задержки до 10-15% по сравнению с нативным сетевым стеком.

Bash
1
2
# Измерение задержки сети в Docker
docker run --rm alpine sh -c "time ping -c 10 172.17.0.2"
Containerd с плагинами CNI демонстрирует меньшие накладные расходы. При прямых измерениях пропускной способности между контейнерами с использованием iperf3 containerd показывает результаты на 7-12% лучше Docker при одинаковой конфигурации сети.

Особняком стоит rkt с его подходом pod-ориентированной архитектуры. Контейнеры внутри пода общаются через localhost вообще без участия сетевого стека, что даёт почти нулевую латентность межсервисного взаимодействия. Однако при коммуникации между подами rkt иногда проигрывает containerd из-за отсутствия некоторых оптимизаций в маршрутизации пакетов.

Для высоконагруженных микросервисных архитектур, где межсервисное взаимодействие создаёт существенную часть трафика, эти цифры могут оказаться решающими при выборе рантайма. В случаях, когда критична именно скорость обмена данными между тесно связанными сервисами, модель подов в rkt или комбинация containerd с оптимизированными CNI-плагинами дают ощутимое преимущество перед классическим Docker.

Сценарии применения



Docker остаётся непревзойдённым для среды разработки и небольших проектов. Его преимущества — низкий порог входа, развитая экосистема и унифицированный интерфейс — перевешивают недостатки в производительности. Для стартапов, внутренних сервисов компаний и обучения Docker по-прежнему первый выбор, позволяющий максимально быстро пройти путь от концепции до работающего продукта.

Bash
1
2
3
4
# Типичный процесс разработки на Docker
docker-compose up -d    # Запуск всей инфраструктуры
docker-compose logs -f  # Мониторинг логов в режиме реального времени
docker exec -it app sh  # Интерактивный доступ к контейнеру
Containerd идеален для масштабных продакшн-систем, особенно под управлением Kubernetes. Когда на кону стоит производительность, стабильность и эффективное использование ресурсов в многокластерных средах, его минималистичный подход и низкие накладные расходы становятся решающими факторами. Google Kubernetes Engine, Amazon EKS и другие крупные платформы не зря стандартизировались именно на containerd — это выбор "тяжелой артиллерии" для серьёзных промышленных нагрузок.

Rkt, несмотря на прекращение активной разработки, сохраняет привлекательность для сценариев с повышенными требованиями к безопасности и изоляции. Его бездемонная архитектура и подход "pod-first" делают его востребованным в финансовом секторе, государственных системах и других областях, где безопасность исполнения кода имеет первостепенное значение. Некоторые организации продолжают использовать rkt именно из-за его уникальной модели безопасности, несмотря на некоторую устарелость.

Выбор рантайма в зависимости от масштаба инфраструктуры



Масштаб инфраструктуры критически влияет на выбор рантайма, и это не просто теоретический вопрос. На практике разница проявляется уже при переходе от десятков контейнеров к сотням и тысячам. Наработанный опыт в этой области позволяет сформулировать несколько ключевых принципов.

Для малых инфраструктур (до 50 контейнеров) Docker остаётся золотым стандартом, и не только из-за простоты. В таких системах накладные расходы на управление не столь критичны, и ценность интегрированного интерфейса управления перевешивает потенциальные недостатки. Docker Compose в этом случае успешно решает задачи оркестрации без избыточной сложности Kubernetes.

Средние инфраструктуры (от 50 до 500 контейнеров) попадают в транзитную зону, где уже ощущаются ограничения Docker, но полноценный переход на специализированные решения еще не оправдан. Здесь оптимален гибридный подход: Docker для разработки и тестирования, containerd или CRI-O для продакшена под управлением лёгких версий Kubernetes вроде k3s или minikube.

Крупномасштабные системы (свыше 500 контейнеров) однозначно выигрывают от использования специализированных рантаймов. Containerd здесь демонстрирует наилучший баланс между производительностью и функциональностью. При тысячах контейнеров даже 5% экономии ресурсов на каждом узле превращается в существенную оптимизацию расходов на инфраструктуру.

Особняком стоят ультра-масштабные системы (десятки тысяч контейнеров), где критична каждая миллисекунда задержки и каждый байт памяти. Google, например, для таких сценариев разработал собственный рантайм gVisor, сочетающий производительность containerd с дополнительным уровнем изоляции контейнеров. А AWS Firecracker представляет собой ещё более специализированное решение для запуска функций в формате serverless.

Миграция между рантаймами: стратегии и лучшие практики



Переход с одного контейнерного рантайма на другой — процесс, требующий продуманной стратегии. Миграция с Docker на containerd, например, требует пошагового подхода, исключающего одномоментное переключение. Лучшая практика — создание параллельной инфраструктуры с новым рантаймом и постепенный перенос рабочих нагрузок с детальным мониторингом производительности и стабильности.

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

Bash
1
2
3
4
5
6
# Пример стратегии переезда с Docker на containerd
# 1. Экспорт образов из Docker в формат OCI
docker save my-image:latest | ctr images import -
 
# 2. Запуск тестового контейнера через containerd
ctr run --rm docker.io/library/my-image:latest test-container
Важно помнить, что миграция — не одноразовая акция, а процесс со своим жизненным циклом: от планирования и тестирования до постепенного внедрения и последующего мониторинга.

Как сделать несколько Docker контейнеров на разных прокси?
Всем привет! Задача следующая, нужно запустить 2 приложения на разных прокси (получать интернет с...

Docker - отложенный запуск, или дождаться запуска других контейнеров
Всем доброго! Подскажите, возможно ли средствами docker отложить запуск контейнера или привязать...

DNS внутри контейнеров Docker
Здравствуйте, возникла проблема с dns внутри docker контейнеров, изнутри контейнеров не работает...

Docker, IP Host -> Docker responce
есть некий сервис достучатся к которому возможно по IP (но только через VPN), задался вопросом, а...

Не могу создать образ Docker, подскажите как сделать. Вылазить ошибка. docker-file. Новичок в докере
Если можно обясните как строить докер файл. столько видео посмотрел ничего не понял Step 4/5 :...

Docker-compose push to Docker Hub
Всем привет! Я заготовил docker-compose.yml, но есть несколько зависимостей в папочках . ├──...

После команды netstat -ntpl отображаются только tcp6 версия и нет названия контейнеров
Доброго времени суток. Пробую запустить пару контейнеров из практически учебных докер-композ...

Docker форумы
Есть ли русскоязычные форумы по docker'у? Погуглил и нашел только статьи, но из них понятны только...

Java Developer (Java,Docker,Clojure) Россия, Москва Полный рабочий день От 150 000 руб
Привет, Мы - Cubic.ai, NLP-стартап с офисами в Кремниевой долине и Москве. Наш продукт Cubic -...

Docker не хочет работать на Ubuntu Server 14.04
Здравствуйте! При попытке запустить команду sudo docker run hello-world появляется ошибка...

Docker, NGINX и MYSQL
Доброго времени. Подскажите пожалуйста. Появилась потребность в использовании Docker для разделения...

Установка Docker в Jail
Здравствуйте! Я использую Freenas 9.10. Поднял на нем jail, в котором необходимо установить докер...

Метки containerd, devops, docker, rkt
Размещено в Без категории
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
Всего комментариев 0
Комментарии
 
Новые блоги и статьи
Unity 4D
GameUnited 13.06.2025
Четырехмерное пространство. . . Звучит как что-то из научной фантастики, правда? Однако для меня, как разработчика со стажем в игровой индустрии, четвертое измерение давно перестало быть абстракцией из. . .
SSE (Server-Sent Events) в ASP.NET Core и .NET 10
UnmanagedCoder 13.06.2025
Кажется, Microsoft снова подкинула нам интересную фичу в новой версии фреймворка. Работая с превью . NET 10, я наткнулся на нативную поддержку Server-Sent Events (SSE) в ASP. NET Core Minimal APIs. Эта. . .
С днём независимости России!
Hrethgir 13.06.2025
Решил побеседовать, с утра праздничного дня, с LM о завоеваниях. То что она написала о народе, представителем которого я являюсь сам сначала возмутило меня, но дальше только смешило. Это чисто. . .
Лето вокруг.
kumehtar 13.06.2025
Лето вокруг. Наполненное бурями и ураганами событий. На фоне магии Жизни, священной и вечной, неумелой рукой человека рисуется панорама душевного непокоя. Странные серые краски проникают и. . .
Популярные LM модели ориентированы на увеличение затрат ресурсов пользователями сгенерированного кода (грязь -заслуги чистоплюев).
Hrethgir 12.06.2025
Вообще обратил внимание, что они генерируют код (впрочем так-же ориентированы разработчики чипов даже), чтобы пользователь их использующий уходил в тот или иной убыток. Это достаточно опытные модели,. . .
Топ10 библиотек C для квантовых вычислений
bytestream 12.06.2025
Квантовые вычисления - это та область, где теория встречается с практикой на границе наших знаний о физике. Пока большая часть шума вокруг квантовых компьютеров крутится вокруг языков высокого уровня. . .
Dispose и Finalize в C#
stackOverflow 12.06.2025
Работая с C# больше десяти лет, я снова и снова наблюдаю одну и ту же историю: разработчики наивно полагаются на сборщик мусора, как на волшебную палочку, которая решит все проблемы с памятью. Да,. . .
Повышаем производительность игры на Unity 6 с GPU Resident Drawer
GameUnited 11.06.2025
Недавно копался в новых фичах Unity 6 и наткнулся на GPU Resident Drawer - штуку, которая заставила меня присвистнуть от удивления. По сути, это внутренний механизм рендеринга, который автоматически. . .
Множества в Python
py-thonny 11.06.2025
В Python существует множество структур данных, но иногда я сталкиваюсь с задачами, где ни списки, ни словари не дают оптимального решения. Часто это происходит, когда мне нужно быстро проверять. . .
Работа с ccache/sccache в рамках C++
Loafer 11.06.2025
Утилиты ccache и sccache занимаются тем, что кешируют промежуточные результаты компиляции, таким образом ускоряя последующие компиляции проекта. Это означает, что если проект будет компилироваться. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru