اگه تا حالا با داکر کار کرده باشید، احتمالاً این صحنه برایتان آشناست: یک کانتینر برای اپلیکیشن، یکی برای دیتابیس، یکی برای Redis، و بعد کلی دستور docker run با فلگهای طولانی که حفظ کردنشان خودش یک مهارت جداست. اینجاست که Docker Compose وارد میشود؛ ابزاری که به شما اجازه میدهد کل استک پروژه را در یک فایل YAML تعریف کنید و با یک دستور ساده بالا بیاورید.
برای جزئیات بیشتر میتوانید به مستندات رسمی Docker Compose هم مراجعه کنید.
در این راهنما از صفر یاد میگیرید Docker Compose چیست، چه فرقی با دستورات معمولی داکر دارد، چطور یک پروژه واقعی (مثلاً وردپرس + MySQL یا یک API ساده) را با آن راه بیندازید، و در نهایت چند نکته عملی برای استفاده روی سرور و محیط پروداکشن. اگر هنوز با مفاهیم پایه داکر آشنا نیستید، پیشنهاد میکنیم اول مطلب داکر چیست را بخوانید و بعد برگردید اینجا.

Docker Compose چیست؟
Docker Compose یک ابزار رسمی از اکوسیستم داکر است که برای تعریف و اجرای اپلیکیشنهای چندکانتینری طراحی شده. بهجای اینکه برای هر سرویس جداگانه docker run بزنید، همه سرویسها، شبکه، ولومها و متغیرهای محیطی را داخل یک فایل (معمولاً به نام docker-compose.yml یا compose.yaml) مینویسید.
بعد فقط کافی است در همان پوشه دستور زیر را اجرا کنید:
docker compose up -d
Compose خودش کانتینرها را میسازد، به هم وصل میکند، ولومها را mount میکند و شبکه داخلی را راه میاندازد. وقتی کارتان تمام شد:
docker compose down
همهچیز بهصورت منظم پایین میآید؛ بدون اینکه دستی دنبال اسم کانتینرها بگردید.
چرا به Docker Compose نیاز دارید؟
برای یک کانتینر تکی، همان docker run کافی است. اما بهمحض اینکه پروژه کمی جدی میشود، معمولاً چند سرویس همزمان لازم دارید:
- وبسرور یا اپلیکیشن (Nginx، Node، Django، Laravel و …)
- دیتابیس (MySQL، PostgreSQL، MongoDB)
- کش (Redis، Memcached)
- گاهی صف پیام، Worker، یا سرویسهای جانبی مثل Mailhog برای تست ایمیل
بدون Compose باید برای هر سرویس دستور جدا بنویسید، پورتها را دستی مپ کنید، شبکه بسازید و اسم کانتینرها را به هم لینک کنید. با Compose این پیچیدگی داخل یک فایل خوانا جمع میشود و تیم شما دقیقاً همان چیزی را اجرا میکند که روی لپتاپ توسعهدهنده کار میکند.
مزایای کلیدی:
- تکرارپذیری: یک فایل، یک محیط یکسان برای همه اعضای تیم
- سرعت بالا آوردن استک: مناسب دمو، تست محلی و حتی استقرار ساده روی سرور
- مستندسازی زنده: فایل Compose خودش توضیح میدهد پروژه از چه سرویسهایی تشکیل شده
- مدیریت یکپارچه: لاگ، ریاستارت، اسکیل و توقف همه با دستورات Compose
تفاوت Docker و Docker Compose
خیلیها این دو را با هم اشتباه میگیرند. خلاصه تفاوتشان این است:
| مورد | Docker (CLI معمولی) | Docker Compose |
|---|---|---|
| واحد کار | یک کانتینر / یک ایمیج | چند سرویس بهصورت یک پروژه |
| تعریف تنظیمات | فلگهای طولانی در خط فرمان یا اسکریپت | فایل YAML خوانا و قابلنسخه |
| شبکه و ولوم | دستی تنظیم میشود | بهصورت پیشفرض و یکپارچه مدیریت میشود |
| مناسب برای | تست سریع یک کانتینر | اپلیکیشن چندسرویسی و تیمهای توسعه |
| دستور نمونه | docker run -d -p 80:80 nginx |
docker compose up -d |
یادتان باشد: Compose جایگزین داکر نیست؛ روی همان Docker Engine سوار میشود و کار مدیریت چند کانتینر را سادهتر میکند.
پیشنیازها: نصب Docker و Compose
در نسخههای جدید داکر (Docker Engine بههمراه Docker Desktop یا پکیجهای رسمی لینوکس)، دستور docker compose بهصورت پلاگین داخلی در دسترس است. دیگر لازم نیست جداگانه docker-compose (با خط تیره) نصب کنید؛ هرچند در خیلی از آموزشهای قدیمی هنوز همان شکل نوشته میشود.
برای اطمینان، این دو دستور را بزنید:
docker --version
docker compose version
اگر نسخه Compose نمایش داده شد، آمادهاید. روی سرور لینوکس معمولاً بعد از نصب Docker Engine، پلاگین Compose را هم اضافه میکنید. اگر از سرویسهای ابری یا سرور مجازی استفاده میکنید، کافی است یک بار داکر را روی سیستمعامل نصب کنید و بعد بقیه کار با همان فایل YAML جلو میرود.
ساختار فایل docker-compose.yml
قلب Compose همین فایل است. یک نمونه مینیمال را ببینید:

services:
web:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- ./html:/usr/share/nginx/html:ro
restart: unless-stopped
redis:
image: redis:7-alpine
restart: unless-stopped
مهمترین بخشها:
- services: لیست سرویسها (هر کدام یک کانتینر منطقی)
- image: ایمیجی که از رجیستری pull میشود
- build: اگر بخواهید از Dockerfile خودتان ایمیج بسازید
- ports: مپ پورت میزبان به پورت داخل کانتینر
- volumes: ماندگاری داده یا اشتراک فایل با میزبان
- environment / env_file: متغیرهای محیطی
- depends_on: ترتیب تقریبی بالا آمدن سرویسها
- networks: جداسازی ترافیک بین سرویسها
- restart: سیاست ریاستارت بعد از قطعی یا ریبوت
نکته کاربردی: از نسخه Compose Specification، کلید سطحبالای version: دیگر الزامی نیست. اگر در فایلهای قدیمی دیدید، نگران نباشید؛ هنوز هم کار میکند.
مثال عملی ۱: وردپرس + MySQL با Docker Compose
یکی از رایجترین سناریوها برای مبتدیها، بالا آوردن وردپرس محلی برای تست قالب یا افزونه است. فایل زیر را با نام compose.yaml ذخیره کنید:
services:
db:
image: mysql:8.0
restart: unless-stopped
environment:
MYSQL_DATABASE: wordpress
MYSQL_USER: wpuser
MYSQL_PASSWORD: strongpass
MYSQL_ROOT_PASSWORD: rootstrongpass
volumes:
- db_data:/var/lib/mysql
wordpress:
image: wordpress:latest
restart: unless-stopped
ports:
- "8080:80"
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_USER: wpuser
WORDPRESS_DB_PASSWORD: strongpass
WORDPRESS_DB_NAME: wordpress
volumes:
- wp_data:/var/www/html
depends_on:
- db
volumes:
db_data:
wp_data:
حالا در همان پوشه:
docker compose up -d
docker compose ps
docker compose logs -f wordpress
سایت را در مرورگر با آدرس http://localhost:8080 باز کنید و مراحل نصب وردپرس را طی کنید. داده دیتابیس داخل ولوم db_data میماند؛ یعنی حتی اگر docker compose down بزنید (بدون فلگ -v)، دیتابیس پاک نمیشود.
برای محیط واقعی، رمزها را داخل فایل ننویسید؛ از .env و سرویسهای مدیریت سکرت استفاده کنید. همچنین روی هاست یا سرور پروداکشن، پشت Nginx/SSL و بکاپ منظم قرار دهید. اگر سایت وردپرسیتان را روی زیرساخت ابری نگه میدارید، امکاناتی مثل گواهی SSL خودکار و بکاپ دورهای میتواند بخشی از دغدغههای عملیاتی را کم کند.
مثال عملی ۲: یک API ساده Node.js با Redis
فرض کنید یک سرویس Node دارید و میخواهید برای کش از Redis استفاده کنید. ساختار پوشه:
my-api/
Dockerfile
compose.yaml
package.json
src/index.js
نمونه Dockerfile:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "src/index.js"]
و compose.yaml:
services:
api:
build: .
ports:
- "3000:3000"
environment:
REDIS_URL: redis://cache:6379
NODE_ENV: production
depends_on:
- cache
restart: unless-stopped
cache:
image: redis:7-alpine
restart: unless-stopped
volumes:
- redis_data:/data
volumes:
redis_data:
نکته مهم شبکه: داخل Compose، سرویسها با نام سرویس همدیگر را پیدا میکنند. برای همین در متغیر محیطی نوشتیم redis://cache:6379 نه localhost. از دید کانتینر API، نام DNS سرویس Redis همان cache است.
دستورات پرکاربرد Docker Compose
| دستور | کاربرد |
|---|---|
docker compose up -d |
ساخت و اجرای سرویسها در پسزمینه |
docker compose down |
توقف و حذف کانتینرها و شبکه پروژه |
docker compose down -v |
همان + حذف ولومها (داده پاک میشود) |
docker compose ps |
وضعیت سرویسهای پروژه |
docker compose logs -f |
دنبال کردن لاگ همه سرویسها |
docker compose logs -f api |
لاگ فقط یک سرویس |
docker compose build |
بیلد مجدد ایمیجها |
docker compose pull |
بهروزرسانی ایمیجها از رجیستری |
docker compose exec api sh |
ورود به شل داخل کانتینر در حال اجرا |
docker compose restart |
ریاستارت سرویسها |
یک عادت خوب: قبل از تغییرات بزرگ، خروجی docker compose config را ببینید تا از صحت YAML و جایگزینی متغیرهای .env مطمئن شوید.
کار با فایل .env و متغیرهای محیطی
رمز عبور و تنظیمات حساس را مستقیم داخل YAML نگذارید. یک فایل .env کنار Compose بسازید:
MYSQL_PASSWORD=strongpass
MYSQL_ROOT_PASSWORD=rootstrongpass
WP_PORT=8080
و در Compose به این شکل استفاده کنید:
services:
db:
image: mysql:8.0
environment:
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
wordpress:
ports:
- "${WP_PORT}:80"
فایل .env را به Git اضافه نکنید؛ بهجایش یک .env.example بدون مقدار واقعی بسازید تا بقیه تیم ساختار را ببینند.
ولوم، داده پایدار و بکاپ
کانتینرها موقتیاند؛ دادههای مهم باید در ولوم یا بایندماونت میزبان باشند. برای دیتابیس تقریباً همیشه از named volume استفاده کنید. برای بکاپ ساده MySQL میتوانید چیزی شبیه این را اجرا کنید:
docker compose exec db mysqldump -u root -p"$MYSQL_ROOT_PASSWORD" wordpress > backup.sql
و برای بازگردانی، محتوا را به mysql پایپ کنید. در محیط پروداکشن، بکاپ را زمانبندی کنید و خارج از همان سرور نگه دارید. اگر از زیرساخت ابری استفاده میکنید، داشتن اسنپشات دیسک یا بکاپ خودکار سرویس هم لایه امنیتی خوبی است؛ Compose جایگزین سیاست بکاپ نیست، فقط استقرار را سادهتر میکند.
نکات امنیتی و آمادهسازی برای سرور
Compose برای توسعه عالی است و برای استقرارهای کوچک تا متوسط هم کاملاً رایج است. قبل از بردن به سرور، این چکلیست را مرور کنید:
- پورتهای غیرضروری را به اینترنت باز نکنید؛ فقط همان چیزی که پشت ریورسپراکسی لازم است
- از ایمیجهای رسمی و تگ مشخص (مثلاً
nginx:1.27-alpine) استفاده کنید، نه همیشهlatest - کاربر non-root داخل Dockerfile تعریف کنید (هرجا ممکن است)
- ریسورسها را محدود کنید (
mem_limit/deploy.resourcesبسته به نسخه) - لاگها را مانیتور کنید و برای دیتابیس بکاپ داشته باشید
- برای HTTPS از Nginx/Caddy یا سرویس لودبالانسر با گواهی SSL استفاده کنید
- آپدیت منظم ایمیجها و پچ امنیتی سیستمعامل را فراموش نکنید
اگر پروژهتان بزرگ شد و به ارکستراسیون چندنود، Self-healing پیشرفته و اسکیل افقی نیاز داشتید، قدم بعدی معمولاً Kubernetes یا سرویسهای کانتینری مدیریتشده است. ولی برای شروع و حتی خیلی از سرویسهای واقعی، Compose هنوز انتخابی منطقی و کمهزینه است.
Docker Compose روی سرور ابری؛ یک سناریوی ساده
فرض کنید یک سرور لینوکس (VPS یا سرور ابری) دارید و میخواهید همان استک وردپرس را روی آن اجرا کنید:
- به سرور SSH بزنید و Docker Engine + پلاگین Compose را نصب کنید
- کد و فایل
compose.yamlرا روی سرور قرار دهید (Git clone یا آپلود) - فایل
.envرا با رمزهای قوی روی سرور بسازید docker compose up -dرا اجرا کنید- دامنه را به IP سرور اشاره دهید و با Nginx/Caddy گواهی SSL بگیرید
در سرویسهای ابری مثل چابکان، میتوانید بهجای درگیر شدن با همه لایههای زیرساختی، روی استقرار اپ تمرکز کنید و برای موضوعاتی مثل شبکه، ذخیرهسازی و مقیاسپذیری از امکانات پنل استفاده کنید. Compose در این مسیر نقش «دستورالعمل تکرارپذیر استقرار» را بازی میکند.
اشتباهات رایج مبتدیها
- استفاده از localhost بین سرویسها: داخل شبکه Compose باید اسم سرویس را صدا بزنید.
- فراموش کردن ولوم برای دیتابیس: با
down -vیا recreate، داده از بین میرود. - باز کردن پورت دیتابیس روی ۰.۰.۰.۰: مگر برای دیباگ کوتاه؛ در پروداکشن خطرناک است.
- کپی کردن رمزهای نمونه از آموزش: حتماً عوضشان کنید.
- ندانستن تفاوت up و up –build: اگر Dockerfile عوض شده، باید بیلد مجدد بگیرید.
- نادیده گرفتن لاگ: بیشتر خطاهای اتصال DB یا permission با
logs -fمعلوم میشوند.
جمعبندی
Docker Compose همان قطعهای است که کار با داکر را از «چند دستور پراکنده» به «یک پروژه منسجم» تبدیل میکند. با یک فایل YAML میتوانید اپ، دیتابیس، کش و وابستگیها را تعریف کنید، روی لپتاپ تست بگیرید و همان تعریف را روی سرور اجرا کنید. از مثال وردپرس یا API+Redis شروع کنید، دستورات پرکاربرد را تمرین کنید، و کمکم سراغ .env، بکاپ و سختکردن تنظیمات برای پروداکشن بروید.
اگر بهتازگی میخواهید سرویس کانتینریتان را روی زیرساخت پایدار بالا بیاورید، یک سرور ابری با منابع شفاف، دسترسی SSH و امکاناتی مثل SSL و بکاپ میتواند مسیر یادگیری تا استقرار واقعی را کوتاهتر کند. Compose را یاد بگیرید؛ بعد انتخاب زیرساخت خیلی سادهتر میشود.
سؤالات متداول (FAQ)
آیا Docker Compose برای پروداکشن مناسب است؟
برای پروژههای کوچک و متوسط، تکسرور یا استکهای ساده، بله و بسیار رایج است. وقتی به کلاستر چندنود، اسکیل خودکار پیچیده و سیاستهای پیشرفته ارکستراسیون نیاز دارید، سراغ Kubernetes یا پلتفرمهای کانتینری مدیریتشده بروید.
فرق docker-compose و docker compose چیست؟
قبلاً باینری جداگانهای به نام docker-compose (V1) وجود داشت. امروز شکل توصیهشده، پلاگین رسمی docker compose (بدون خط تیره) است که همراه داکر نصب میشود. از نظر فایل YAML تقریباً سازگارند، اما بهتر است به نسخه جدید مهاجرت کنید.
آیا باید Kubernetes را هم همزمان یاد بگیرم؟
نه لزوماً. اول Compose و مفاهیم کانتینر، شبکه و ولوم را خوب یاد بگیرید. Kubernetes قدرت بیشتری دارد ولی پیچیدگیاش هم بیشتر است؛ بدون پایه Compose معمولاً گیجکننده میشود.
چطور چند محیط (dev/stage/prod) را مدیریت کنم؟
میتوانید چند فایل Compose داشته باشید، مثلاً compose.yaml پایه و compose.override.yaml برای توسعه، یا با فلگ -f فایلهای جدا را ترکیب کنید. متغیرهای محیطی را هم برای هر محیط جدا نگه دارید.
اگر یکی از سرویسها دیر بالا بیاید چه کار کنم؟
depends_on فقط ترتیب استارت را مشخص میکند، نه آماده بودن واقعی سرویس. برای انتظار تا healthy شدن دیتابیس، از healthcheck و شرط depends_on: condition: service_healthy استفاده کنید یا در اپ منطق retry بگذارید.
آیا میتوانم فقط یک سرویس را ریاستارت کنم؟
بله. مثلاً docker compose restart wordpress یا برای بیلد مجدد: docker compose up -d --build api.