شاید برای شما هم پیش آمده باشد که مدلی را پس از ساعتها تلاش روی سیستم خود اجرا کنید، اما همکارتان به دلیل تفاوت در نسخهی درایور CUDA، نسخهی پایتون یا پکیجهای C با خطاهای بیپایان مواجه شود. پروژههای هوش مصنوعی بهخاطر وابستگیهای درهمتنیدهی سیستمعامل، درایورهای گرافیک و کتابخانههای یادگیری عمیق، بیش از هر نرمافزار دیگری در معرض ناهماهنگی محیطهای توسعه هستند. داکر این چالش را با ایزولهسازی دقیق پشتهی نرمافزاری برطرف میکند.
در توسعهی پروژههای مبتنی بر هوش مصنوعی، داکر علاوه بر یکسانسازی محیط، نقشی کلیدی در مدیریت ایمیجهای حجیم، مدلهای چند ده گیگابایتی و راهاندازی زیرساختهای چندسرویسی مانند سرورهای استنتاج و پایگاههای دادهی برداری دارد. با استفاده از قابلیت Volume Mount، دادهها و وزن مدلها پایدار میمانند و بازسازی مکرر کانتینرها سرعت کار را کند نمیکند.
با توجه به اینکه دانلود ایمیجها از Docker Hub و دریافت بستهها از PyPI از داخل ایران گاهی با کندی یا اختلال همراه است، استفاده از میرورهای محلی یا تنظیمات پروکسی مناسب فرایند بیلد را بسیار پایدارتر میکند. همچنین اگر به GPU دسترسی ندارید، بیشتر این تمرینها بدون نیاز به پردازندهی گرافیکی خارجی و با تکیه بر CPU یا پردازش محلی نیز قابل آزمایش هستند.
کانتینرها عبارت «روی سیستم من که کار میکنه!» را برای همیشه به خاطرهها میسپارند.
اهداف یادگیری
- ساخت ایمیج داکر (Docker image) مجهز به پردازندهی گرافیکی (GPU) همراه با CUDA، PyTorch و کتابخانههای هوش مصنوعی از روی یک Dockerfile
- اتصال (Mount) دایرکتوریهای سیستم میزبان به عنوان Volume برای ماندگاری مدلها، مجموعهدادهها و کدها در زمان بازسازی کانتینر
- پیکربندی ابزار NVIDIA Container Toolkit جهت دسترسی کانتینرها به پردازندهی گرافیکی
- هماهنگسازی برنامههای چندسرویسی هوش مصنوعی (سرور استنتاج + پایگاه دادهی برداری) با ابزار Docker Compose
صورت مسئله
مدلی را روی لپتاپ خود با PyTorch 2.3، CUDA 12.4 و Python 3.12 آموزش دادهاید. همکارتان PyTorch 2.1، CUDA 11.8 و Python 3.10 دارد. مدل روی سیستم او از کار میافتد؛ اما Dockerfile شما روی هر دو سیستم کار میکند.
پروژههای هوش مصنوعی کابوس وابستگیها هستند. یک پشتهی نرمافزاری معمولی شامل Python، PyTorch، درایورهای CUDA، cuDNN، کتابخانههای سیستمیِ C و بستههای خاصی مثل flash-attn است که به نسخهی دقیق کامپایلر نیاز دارند. داکر همهی این موارد را درون ایمیجی یکپارچه بستهبندی میکند تا همهجا کاملاً یکسان اجرا شود.
مفاهیم پایه
داکر کد، محیط اجرا (Runtime)، کتابخانهها و ابزارهای سیستمی شما را درون واحدی ایزوله به نام کانتینر (Container) قرار میدهد. آن را مثل یک ماشین مجازی سبک در نظر بگیرید؛ با این تفاوت که به جای اجرای کرنل مستقل، از کرنل سیستمعامل میزبان استفاده میکند و در نتیجه به جای چند دقیقه، ظرف چند ثانیه راهاندازی میشود.
چرا پروژههای هوش مصنوعی بیش از بقیه به داکر نیاز دارند؟
-
درایورهای پردازندهی گرافیکی شکنندهاند. کدی که برای CUDA 12.4 نوشته شده است روی CUDA 11.8 اجرا نمیشود. داکر تولکیتِ CUDA را درون کانتینر ایزوله میکند و همزمان از طریق NVIDIA Container Toolkit، درایور گرافیک سیستم میزبان را به اشتراک میگذارد.
-
وزنهای مدلها بسیار حجیماند. یک مدل 7B پارامتری در قالب fp16 حدود 14 گیگابایت حجم دارد. قطعاً نمیخواهید با هر بار بیلد مجدد، آن را دوباره دانلود کنید. والیومهای داکر (Docker volumes) امکان میدهند دایرکتوری مدلها را از سیستم میزبان مانت کنید.
-
معماریهای چندسرویسی رایج هستند. یک برنامهی کاربردی واقعی در حوزهی هوش مصنوعی فقط یک اسکریپت پایتون نیست؛ بلکه شامل سرور استنتاج (Inference server)، پایگاه دادهی برداری (Vector database) برای RAG و شاید یک فرانتاند وب است. ابزار Docker Compose همهی این بخشها را تنها با یک دستور هماهنگ و اجرا میکند.
اصطلاحات کلیدی
| اصطلاح | مفهوم |
|---|---|
| Image | یک قالب فقطخواندنی؛ حکم دستور پخت شما را دارد و از روی Dockerfile ساخته میشود. |
| Container | نمونهی در حال اجرای یک ایمیج؛ حکم آشپزخانهی شما را دارد. |
| Dockerfile | دستورالعملهای لایهبهلایه برای ساخت یک ایمیج. |
| Volume | فضای ذخیرهسازی ماندگار که پس از ریاستارت کانتینر هم باقی میماند. |
| docker-compose | ابزاری برای تعریف برنامههای چندکانتینری در قالب فایلهای YAML. |
الگوهای رایج کانتینر در هوش مصنوعی
Dev Container
Full toolkit. Editor support. Jupyter. Debugging tools.
Used during development and experimentation.
Training Container
Minimal. Just the training script and dependencies.
Runs on GPU clusters. No editor, no Jupyter.
Inference Container
Optimized for serving. Small image. Fast cold start.
Runs behind a load balancer in production.
پیادهسازی از صفر
گام 1: نصب داکر
# macOS
brew install --cask docker
open /Applications/Docker.app
# Ubuntu
curl -fsSL https://get.docker.com | sh
sudo usermod -aG docker $USER
# خروج و ورود مجدد برای اعمال تغییر گروه
بررسی صحت نصب:
docker --version
docker run hello-world
گام 2: نصب NVIDIA Container Toolkit (لینوکس دارای پردازندهی گرافیکی NVIDIA)
این ابزار امکان دسترسی کانتینرهای داکر به پردازندهی گرافیکی را فراهم میکند. کاربران macOS و Windows (WSL2) نیازی به اجرای این مرحله ندارند؛ چرا که Docker Desktop در این پلتفرمها دسترسی به پردازندهی گرافیکی را به روش دیگری مدیریت میکند.
distribution=$(. /etc/os-release;echo $ID$VERSION_ID)
curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg
curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list
sudo apt-get update
sudo apt-get install -y nvidia-container-toolkit
sudo nvidia-ctk runtime configure --runtime=docker
sudo systemctl restart docker
تست دسترسی به پردازندهی گرافیکی از داخل کانتینر:
docker run --rm --gpus all nvidia/cuda:12.4.1-base-ubuntu22.04 nvidia-smi
نمایش مشخصات پردازندهی گرافیکی نشان میدهد این تولکیت بهدرستی کار میکند.
گام 3: شناخت ایمیجهای پایه
انتخاب درست ایمیج پایه (Base image) از ساعتها اتلاف وقت برای خطایابی جلوگیری میکند.
nvidia/cuda:12.4.1-devel-ubuntu22.04
Full CUDA toolkit. Compilers included.
Use for: building packages that need nvcc (flash-attn, bitsandbytes)
Size: ~4 GB
nvidia/cuda:12.4.1-runtime-ubuntu22.04
CUDA runtime only. No compilers.
Use for: running pre-built code
Size: ~1.5 GB
pytorch/pytorch:2.6.0-cuda12.4-cudnn9-runtime
PyTorch pre-installed on top of CUDA.
Use for: skipping the PyTorch install step
Size: ~6 GB
python:3.12-slim
No CUDA. CPU only.
Use for: inference on CPU, lightweight tools
Size: ~150 MB
گام 4: نوشتن Dockerfile برای توسعهی هوش مصنوعی
این فایل داکر در مسیر code/Dockerfile قرار دارد. بخشهای مختلف آن را مرور کنید:
FROM --platform=linux/amd64 nvidia/cuda:12.4.1-devel-ubuntu22.04
ENV DEBIAN_FRONTEND=noninteractive
ENV PYTHONUNBUFFERED=1
RUN apt-get update && apt-get install -y --no-install-recommends \
software-properties-common \
git \
curl \
build-essential \
&& add-apt-repository -y ppa:deadsnakes/ppa \
&& apt-get update && apt-get install -y --no-install-recommends \
python3.12 \
python3.12-venv \
python3.12-dev \
&& rm -rf /var/lib/apt/lists/*
RUN update-alternatives --install /usr/bin/python python /usr/bin/python3.12 1
RUN curl -sSL https://raw.githubusercontent.com/pypa/get-pip/3b73145063be545b649ad9ca83ea8da5fc915a4f/public/get-pip.py -o /tmp/get-pip.py \
&& echo "a341e1a43e38001c551a1508a73ff23636a11970b61d901d9a1cad2a18f57055 /tmp/get-pip.py" | sha256sum -c - \
&& python /tmp/get-pip.py \
&& rm /tmp/get-pip.py \
&& update-alternatives --install /usr/bin/pip pip /usr/local/bin/pip3.12 1
RUN python -m pip install --no-cache-dir --upgrade pip setuptools wheel
RUN python -m pip install --no-cache-dir \
torch==2.6.0+cu124 \
torchvision==0.21.0+cu124 \
torchaudio==2.6.0+cu124 \
--index-url https://download.pytorch.org/whl/cu124
RUN python -m pip install --no-cache-dir \
numpy \
pandas \
scikit-learn \
matplotlib \
jupyter \
transformers \
datasets \
accelerate \
safetensors
WORKDIR /workspace
VOLUME ["/workspace", "/models"]
EXPOSE 8888
CMD ["python"]
بیلد کردن ایمیج:
docker build -t ai-dev -f phases/00-setup-and-tooling/07-docker-for-ai/code/Dockerfile .
این مرحله در بار اول زمانبر خواهد بود (دانلود ایمیج پایهی CUDA + پایتورچ). بیلدهای بعدی از لایههای کششده استفاده خواهند کرد.
سیستمعامل macOS / تراشههای Apple Silicon (مدلهای M1/M2/M3/M4): عبارت --platform=linux/amd64 در خط FROM همان چیزی است که امکان اجرای موفق این بیلد را روی مک فراهم میکند. ایمیج پایهی CUDA نسخهی arm64 هم دارد و Docker Desktop روی Apple Silicon آن را بهصورت خودکار انتخاب میکند؛ اما PyTorch پکیجهای ویل (Wheels) مربوط به cu124 را فقط برای x86_64 عرضه کرده است، بنابراین لایهی pip install torch==2.6.0+cu124 با خطای No matching distribution found for torch==2.6.0+cu124 شکست میخورد. با قفل کردن پلتفرم، ایمیج x86_64 دانلود شده و به کمک شبیهساز اجرا میشود: در این حالت فرایند بیلد کندتر است و کانتینر دسترسی به پردازندهی گرافیکی ندارد (روی سیستمهای مک در هر صورت قابلیت CUDA وجود ندارد). در دستورات docker run زیر روی مک، گزینهی --gpus all را بردارید. برای کارهای مبتنی بر GPU روی Apple Silicon، درسها را مستقیماً بهصورت محلی با نسخهی MPS از درس 01 اجرا کنید و این ایمیج را فقط برای هاستهای لینوکسی x86_64 مجهز به گرافیک NVIDIA نگه دارید.
اجرای کانتینر:
docker run --rm -it --gpus all \
-v $(pwd):/workspace \
-v ~/models:/models \
ai-dev python -c "import torch; print(f'PyTorch {torch.__version__}, CUDA: {torch.cuda.is_available()}')"
اجرای ژوپیتر درون کانتینر:
docker run --rm -it --gpus all \
-v $(pwd):/workspace \
-v ~/models:/models \
-p 8888:8888 \
ai-dev jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --allow-root
گام 5: اتصال والیومها برای دادهها و مدلها
اتصال والیوم برای کارهای هوش مصنوعی حیاتی است. بدون آن، فایل 14 گیگابایتی مدلی که دانلود کردهاید با متوقف شدن کانتینر پاک میشود.
# مانت کردن کد شما
-v $(pwd):/workspace
# مانت کردن یک پوشهٔ اشتراکی برای مدلها
-v ~/models:/models
# مانت کردن مجموعهدادهها
-v ~/datasets:/data
درون اسکریپت آموزشی خود، مدل را از مسیر مانتشده بارگذاری کنید:
from transformers import AutoModel
model = AutoModel.from_pretrained("/models/llama-7b")
مدل روی سیستم فایل اصلی سیستم میزبان باقی میماند؛ بنابراین هر چند بار که بخواهید کانتینر را از نو بیلد کنید، نیازی به دانلود دوبارهی مدل نیست.
گام 6: استفاده از Docker Compose برای برنامههای چندسرویسی
یک برنامهی واقعی RAG به یک سرور استنتاج و یک پایگاه دادهی برداری نیاز دارد. Docker Compose هر دو را تنها با یک دستور اجرا میکند.
فایل code/docker-compose.yml را بررسی کنید:
services:
ai-dev:
build:
context: .
dockerfile: Dockerfile
deploy:
resources:
reservations:
devices:
- driver: nvidia
count: all
capabilities: [gpu]
volumes:
- ../../../:/workspace
- ~/models:/models
- ~/datasets:/data
ports:
- "8888:8888"
stdin_open: true
tty: true
command: jupyter notebook --ip=0.0.0.0 --port=8888 --no-browser --allow-root
qdrant:
image: qdrant/qdrant:v1.12.5
ports:
- "6333:6333"
- "6334:6334"
volumes:
- qdrant_data:/qdrant/storage
volumes:
qdrant_data:
راهاندازی همهی سرویسها:
cd phases/00-setup-and-tooling/07-docker-for-ai/code
docker compose up -d
حالا کانتینر توسعهی هوش مصنوعی شما میتواند از طریق نام سرویس و با آدرس http://qdrant:6333 به پایگاه دادهی برداری دسترسی پیدا کند. ابزار Docker Compose یک شبکهی مشترک را بهصورت خودکار میسازد.
تست اتصال از داخل کانتینر هوش مصنوعی:
from qdrant_client import QdrantClient
client = QdrantClient(host="qdrant", port=6333)
print(client.get_collections())
متوقف کردن همهی سرویسها:
docker compose down
با اضافه کردن -v، والیوم مربوط به پایگاه دادهی qdrant نیز حذف میشود:
docker compose down -v
گام 7: دستورات کاربردی داکر در پروژههای هوش مصنوعی
# فهرست کردن کانتینرهای در حال اجرا
docker ps
# فهرست کردن تمام ایمیجها و حجم آنها
docker images
# حذف ایمیجهای بلااستفاده (آزادسازی فضای دیسک)
docker system prune -a
# بررسی مصرف GPU در داخل یک کانتینر در حال اجرا
docker exec -it <container_id> nvidia-smi
# کپی کردن یک فایل از کانتینر به هاست
docker cp <container_id>:/workspace/results.csv ./results.csv
# مشاهده لاگهای کانتینر
docker logs -f <container_id>
استفاده از ابزارهای واقعی
اکنون یک محیط توسعهی هوش مصنوعیِ بازتولیدپذیر در اختیار دارید. برای ادامهی این دوره:
- با
docker compose upمحیط توسعه و پایگاه دادهی برداری را همزمان اجرا کنید. - کدها، مدلها و دادهها را به عنوان والیوم مانت کنید تا هنگام بیلد مجدد چیزی از دست نرود.
- هر زمان درسی به پکیج پایتونی جدیدی نیاز داشت، آن را به Dockerfile اضافه کرده و دوباره بیلد کنید.
- فایل Dockerfile را با همکاران خود به اشتراک بگذارید تا همگی دقیقاً از محیط کاری یکسانی استفاده کنید.
پردازندهی گرافیکی ندارید؟
فلگ --gpus all و بخش deploy مربوط به NVIDIA را حذف کنید. کانتینر همچنان برای درسهای مبتنی بر پردازندهی مرکزی (CPU) به کار خود ادامه میدهد. PyTorch نبودِ CUDA را بهصورت خودکار تشخیص داده و محاسبات را به پردازندهی اصلی منتقل میکند.
تمرینها
- فایل Dockerfile را بیلد کنید و دستور
python -c "import torch; print(torch.__version__)"را درون کانتینر اجرا کنید. - پشتهی docker-compose را اجرا کرده و مطمئن شوید Qdrant از داخل کانتینر هوش مصنوعی در آدرس
http://qdrant:6333/collectionsدر دسترس است. - بستهی
flaskرا به Dockerfile اضافه کنید، ایمیج را مجدداً بسازید و یک سرور API ساده روی پورت 5000 اجرا کنید. پورت را با-p 5000:5000نگاشت دهید. - حجم ایمیج را با دستور
docker imagesبررسی کنید. سپس ایمیج پایه را ازdevelبهruntimeتغییر دهید و تفاوت حجمها را مقایسه کنید.
راهنماییها
تمرین 1. ایمیج را با دستور docker build -t ai-dev -f phases/00-setup-and-tooling/07-docker-for-ai/code/Dockerfile . موجود در درس بسازید، سپس دستور ایمپورت را داخل docker run --rm ai-dev اجرا کنید. همانطور که در متن درس توضیح داده شد، روی مک گزینهی --gpus all را نگذارید. نسخهی چاپشده در کانتینر باید با 2.6.0 شروع شود.
تمرین 2. دستور docker compose up -d را در پوشهی code/ اجرا کنید و سپس با docker compose exec ai-dev bash یک شل در سرویس ai-dev باز کنید. در داخل آن، دستور curl http://qdrant:6333/collections را اجرا کنید؛ دریافت یک پاسخ JSON یعنی نام سرویس روی شبکهی compose بهدرستی شناسایی شده است.
تمرین 3. خط RUN pip install flask را به Dockerfile اضافه کنید، ایمیج را مجدداً بیلد کنید و سرور را با host="0.0.0.0" اجرا کنید؛ چرا که اگر سرور به localhost داخلی کانتینر متصل شود، از بیرون در دسترس نخواهد بود. سپس http://localhost:5000 را در سیستم خود باز کنید تا مطمئن شوید نگاشت پورت کار میکند.
تمرین 4. دستور docker images ai-dev را اجرا کرده و مقدار ستون SIZE را یادداشت کنید. کلمهی devel را در خط FROM به runtime تغییر دهید، ایمیج را با تگ جدیدی بسازید و حجمها را مقایسه کنید؛ ایمیج runtime کامپایلرها و هدرها را ندارد.
اصطلاحات کلیدی
| اصطلاح | در گفتوگوها | معنای فنی و دقیق |
|---|---|---|
| Container | «ماشین مجازی سبک» | فرایندی ایزوله که از هستهی سیستمعامل میزبان استفاده میکند و سیستم فایل و شبکهی اختصاصی خود را دارد. |
| Image layer | «مرحلهی کششده» | هر دستور Dockerfile یک لایه میسازد. لایههای دستنخورده کش میشوند تا بیلدهای بعدی سریع انجام شوند. |
| NVIDIA Container Toolkit | «کارت گرافیک در داکر» | یک هوک در محیط اجرا که پردازندههای گرافیکی میزبان را با فلگ --gpus در اختیار کانتینرها میگذارد. |
| Volume mount | «پوشهی اشتراکی» | دایرکتوری مشخصی روی سیستم میزبان که به داخل کانتینر نگاشت میشود؛ تغییرات آن پس از توقف کانتینر هم حفظ میشوند. |
| Base image | «نقطهی شروع» | ایمیجی که در خط FROM تعریف میشود و Dockerfile شما روی آن ساخته میشود؛ مشخص میکند چه ابزارهایی از قبل نصب شدهاند. |
