Як я запускав Докер усередині Докера і що з цього вийшло

Всім привіт! В своїй попередній статтія обіцяв розповісти про запуск Докера в Докері і про практичні аспекти застосування цього заняття. Настав час виконати свою обіцянку. Досвідчений девопс, мабуть, заперечить, що тим кому потрібен Докер всередині Докера, просто прокидають сокет Докер демона з хоста всередину контейнера і цього вистачить у 99% випадків. Але не поспішайте кидати в мене печінки, адже мова піде про реальний запуск Докера всередині Докера. У цього рішення багато можливих областей застосування і про один з них ця стаття, так що сідайте зручніше і випряміть руки перед собою.

Як я запускав Докер усередині Докера і що з цього вийшло

Початок

Все почалося дощовим вересневим вечором, коли я чистив орендовану за $5 машинку на Digital Ocean, яка намертво повисла через те, що Докер заполонив своїми образами та контейнерами всі 24 гігабайти доступного дискового простору. Іронія була в тому, що всі ці образи та контейнери були транзієнтними і потрібні були лише для того, щоб тестувати працездатність моєї програми щоразу, коли виходила нова версія якоїсь бібліотеки чи фреймворку. Я пробував писати шелл-сркіпти і налаштовувати розклад крон для очищення сміття, але це не врятувало: щоразу все неминуче закінчувалося тим, що дисковий простір мого сервера виявлявся з'їденим а сервер завислим (у кращому випадку). В якийсь момент я натрапив на статтю про те, як запускати Jenkins в контейнері і як він може створювати і видаляти конвеєри зборки через прокинутий в нього сокет докер демона. Ідея мені сподобалася, але я вирішив піти далі і спробувати поекспериментувати з безпосереднім запуском Докера всередині Докера. Мені тоді здавалося цілком логічним рішенням викачувати докер образи і створювати контейнери всіх додатків, які мені потрібні для тестування всередині іншого контейнера (давайте назвемо його staging контейнер). Ідея полягала у тому, щоб запускати staging контейнер з прапором -rm, що автоматично видаляє весь контейнер з усім його вмістом у його зупинці. Я покопався з докером чином від самого Докера (https://hub.docker.com/_/docker), але воно виявилося занадто громіздким і мені так і не вдалося змусити його працювати так, як мені потрібно і мені хотілося пройти весь шлях самому.

практика. Шишки

Я поставив за мету змусити контейнер працювати так як мені було потрібно і продовжував свої експерименти, результатом яких стала незліченна кількість шишок. Підсумком мого самокатування став такий алгоритм:

  1. Запускаємо контейнер Докер в інтерактивному режимі.

    docker run --privileged -it docker:18.09.6

    Зверніть увагу на версію контейнера, крок праворуч або ліворуч і ваш ДінД перетворюється на гарбуз. Насправді все ламається досить часто з виходом нової версії.
    Ми повинні одразу потрапити до шеллу.

  2. Пробуємо дізнатися, які контейнери запущені (Відповідь: ніякі), але давайте виконаємо команду все одно:

    docker ps

    Ви будете трохи здивовані, але виявляється Докер демон навіть не запущений:

    error during connect: Get http://docker:2375/v1.40/containers/json: dial tcp: lookup docker on 
    192.168.65.1:53: no such host

  3. Давайте запустимо його самостійно:

    dockerd &

    Ще одна неприємна несподіванка:

    failed to start daemon: Error initializing network controller: error obtaining controller instance: failed 
    to create NAT chain DOCKER: Iptables not found

  4. Встановлюємо пакети iptables і bash (у баші всяко працювати приємніше ніж у sh):

    apk add --no-cache iptables bash

  5. Запускаємо bash. Нарешті ми знову у звичному шеллі

  6. спробуємо запустити Докер ще раз:

    dockerd &

    Ми повинні побачити довге простирадло логів, що закінчується:

    INFO[2019-11-25T19:51:19.448080400Z] Daemon has completed initialization          
    INFO[2019-11-25T19:51:19.474439300Z] API listen on /var/run/docker.sock

  7. Натискаємо Enter. Ми знову у баші.

Починаючи з цього моменту ми можемо пробувати запускати інші контейнери всередині нашого Докер контейнера, але що якщо ми хочемо підняти ще один Докер контейнер всередині нашого Докер контейнера або щось піде не так і контейнер «вилетить»? Починати все спочатку.

Власний DinD контейнер та нові експерименти

Як я запускав Докер усередині Докера і що з цього вийшло
Щоб не повторювати вищезгадані кроки знову і знову я створив власний DinD контейнер:

https://github.com/alekslitvinenk/dind

Робоче DinD рішення дало мені можливість запускати Докер всередині Докер рекурсивно і проводити сміливіші експерименти.
Один такий (вдалий) експеримент із запуском MySQL та Nodejs я збираюся зараз описати.
Найбільш нетерплячі можуть подивитись як це було тут

Тож почнемо:

  1. Запускаємо DinD в інтерактивному режимі. У цій версії DinD нам потрібно вручну замапити всі порти, які можуть використовувати наші дочірні контейнери (я над цим вже працюю)

    docker run --privileged -it 
    -p 80:8080 
    -p 3306:3306 
    alekslitvinenk/dind

    Ми потрапляємо в баш, звідки ми можемо відразу приступати до запуску дочірніх контейнерів.

  2. Запускаємо MySQL:

    docker run --name mysql -e MYSQL_ROOT_PASSWORD=strongpassword -d -p 3306:3306 mysql

  3. Підключаємося до бази даних як і ми підключалися до неї локально. Переконуємось, що все працює.

  4. Запускаємо другий контейнер:

    docker run -d --rm -p 8080:8080 alekslitvinenk/hello-world-nodejs-server

    Зверніть увагу, що порт мапінг тут буде саме 8080:8080, тому що ми вже замапили порт 80 з хоста до батьківського контейнера на порт 8080.

  5. Йдемо на localhost у браузері, переконуємось, що сервер відповідає «Hello World!».

У моєму випадку експеримент із вкладеними докерами контейнерами виявився досить позитивним і я продовжу розвивати проект і використовувати його для стейджингу. Мені здається, що це набагато більш легке рішення ніж той же Kubernetes та Jenkins X. Але це моя суб'єктивна думка.

Я думаю, що для сьогоднішньої статті це все. У наступній статті я докладніше опишу експерименти з рекурсивним запуском Докера в Докері та монтування директорій углиб вкладених контейнерів.

PS Якщо ви вважаєте цей проект корисним, то будь ласка, поставте йому зірочку на ГітХабі, зробіть форк і розкажіть друзям.

Edit1 Виправив помилки, зробив фокус на 2 відео

Джерело: habr.com

Додати коментар або відгук