در این مقاله، مراحل لازم به منظور اجرای docker درون یک docker با سه روش مختلف برای شما شرح داده شده است.

 

 

کاربرد اجرای docker درون docker

در مواردی ممکن است نیاز داشته باشید که یک docker را درون docker container دیگری اجرا نمایید. چند نمونه از این موارد به شرح زیر است:

  • یکی از موارد استفاده بالقوه برای اجرای docker درون docker، در CI pipeline است که در آن، شما باید پس از ساخت موفق کد، imageهای داکر را ساخته در یک کانتینر انتقال دهید.
  •  
  • ساخت imageهای داکر با یک VM بسیار ساده است. با این حال، هنگامی‌که قصد دارید از عوامل پویای مبتنی بر داکر Jenkins برای CI/CD pipeline خود استفاده کنید، اجرای docker درون docker به عنوان یک عملکرد ضروری مطرح می‌شود.
  •  
  • محیط‌های جعبه شنی (Sandbox).
  •  
  • برای اهداف آزمایشی در ایستگاه کاری توسعه محلی.

 

اجرای Docker در Docker Container

سه راه برای دستیابی به Docker در Docker وجود دارد:

  • اجرای docker با mount کردن docker.sock (روش DooD)
  • روش dind
  • استفاده از Nestybox sysbox Docker runtime

در ادامه، هر روش را با جزئیات بررسی می‌کنیم. قبل از دنبال کردن ادامه مقاله، مطمئن شوید که docker را در‌ میزبان خود نصب کرده‌اید.

 

روش 1: Docker در Docker با استفاده از [/var/run/docker.sock]

 

/var/run/docker.sock چیست؟

/var/run/docker.sock، سوکت پیش فرض یونیکس است. سوکت‌ها برای ارتباط بین فرآیندها در یک میزبان یکسان طراحی شده‌اند. Docker daemon به طور پیش فرض سوکت docker.sock را شنود می‌کند. اگر در میزبانی هستید که Docker daemon در آن اجرا است، شما می‌توانید از /var/run/docker.sock به منظور مدیریت کانتینرها استفاده نمایید.

به عنوان مثال، اگر دستور زیر را اجرا کنید، نسخه docker engine را برمی‌گرداند.

curl --unix-socket /var/run/docker.sock http://localhost/version

اکنون که کمی درک کرده‌اید که docker.sock چیست، در ادامه خواهید دید که چگونه می‌توان docker را در docker با استفاده از docker.sock اجرا کرد.

به منظور اجرای docker در داخل docker، کافی است docker را با سوکت پیش‌فرض یونیکس docker.sock به عنوان یک volume اجرا نمایید.

مثلا،

docker run -v /var/run/docker.sock:/var/run/docker.sock \
           -ti docker

 

تذکر: دقت کنید که اگر کانتینر شما به docker.sock دسترسی دارد، به این معنی است که امتیازات بیشتری نسبت به daemon docker شما دارد. بنابراین هنگامی‌که در پروژه‌های واقعی استفاده می‌شود، خطرات امنیتی را درک کرده و سپس از آن استفاده نمایید.

اکنون، از داخل کانتینر، باید بتوانید دستورات docker را برای ساختن و ارسال imageها به رجیستری اجرا کنید.

در اینجا، عملیات داکر واقعی بر روی میزبان VMای رخ می‌دهد که کانتینر پایه داکر شما را اجرا می‌کند؛ به جای اینکه داخل کانتینر انجام شود. به این معنی که، حتی اگر دستورات docker را از داخل کانتینر اجرا می‌نمایید، به کلاینت docker دستور می‌دهید که از طریق docker.sock به موتور داکر میزبانVM متصل شود.

به منظور تست تنظیمات آن، از image رسمی docker در docker hub استفاده کنید. چراکه داکری دارد که docker binary در آن است.

 

برای تست تنظیمات، مراحل زیر را دنبال نمایید.

مرحله 1: کانتینر Docker را در حالت mount تعاملی docker.sock به عنوان volume اجرا کنید. در اینجا، از image رسمی docker استفاده کرده‌ایم.

docker run -v /var/run/docker.sock:/var/run/docker.sock -ti docker

مرحله 2: هنگامی‌که داخل کانتینر هستید، دستور docker زیر را اجرا نمایید.

docker pull ubuntu

مرحله 3: هنگامی‌که imageهای داکر را لیست می‌کنید، باید image اوبونتو را به همراه سایر imageهای داکر در VM میزبان خود مشاهده نمایید.

docker images

 

مرحله 4: اکنون یک Dockerfile در دایرکتوری test ایجاد کنید.

mkdir test && cd test
vi Dockerfile

محتویات Dockerfile زیر را برای آزمایش ساخت image از داخل container کپی نمایید.

FROM ubuntu:18.04

LABEL maintainer="Bibin Wilson <bibinwilsonn@gmail.com>"

RUN apt-get update && \
    apt-get -qy full-upgrade && \
    apt-get install -qy curl && \
    apt-get install -qy curl && \
    curl -sSL https://get.docker.com/ | sh

Dockerfile را به صورت زیر بسازید:

docker build -t test-image .

 

روش 2: داکر درون داکر با استفاده از dind

 

این روش در واقع یک کانتینر فرزند در داخل یک کانتینر ایجاد می‌کند. از این روش تنها در صورتی استفاده کنید که واقعاً می‌خواهید containerها و imageها داخل آن کانتینر باشند. در غیر این صورت، پیشنهاد می‌کنیم از روش اول استفاده نمایید.

بدین منظور، تنها باید از image رسمی docker با تگ dind استفاده کنید. این image با ابزارهای مورد نیاز برای Docker تنظیم شده است تا در یک کانتینر docker اجرا شود.

به منظور تست تنظیمات، مراحل زیر را دنبال نمایید.

 

توجه: برای این کار لازم است container شما در حالت ممتاز (privileged) اجرا شود.

مرحله 1: یک کانتینر به نام dind-test با docker:dind (به عنوان image) ایجاد کنید.

docker run --privileged -d --name dind-test docker:dind

مرحله 2: با استفاده از exec، به صورت زیر وارد کانتینر شوید.

docker exec -it dind-test /bin/sh

اکنون مراحل 2 تا 4 روش قبلی را انجام داده و دستورالعمل‌های خط فرمان docker و ساخت image را تأیید نمایید.

 

روش 3: داکر در داکر با استفاده از Sysbox Runtime

 

روش 1 و 2 به دلیل اجرای کانتینرهای پایه در حالت ممتاز، از نظر امنیت دارای معایبی هستند. Nestybox سعی می‌کند این مشکل را با داشتن یک sysbox Docker runtime حل کند.

اگر یک کانتینر با استفاده از sysbox Docker runtime ایجاد نمایید، می‌تواند محیط‌های مجازی را در داخل یک کانتینری ایجاد کند که قادر به اجرای systemd، docker، kubernetes بدون دسترسی ممتاز به سیستم میزبان اصلی است.

به منظور درک این روش، مثال زیر را دنبال کنید.

مرحله 1: محیط sysbox runtime را نصب نمایید. به منظور دریافت آخرین دستورالعمل‌های رسمی در مورد نصب sysbox runtime به این سایت مراجعه کنید.

مرحله 2: هنگامی‌که sysbox runtime را در دسترس دارید، تنها کاری که باید انجام دهید این است که کانتینر docker را با پرچم  sysbox runtime مانند تصویر زیر راه‌اندازی نمایید. در اینجا از image رسمی docker dind استفاده کرده‌ایم.

docker run --runtime=sysbox-runc --name sysbox-dind -d docker:dind

مرحله 3: در مرحله آخر، یک نشست exec به کانتینر sysbox-dind ببرید.

docker exec -it sysbox-dind /bin/sh

اکنون می‌توانید مطابق روش‌های قبلی، با Dockerfile یکسری image بسازید.

 

نکات کلیدی

از Docker درون Docker تنها در صورت نیاز استفاده کنید. قبل از انتقال هر مورد به روش Docker-in-Docker، حتماً POCها و آزمایشات کافی را انجام دهید.

هنگام استفاده از containerها در حالت ممتاز، حتماً مطمئن شوید که تأییدیه‌های لازم را از تیم‌های امنیتی سازمانی در مورد این کار دریافت می‌کنید.

اگر قصد دارید از Nestybox (Sysbox) استفاده نمایید، مطمئن شوید که توسط معماران سازمانی/تیم‌های امنیتی تست و تایید شده است.

 

 

 

منبع:

devopscube