#docker
Вопрос:
Как docker может работать на хосте Debian, возможно, на openSUSE в контейнере? Он использует другое ядро с отдельными модулями. Кроме того, в более старых версиях Debian использовались более старые ядра, так как же запустить его в версии ядра 3.10 ? Старые ядра имеют только старые встроенные функции, как старый дистрибутив может управлять новыми функциями? Что в этом «подвоха»?
Ответ №1:
Docker никогда не использует другое ядро: ядро всегда является ядром вашего хоста.
Если ядро вашего хоста «достаточно совместимо» с программным обеспечением в контейнере, который вы хотите запустить, оно будет работать; в противном случае оно не будет работать.
«Контейнеры» — Это Просто Конфигурация Процесса
Главное, что нужно понять, — это то, что контейнер Docker не является виртуальной машиной: он не создает новый виртуальный компьютер для запуска программного обеспечения. Вместо этого Docker просто запускает процессы в существующей операционной системе, аналогично тому, как вы просто запускаете процесс из командной строки.
Разница между контейнерным процессом и обычным процессом заключается в ограничениях, накладываемых на контейнерный процесс, и изменениях в том, как он видит окружающую среду вокруг себя. (Они передаются любым дочерним процессам, запущенным контейнеризованным процессом.) Типичные ограничения и изменения включают:
- Вместо того, чтобы использовать корневую файловую систему хоста, смонтируйте другую файловую
/
систему (обычно поставляемую с изображением контейнера). Части файловой системы хоста могут быть смонтированы под корневой файловой системой нового процесса, например, с помощьюdocker run -v /u/myprogram-data:/var/data/myprogram
так, чтобы, когда контейнеризованный процесс считывает или записывает/var/data/myprogram/file
, это считывает/записывает/u/myprogram-data/file
в файловой системе хоста. - Создайте отдельное пространство процесса для контейнеризованного процесса, чтобы он мог видеть только себя и своих дочерних процессов (с
ps
помощью или аналогичных команд), но не мог видеть другие процессы, запущенные на хосте. - Создайте отдельное пространство имен пользователей, чтобы пользователи в контейнере отличались от пользователей на хосте: например, UID 1234 в контейнеризованном процессе не будет таким же, как UID 1234 для неконтейнеризованных
- Создайте отдельный набор сетевых интерфейсов со своими собственными IP-адресами, часто используя «виртуальный маршрутизатор» и преобразование адресов между ними и сетевыми интерфейсами хоста. (Например, хост, когда он получает пакет на порту 8080, перенаправляет его на порт 80 в виртуальном сетевом интерфейсе процессов контейнера.)
Все это выполняется средствами, встроенными в ядро; вы можете сделать все это самостоятельно без докера, если напишете программу для соответствующей настройки и зададите соответствующие параметры при запуске нового процесса.
Совместимость
Так что же означает «достаточно совместимый»? Это зависит от того, какие запросы программа делает к ядру (системные вызовы) и какие функции, как она ожидает, будет поддерживать ядро. Некоторые программы делают запросы, которые могут что-то нарушить, другие-нет. Например, на Ubuntu 18.04 (ядро 4.19) или аналогичном хосте:
docker run centos:7 bash
работает нормально.docker run centos:6 bash
сбой с кодом выхода 139, что означает, что он завершился сигналом о нарушении сегментации; это связано с тем, что ядро 4.19 не поддерживает то, чтоbash
пыталась сделать сборка.docker run centos:6 ls
работает нормально, потому что он не делает запрос, который ядро не может обработать, какbash
это было.
Если вы попробуете docker run centos:6 bash
более старое ядро, скажем, 4.9 или более раннее, вы обнаружите, что оно будет работать нормально. (По крайней мере, насколько я это проверял.)
Комментарии:
1. Отличное объяснение. Прояснил для меня многое о том, как работает докер.
2. Это отличный ответ! Ответил на многие мои вопросы о докере.
3. Недавно я услышал выражение, которое прекрасно подводит итог этому имо: «Докер-это просто набор ядер Linux». Ссылаясь на пространства имен, группы …
4. Отличные примеры, проясняющие большую часть путаницы.
5. @erikbozic, если быть более точным: это ядро Linux, которое «контейнеризирует» процессы, а Docker-это система, которая позволяет создавать, хранить и отзывать конфигурации процессов ядра Linux. (А также удобно хранит изображения файловой системы.)
Ответ №2:
Как docker может работать на хосте Debian, возможно, на openSUSE в контейнере
Поскольку ядро одно и то же и будет поддерживать механизм Docker для запуска всех этих образов контейнеров: ядро хоста должно быть 3.10 или более, но его список системных вызовов довольно стабилен.
См. раздел «Архитектура контейнеров: почему понимание пользовательского пространства по сравнению Пространство Ядра Имеет значение«:
- Приложения содержат бизнес-логику, но полагаются на системные вызовы.
- Как только приложение скомпилировано, набор системных вызовов, которые использует приложение (т. Е. полагается на них), встроен в двоичный файл (на языках более высокого уровня это интерпретатор или JVM).
- Контейнеры не абстрагируют необходимость в том, чтобы пространство пользователя и пространство ядра совместно использовали общий набор системных вызовов.
- В контейнеризированном мире это пользовательское пространство упаковывается и отправляется на разные хосты, начиная от ноутбуков и заканчивая производственными серверами.
- В ближайшие годы это создаст проблемы.
Время от времени добавляются новые системные вызовы, а старые системные вызовы устаревают; это следует учитывать при рассмотрении жизненного цикла вашей контейнерной инфраструктуры и приложений, которые будут в ней выполняться.
См. Также «Почему версия ядра не соответствует версии Ubuntu в контейнере Docker?«:
Внутри контейнера нет ядра. Даже если вы установите ядро, оно не будет загружено при запуске контейнера. Само назначение контейнера состоит в том, чтобы изолировать процессы без необходимости запускать новое ядро.
Комментарии:
1. Я думаю, что вышесказанное не дает полного ответа на этот вопрос. Хотя я полностью согласен с тем, что ссылки на ссылки дают хорошее объяснение того, почему контейнеры не создают собственное ядро, мы могли бы на самом деле захотеть создать контейнер, который, возможно, зависит от конкретной версии ядра. Я думаю, что docker даже при запуске на хосте Linux может иметь режим, в котором вы можете выбрать версию ядра.
2. Эта диаграмма неверна и вводит в заблуждение: часть «контейнер» вообще не находится в пространстве пользователя. Конфигурация контейнера изменяет то, как ядро реагирует на системные вызовы, например , если вы
open("/etc/passwd", O_RDONLY)
, какой из многих файлов, известных ядру, фактически открыт? С точки зрения пользовательского пространства процесс не отличается от «неконтейнеризованного» процесса.