Авторские статьи

LXD 2.0: Docker в LXD [7/12].


В седьмой статье рассмотрен вариант использования Docker (инструмент развёртывания приложений в контейнерах) внутри LXD.

Зачем запускать Docker внутри LXD?

Как кратко было написано в начале первого поста серии, LXD фокусируется на системных контейнерах. То есть внутри запускается не модифицированный дистрибутив Linux. LXD не заботится о рабочей нагрузке внутри контейнера. Он просто создаёт namespace контейнера и применяет политики безопасности, затем запускает /sbin/init и ждёт когда контейнер завершит свою работу.

Контейнеры приложений, такие как Docker или Rkt, используются для дистрибуции ПО, обычно запускают единичный процесс внутри, тем самым являясь более эфемерными в сравнении с LXD. Два типа контейнера не являются взаимоисключающими. Много усилий было сделано разработчиками, чтобы Docker отлично работал внутри LXD.

Это означает, что в Ubuntu 16.04 и с LXD 2.0 вы можете создать контейнеры для ваших пользователей, которые подсоединятся к ним, как к обычной Убунту системе, и с помощью Docker развернут сервисы и программы, которые им нужны.

Требования

Есть много кусочков, из которых слагается пазл:

  • Ядро Linux с поддержкой CGroup namespace (4.4 и новее).
  • LXD 2.0 используют LXC 2.0 и LXCFS 2.0.
  • Специальная версия Docker (или со всеми патчами от разработчиков LXD).
  • Образ Docker, понимающий ограничение его пользовательского namespace, или можно сделать контейнер LXD, в котором сидит Докер, привилегированным (security.privileged=true).

Запуск базовых нагрузок Docker

Хватит болтать, давайте сделаем что-нибудь в Docker. Прежде всего вам нужен контейнер LXD с Ubuntu 16.04 - lxc launch ubuntu-daily:16.04 docker -p default -p docker

"-p default -p docker" - инструктирует LXD применить профили default и docker. Профиль default содержит базовую конфигурацию сети, а профиль docker говорит LXD загрузить нужные модули ядра и примонтировать нужное в контейнере. Профиль docker так же включает вложенность контейнеров (container nesting).

Всё должно быть актуальным:
lxc exec docker -- apt update
lxc exec docker -- apt dist-upgrade -y
lxc exec docker -- apt install docker.io -y

Вот и всё! У вас установлен актуальный Докер и запущен в контейнере. Теперь можно сделать базовые вещи средствами Docker

lxc exec docker -- docker run --detach --name app carinamarina/hello-world-app

Unable to find image 'carinamarina/hello-world-app:latest' locally
latest: Pulling from carinamarina/hello-world-app
efd26ecc9548: Pull complete 
a3ed95caeb02: Pull complete 
d1784d73276e: Pull complete 
72e581645fc3: Pull complete 
9709ddcc4d24: Pull complete 
2d600f0ec235: Pull complete 
c4cf94f61cbd: Pull complete 
c40f2ab60404: Pull complete 
e87185df6de7: Pull complete 
62a11c66eb65: Pull complete 
4c5eea9f676d: Pull complete 
498df6a0d074: Pull complete 
Digest: sha256:6a159db50cb9c0fbe127fb038ed5a33bb5a443fcdd925ec74bf578142718f516
Status: Downloaded newer image for carinamarina/hello-world-app:latest
c8318f0401fb1e119e6c5bb23d1e706e8ca080f8e44b42613856ccd0bf8bfb0d

lxc exec docker -- docker run --detach --name web --link app:helloapp -p 80:5000 carinamarina/hello-world-web

Unable to find image 'carinamarina/hello-world-web:latest' locally
latest: Pulling from carinamarina/hello-world-web
efd26ecc9548: Already exists 
a3ed95caeb02: Already exists 
d1784d73276e: Already exists 
72e581645fc3: Already exists 
9709ddcc4d24: Already exists 
2d600f0ec235: Already exists 
c4cf94f61cbd: Already exists 
c40f2ab60404: Already exists 
e87185df6de7: Already exists 
f2d249ff479b: Pull complete 
97cb83fe7a9a: Pull complete 
d7ce7c58a919: Pull complete 
Digest: sha256:c31cf04b1ab6a0dac40d0c5e3e64864f4f2e0527a8ba602971dab5a977a74f20
Status: Downloaded newer image for carinamarina/hello-world-web:latest
d7b8963401482337329faf487d5274465536eebe76f5b33c89622b92477a670f

Теперь осталось узнать IP адрес LXD контейнера, чтобы получить доступ к тому что сделал Docker - lxc list

+--------+---------+----------------------+----------------------------------------------+------------+-----------+
|  NAME  |  STATE  |         IPV4         |                      IPV6                    |    TYPE    | SNAPSHOTS |
+--------+---------+----------------------+----------------------------------------------+------------+-----------+
| docker | RUNNING | 172.17.0.1 (docker0) | 2001:470:b368:4242:216:3eff:fe55:45f4 (eth0) | PERSISTENT | 0         |
|        |         | 10.178.150.73 (eth0) |                                              |            |           |
+--------+---------+----------------------+----------------------------------------------+------------+-----------+

curl 10.178.150.73

The linked container said... "Hello World!"

Вывод

Реально просто запустить Docker контейнер внутри LXD контейнера. Не все контейнеры Docker легко будут работать, как в примере, из-за дополнительных ограничений LXD, особенно касаемый пользовательского namespace.

Только хранилище типа overlayfs работает с Docker в этом режиме. Сам тип хранилища может налагать свои ограничения на количество образов, работающие в данной среде. Если у вас не всё работает как нужно в докере и вы доверяете пользователю внутри LXD, то можете сделать контейнер привилегированным: lxc config set docker security.privileged true && lxc restart docker
Только помните, что в данном режиме root внутри контейнера совпадает с UID root хоста. Есть несколько известных способов сбежать из контейнера и получить рутовые права в хосте. Так что сто раз подумайте, представляя пользователя в контейнере как root хоста.

Оглавление цикла статей про LXD 2.0.
Предыдущая статья LXD 2.0: Удалённые хосты и миграция контейнеров [6/12].
Следующая статья LXD 2.0: LXD в LXD [8/12].

Дата последней правки: 2024-03-28 09:42:08

RSS vasilisc.com   


Разделы

Главная
Новости
Ворох бумаг
Видео Linux
Игры в Linux
Безопасность
Статьи об Astra Linux
Статьи о FreeBSD
Статьи об Ubuntu
Статьи о Snappy
Статьи об Ubuntu Phone
Статьи о Kubuntu
Статьи о Xubuntu
Статьи о Lubuntu
Статьи об Open Source
Карта сайта