В седьмой статье рассмотрен вариант использования Docker (инструмент развёртывания приложений в контейнерах) внутри LXD.
Как кратко было написано в начале первого поста серии, LXD фокусируется на системных контейнерах. То есть внутри запускается не модифицированный дистрибутив Linux. LXD не заботится о рабочей нагрузке внутри контейнера. Он просто создаёт namespace контейнера и применяет политики безопасности, затем запускает /sbin/init и ждёт когда контейнер завершит свою работу.
Контейнеры приложений, такие как Docker или Rkt, используются для дистрибуции ПО, обычно запускают единичный процесс внутри, тем самым являясь более эфемерными в сравнении с LXD. Два типа контейнера не являются взаимоисключающими. Много усилий было сделано разработчиками, чтобы Docker отлично работал внутри LXD.
Это означает, что в Ubuntu 16.04 и с LXD 2.0 вы можете создать контейнеры для ваших пользователей, которые подсоединятся к ним, как к обычной Убунту системе, и с помощью 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].