وبلاگ
Docker Compose Extends: استفاده مجدد و ارثبری از پیکربندیها
فهرست مطالب
“تسلط به برنامهنویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT”
"تسلط به برنامهنویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT"
"با شرکت در این دوره جامع و کاربردی، به راحتی مهارتهای برنامهنویسی پایتون را از سطح مبتدی تا پیشرفته با کمک هوش مصنوعی ChatGPT بیاموزید. این دوره، با بیش از 6 ساعت محتوای آموزشی، شما را قادر میسازد تا به سرعت الگوریتمهای پیچیده را درک کرده و اپلیکیشنهای هوشمند ایجاد کنید. مناسب برای تمامی سطوح با زیرنویس فارسی حرفهای و امکان دانلود و تماشای آنلاین."
ویژگیهای کلیدی:
بدون نیاز به تجربه قبلی برنامهنویسی
زیرنویس فارسی با ترجمه حرفهای
۳۰ ٪ تخفیف ویژه برای دانشجویان و دانش آموزان
0 تا 100 عطرسازی + (30 فرمولاسیون اختصاصی حامی صنعت)
دوره آموزش Flutter و برنامه نویسی Dart [پروژه محور]
دوره جامع آموزش برنامهنویسی پایتون + هک اخلاقی [با همکاری شاهک]
دوره جامع آموزش فرمولاسیون لوازم آرایشی
دوره جامع علم داده، یادگیری ماشین، یادگیری عمیق و NLP
دوره فوق فشرده مکالمه زبان انگلیسی (ویژه بزرگسالان)
شمع سازی و عودسازی با محوریت رایحه درمانی
صابون سازی (دستساز و صنعتی)
صفر تا صد طراحی دارو
متخصص طب سنتی و گیاهان دارویی
متخصص کنترل کیفی شرکت دارویی
Docker Compose Extends: استفاده مجدد و ارثبری از پیکربندیها
در دنیای توسعه نرمافزار مدرن، داکر کامپوز (Docker Compose) به ابزاری جداییناپذیر برای تعریف و اجرای برنامههای چند کانتینری تبدیل شده است. این ابزار به توسعهدهندگان و تیمهای DevOps امکان میدهد تا تمامی سرویسهای مورد نیاز یک برنامه را در یک فایل YAML واحد پیکربندی کرده و تنها با یک دستور آنها را راهاندازی کنند. اما با افزایش پیچیدگی پروژهها و نیاز به مدیریت پیکربندیهای مختلف برای محیطهای توسعه، تست و تولید، چالشهای جدیدی پدیدار میشود: چگونه میتوان از تکرار کد جلوگیری کرد و پیکربندیها را به صورت کارآمدتر مدیریت نمود؟ اینجاست که قابلیت extends در داکر کامپوز به نجات ما میآید.
extends یک ویژگی قدرتمند در داکر کامپوز است که به شما اجازه میدهد تا یک سرویس را از یک فایل کامپوز دیگر یا حتی از یک سرویس دیگر در همان فایل گسترش دهید. این قابلیت شبیه به وراثت در برنامهنویسی شیگرا عمل میکند؛ شما میتوانید یک پیکربندی پایه (base configuration) تعریف کنید و سپس پیکربندیهای خاصتر را بر اساس آن بسازید، تنها با اضافه کردن یا تغییر دادن آنچه که نیاز است. این نه تنها باعث کاهش تکرار کد میشود، بلکه مدیریت و نگهداری پیکربندیها را نیز بسیار سادهتر و خطاپذیری را کمتر میکند.
در این مقاله جامع و تخصصی، ما به بررسی عمیق ویژگی extends در Docker Compose خواهیم پرداخت. از مبانی و نحوه استفاده اولیه گرفته تا سناریوهای پیشرفته، بهترین شیوهها، مقایسه با روشهای جایگزین و نکات عیبیابی، هر آنچه را که برای تسلط بر این ابزار قدرتمند نیاز دارید، پوشش خواهیم داد. هدف ما ارائه یک راهنمای کامل و کاربردی برای جامعه تخصصی توسعهدهندگان و مهندسان DevOps است تا بتوانند از extends برای ساختن سیستمهای داکری منعطفتر، مقیاسپذیرتر و قابل نگهداریتر استفاده کنند.
چرا به Docker Compose Extends نیاز داریم؟ چالشهای تکرار پیکربندی
پیش از غواصی در جزئیات فنی extends، لازم است درک کنیم که این ویژگی چه مشکلاتی را حل میکند. در پروژههای واقعی، معمولاً با سناریوهای زیر مواجه میشویم:
- پیکربندیهای محیطی مختلف: یک برنامه ممکن است در محیط توسعه نیاز به پورتهای خاص، متغیرهای محیطی متفاوت یا نسخههای داکر ایمیج خاصی داشته باشد، در حالی که در محیط تولید به پورتهای دیگر، متغیرهای حساس و ایمیجهای بهینهشده نیاز دارد. مدیریت چندین فایل
docker-compose.yamlمجزا برای هر محیط میتواند به سرعت منجر به تکرار بخشهای عمدهای از پیکربندی شود. - سرویسهای مشترک بین پروژهها: بسیاری از پروژهها از سرویسهای پایهای مشابهی مانند دیتابیس (PostgreSQL, MySQL)، کشینگ (Redis) یا صف پیام (RabbitMQ) استفاده میکنند. اگر هر پروژه پیکربندی این سرویسها را از ابتدا بنویسد، زمان زیادی هدر رفته و نگهداری آنها دشوار میشود.
- تقسیم مسئولیتها در تیمهای بزرگ: در تیمهای بزرگ، ممکن است مسئولیت پیکربندی سرویسهای پایه بر عهده یک تیم (مثلاً تیم پلتفرم) باشد، در حالی که تیمهای توسعهدهنده برنامه تنها نیاز به استفاده و افزودن جزئیات مربوط به سرویسهای خود را دارند.
extendsاین جداسازی مسئولیتها را تسهیل میکند. - کاهش خطاهای انسانی: کپی-پیست کردن پیکربندیها نه تنها خستهکننده است، بلکه به طور بالقوه منجر به خطاهای انسانی میشود که شناسایی و رفع آنها میتواند پرهزینه باشد. با متمرکز کردن پیکربندیهای پایه، احتمال بروز این خطاها کاهش مییابد.
ویژگی extends به ما این امکان را میدهد که این چالشها را به طور مؤثری برطرف کنیم. با تعریف پیکربندیهای پایه و سپس ارثبری از آنها، میتوانیم یک منبع حقیقت واحد برای هر سرویس داشته باشیم و تنها تغییرات لازم را در هر محیط یا پروژه اعمال کنیم.
مبانی Docker Compose Extends: چگونه کار میکند؟
extends در داکر کامپوز به شما اجازه میدهد تا تعریف یک سرویس را از یک سرویس دیگر که در یک فایل کامپوز جداگانه (یا حتی در همان فایل) تعریف شده است، به ارث ببرید. وقتی از extends استفاده میکنید، کامپوز پیکربندی سرویس پایه را بارگذاری کرده و سپس تغییرات یا اضافات تعریف شده در سرویس گسترشیافته را بر روی آن اعمال میکند.
سینتکس پایه
سینتکس extends نسبتاً ساده است. شما باید دو چیز را مشخص کنید:
- مسیر فایل کامپوز پایه: با استفاده از کلید
file(اختیاری اگر سرویس پایه در همان فایل باشد). - نام سرویس پایه: با استفاده از کلید
service.
به عنوان مثال، فرض کنید ما یک فایل base-compose.yaml برای تعریف یک سرویس پایگاه داده داریم:
# base-compose.yaml
version: '3.8'
services:
db-base:
image: postgres:13
environment:
POSTGRES_DB: mydb
POSTGRES_USER: user
POSTGRES_PASSWORD: password
volumes:
- db_data:/var/lib/postgresql/data
networks:
- app-net
volumes:
db_data:
networks:
app-net:
حالا، در فایل docker-compose.yaml پروژه خود، میتوانیم این سرویس پایه را گسترش دهیم:
# docker-compose.yaml
version: '3.8'
services:
app-db:
extends:
file: ./base-compose.yaml
service: db-base
ports:
- "5432:5432" # اضافه کردن پورت برای دسترسی از هاست
environment:
# اورراید کردن یا افزودن متغیرهای محیطی
POSTGRES_HOST_AUTH_METHOD: trust
در این مثال:
- سرویس
app-dbپیکربندی خود را از سرویسdb-baseکه در فایلbase-compose.yamlتعریف شده، به ارث میبرد. - تمامی تنظیمات
image،environment(به جز آنچه اورراید شده)،volumesوnetworksازdb-baseبهapp-dbمنتقل میشوند. app-dbیک پورت جدید (5432:5432) اضافه میکند که درdb-baseوجود نداشت.app-dbمتغیر محیطیPOSTGRES_HOST_AUTH_METHODرا اضافه میکند. اگر متغیری با همین نام درdb-baseوجود داشت، مقدار جدید جایگزین مقدار قدیمی میشد.
قوانین ادغام (Merging Rules)
درک نحوه ادغام پیکربندیها بسیار مهم است:
- Mapping (دیکشنریها/اشیاء): اگر هر دو سرویس یک کلید از نوع mapping (مانند
environment،labels،portsو غیره) را تعریف کنند، مقادیر آنها به صورت بازگشتی ادغام میشوند. به این معنی که کلیدهای جدید اضافه میشوند و کلیدهای موجود در سرویس گسترشیافته، مقادیر کلیدهای متناظر در سرویس پایه را رونویسی میکنند. - List (آرایهها): برای لیستها (مانند
volumes،ports،expose،external_links،dnsوcap_add/cap_drop)، لیست سرویس گسترشیافته به انتهای لیست سرویس پایه اضافه میشود. این بدان معناست که شما نمیتوانید عناصر خاصی از لیست پایه را به طور مستقیم حذف کنید، بلکه میتوانید موارد جدیدی را اضافه کنید. (نکته: برایports، اگر پورتی در سرویس گسترش یافته با پورتی در سرویس پایه همپوشانی داشته باشد، پورت جدید جایگزین پورت پایه میشود). - Scalar (مقادیر ساده): برای کلیدهایی مانند
image،command،entrypointوcontainer_name، مقدار تعریف شده در سرویس گسترشیافته به طور کامل مقدار سرویس پایه را رونویسی میکند.
این قوانین ادغام باعث میشود که extends هم برای افزودن پیکربندیها و هم برای اورراید کردن آنها بسیار انعطافپذیر باشد.
سناریوهای پیشرفته استفاده از Docker Compose Extends
قابلیت extends زمانی قدرت واقعی خود را نشان میدهد که در سناریوهای پیچیدهتر به کار گرفته شود. در اینجا به برخی از رایجترین و مفیدترین الگوهای استفاده میپردازیم:
1. پیکربندی پایه مرکزی برای سرویسها
فرض کنید در سازمان شما، سرویسهای مشترکی مانند PostgreSQL، Redis، Nginx و غیره با پیکربندیهای استاندارد خاصی استفاده میشوند. میتوانید یک فایل کامپوز مرکزی (مثلاً common-services.yaml) ایجاد کنید که این سرویسهای پایه را تعریف میکند.
# common-services.yaml
version: '3.8'
services:
postgres-base:
image: postgres:14-alpine
environment:
POSTGRES_USER: admin
POSTGRES_PASSWORD: secretpassword
healthcheck:
test: ["CMD-SHELL", "pg_isready -U admin"]
interval: 5s
timeout: 5s
retries: 5
networks:
- backend
redis-base:
image: redis:6-alpine
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 5s
timeout: 3s
retries: 5
networks:
- backend
nginx-proxy-base:
image: nginx:latest
volumes:
- ./nginx/conf.d:/etc/nginx/conf.d:ro
networks:
- frontend
- backend
depends_on:
- some-app # placeholder, to be overridden
networks:
backend:
name: common_backend_net
frontend:
name: common_frontend_net
سپس، در فایل docker-compose.yaml هر پروژه، میتوانید این سرویسها را گسترش دهید و جزئیات خاص پروژه را اضافه کنید:
# project-a/docker-compose.yaml
version: '3.8'
services:
db:
extends:
file: ../common-services.yaml # فرض بر این است که common-services در یک سطح بالاتر است
service: postgres-base
environment:
POSTGRES_DB: project_a_db # اورراید نام دیتابیس
volumes:
- db_data_project_a:/var/lib/postgresql/data # افزودن ولوم اختصاصی
ports:
- "5432:5432" # تنها در محیط توسعه نیاز است
cache:
extends:
file: ../common-services.yaml
service: redis-base
command: redis-server --appendonly yes # افزودن کامند خاص
ports:
- "6379:6379"
web-app:
build: .
ports:
- "8000:8000"
environment:
DATABASE_URL: postgres://admin:secretpassword@db:5432/project_a_db
depends_on:
- db
- cache
networks:
- backend
volumes:
db_data_project_a:
networks:
backend:
name: project_a_backend_net # نام شبکه در پروژه خاص
این الگو به شما امکان میدهد تا یک منبع حقیقت واحد برای پیکربندیهای پایه داشته باشید و از تکرار کد جلوگیری کنید، در حالی که انعطافپذیری لازم برای سفارشیسازی هر پروژه را نیز حفظ میکنید.
2. مدیریت پیکربندیهای محیطی (توسعه، تست، تولید)
یکی از قویترین کاربردهای extends مدیریت آسان پیکربندیهای خاص محیط است. به جای داشتن چندین فایل کامپوز کاملاً مجزا (مانند docker-compose.dev.yaml، docker-compose.prod.yaml)، میتوانید یک فایل پایه داشته باشید و فایلهای محیطی را برای اورراید کردن مقادیر خاص ایجاد کنید.
# docker-compose.base.yaml (پیکربندی پایه)
version: '3.8'
services:
web:
image: myapp:latest # در تولید این ایمیج استفاده شود
build:
context: .
dockerfile: Dockerfile # در توسعه ممکن است نیاز به build داشته باشیم
environment:
APP_ENV: production
DATABASE_HOST: production-db
volumes:
- app_data:/app/data
networks:
- app-net
db:
image: postgres:13-alpine
environment:
POSTGRES_DB: production_db
POSTGRES_USER: prod_user
POSTGRES_PASSWORD: prod_password
volumes:
- prod_db_data:/var/lib/postgresql/data
networks:
- app-net
networks:
app-net:
volumes:
app_data:
prod_db_data:
# docker-compose.dev.yaml (اوررایدهای محیط توسعه)
version: '3.8'
services:
web:
extends:
file: docker-compose.base.yaml
service: web
image: myapp:dev # استفاده از ایمیج توسعه
build:
context: . # حتما باید بیلد شود
ports:
- "80:80"
- "443:443"
environment:
APP_ENV: development
DATABASE_HOST: dev-db # اشاره به دیتابیس توسعه
volumes:
- ./src:/app/src:cached # ماونت کد منبع برای توسعه
# build is now the default behavior because it is defined in dev, overriding image from base
db:
extends:
file: docker-compose.base.yaml
service: db
image: postgres:13 # شاید در dev از یک نسخه کاملتر استفاده کنیم
ports:
- "5432:5432" # برای دسترسی مستقیم در توسعه
environment:
POSTGRES_DB: dev_db
POSTGRES_USER: dev_user
POSTGRES_PASSWORD: dev_password
volumes:
- dev_db_data:/var/lib/postgresql/data
volumes:
dev_db_data: # ولوم جداگانه برای dev
برای اجرای محیط توسعه، کافیست دستور زیر را اجرا کنید:
docker compose -f docker-compose.base.yaml -f docker-compose.dev.yaml up
این روش استفاده از چندین فایل کامپوز (که extends را درون خود استفاده میکنند) بسیار قدرتمند است. فایل docker-compose.base.yaml حاوی تمام تنظیمات مشترک است و فایل docker-compose.dev.yaml (یا docker-compose.prod.yaml) تنها تغییرات و اضافات مخصوص آن محیط را شامل میشود. این رویکرد را میتوان با استفاده از متغیرهای محیطی نیز ترکیب کرد تا فایلهای کامپوز حتی منعطفتر شوند.
3. ارثبری زنجیرهای (Chaining Extends)
یکی دیگر از ویژگیهای قدرتمند extends، قابلیت ارثبری زنجیرهای است. این بدان معناست که یک سرویس میتواند از سرویسی ارث ببرد که خود آن سرویس نیز از سرویس دیگری ارث برده است. این قابلیت به شما امکان میدهد تا سلسله مراتب پیچیدهای از پیکربندیها را ایجاد کنید.
# docker-compose.tier0.yaml (پایهترین پیکربندی)
version: '3.8'
services:
app-base:
image: ubuntu:latest
command: /bin/bash -c "while true; do echo Hello from base; sleep 1; done"
environment:
BASE_VAR: "Hello"
networks:
- base-net
networks:
base-net:
# docker-compose.tier1.yaml (گسترش از tier0)
version: '3.8'
services:
web-app-base:
extends:
file: docker-compose.tier0.yaml
service: app-base
image: my-web-app:1.0 # اورراید image
environment:
TIER1_VAR: "World"
BASE_VAR: "Goodbye" # اورراید BASE_VAR
ports:
- "8080:80"
api-app-base:
extends:
file: docker-compose.tier0.yaml
service: app-base
image: my-api-app:1.0
environment:
TIER1_VAR: "API"
BASE_VAR: "API Base"
ports:
- "8000:8000"
# docker-compose.project.yaml (گسترش از tier1)
version: '3.8'
services:
project-web:
extends:
file: docker-compose.tier1.yaml
service: web-app-base
environment:
PROJECT_VAR: "Project A Web"
TIER1_VAR: "Project A Web Override" # اورراید TIER1_VAR
volumes:
- ./web-code:/app/code
project-api:
extends:
file: docker-compose.tier1.yaml
service: api-app-base
environment:
PROJECT_VAR: "Project A API"
ports:
- "8001:8000" # اورراید پورت
volumes:
- ./api-code:/app/api
در این سناریو:
app-baseدرtier0پایه را تعریف میکند.web-app-baseوapi-app-baseدرtier1ازapp-baseارث میبرند و تغییرات خاص خود را اعمال میکنند.project-webوproject-apiدرprojectاز سرویسهایtier1ارث میبرند و سفارشیسازیهای نهایی را انجام میدهند.
این روش به خصوص برای ساخت پلتفرمهای داخلی یا استانداردسازی سرویسها در یک سازمان بزرگ بسیار مفید است، جایی که هر سطح از ارثبری مسئولیتهای متفاوتی در پیکربندی دارد.
4. استفاده از extends برای تنها بخشی از پیکربندی (Partial Extension)
در برخی موارد، ممکن است نیاز باشد که تنها یک بخش خاص از پیکربندی یک سرویس را به ارث ببرید. داکر کامپوز extends به صورت سرویس-محور کار میکند، اما شما میتوانید با تعریف سرویسهای کوچک و تخصصی در فایل پایه، این کار را شبیهسازی کنید.
# common-configs.yaml
version: '3.8'
services:
default-logging:
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
default-network:
networks:
- app-network
networks:
app-network:
# docker-compose.yaml
version: '3.8'
services:
my-app:
image: my-app:latest
extends:
file: common-configs.yaml
service: default-logging # به ارث بردن تنظیمات لاگینگ
ports:
- "80:80"
environment:
APP_CONFIG: production
networks:
- app-network # نیاز است network را هم جداگانه تعریف کنیم
توجه داشته باشید که در مثال بالا، سرویس my-app از default-logging ارث میبرد. اما این به این معنی نیست که تنها بخش logging را به ارث میبرد. بلکه تمام پیکربندی default-logging (که در اینجا فقط logging است) به my-app اضافه میشود. اگر default-logging شامل image یا command بود، آنها نیز به my-app اعمال میشدند. برای اعمال شبکه نیز میتوانیم یا آن را مستقیماً در my-app اضافه کنیم یا یک سرویس دیگر در common-configs.yaml برای آن تعریف کنیم و با استفاده از دستور docker compose -f آن را با هم ادغام کنیم.
این مثال نشان میدهد که extends بر اساس سرویسها عمل میکند، نه بخشهای کوچک پیکربندی. برای ترکیب دقیقتر بخشهای کوچک، استفاده از قابلیت چند فایل docker compose -f و متغیرهای محیطی میتواند گزینههای بهتری باشد.
مقایسه Extends با سایر روشهای استفاده مجدد
در داکر کامپوز، چندین راه برای استفاده مجدد و مدیریت پیکربندیها وجود دارد. درک تفاوتها و مزایا و معایب هر روش برای انتخاب بهترین ابزار برای هر سناریو حیاتی است.
1. متغیرهای محیطی (Environment Variables)
متغیرهای محیطی یکی از رایجترین روشها برای پویاسازی پیکربندیها در داکر کامپوز هستند. شما میتوانید مقادیر را در فایل .env تعریف کنید و سپس در فایل docker-compose.yaml از آنها استفاده کنید.
# .env
POSTGRES_VERSION=13
APP_PORT=8080
# docker-compose.yaml
version: '3.8'
services:
db:
image: postgres:${POSTGRES_VERSION}
environment:
POSTGRES_DB: ${DB_NAME:-mydb} # مقدار پیشفرض در صورت عدم تعریف DB_NAME
ports:
- "${APP_PORT}:80"
مزایا:
- سادگی: بسیار آسان برای استفاده و درک.
- انعطافپذیری: امکان تغییر مقادیر بدون تغییر فایل کامپوز.
- پویاسازی: ایدهآل برای مقادیر کوچک و متغیر (مانند پورتها، نام دیتابیس، پسوردها).
معایب:
- عدم قابلیت ارثبری ساختار: نمیتواند ساختارهای پیچیده YAML (مانند کلیدهای nested) را به ارث ببرد یا اضافه کند. فقط جایگزین مقادیر Scalar میشود.
- پیچیدگی برای پیکربندیهای بزرگ: برای تغییر بخشهای بزرگتر پیکربندی (مانند افزودن یک ولوم یا شبکه) نامناسب است.
- خطاپذیری: اگر متغیری تعریف نشده باشد و مقدار پیشفرض نداشته باشد، ممکن است با خطا مواجه شوید.
نتیجهگیری: متغیرهای محیطی برای مقادیر متغیر و کوچک عالی هستند، اما برای به اشتراکگذاری یا ارثبری ساختارهای بزرگتر پیکربندی ناکافیاند. extends برای این منظور مناسبتر است.
2. انکرهای YAML (YAML Anchors)
انکرهای YAML به شما اجازه میدهند تا بخشی از یک فایل YAML را “لنگر” (anchor) کنید و سپس در جاهای دیگر همان فایل به آن “رجوع” (alias) کنید. این برای جلوگیری از تکرار در یک فایل مفید است.
# docker-compose.yaml
version: '3.8'
x-common-labels: &common-labels
labels:
env: development
project: myapp
services:
web:
image: myapp:latest
<<: *common-labels # استفاده از انکر
ports:
- "80:80"
api:
image: myapi:latest
<<: *common-labels # استفاده از انکر
ports:
- "8000:8000"
مزایا:
- کاهش تکرار: کد DRY (Don't Repeat Yourself) را در یک فایل YAML پیادهسازی میکند.
- خوانایی: میتواند خوانایی فایلهای کامپوز طولانی را بهبود بخشد.
معایب:
- محدود به یک فایل: نمیتوانید از انکرهای تعریف شده در یک فایل YAML در فایل YAML دیگری استفاده کنید. این بزرگترین محدودیت آن است.
- عدم قابلیت اورراید آسان: اورراید کردن مقادیر جزئی از یک انکر میتواند پیچیده باشد.
- محدودیتهای ادغام: رفتارش در ادغام لیستها یا دیکشنریها ممکن است کمتر بصری باشد.
نتیجهگیری: انکرهای YAML برای استفاده مجدد در داخل یک فایل واحد مفید هستند، اما برای به اشتراکگذاری پیکربندیها بین فایلها یا پروژههای مختلف مناسب نیستند. extends در این زمینه بسیار تواناتر است.
3. استفاده از چند فایل کامپوز (Multiple Compose Files)
این روش شامل استفاده از چندین فایل docker-compose.yaml است که با دستور docker compose -f file1.yaml -f file2.yaml up با هم ادغام میشوند. داکر کامپوز به طور هوشمندانه پیکربندیهای سرویسها را از همه فایلها ادغام میکند. این روش مکمل extends است.
# docker-compose.base.yaml
version: '3.8'
services:
web:
image: myapp:latest
networks:
- app-net
db:
image: postgres:13
networks:
- app-net
networks:
app-net:
# docker-compose.dev.yaml
version: '3.8'
services:
web:
build: .
ports:
- "80:80"
volumes:
- ./src:/app/src
environment:
APP_ENV: development
db:
ports:
- "5432:5432"
environment:
POSTGRES_DB: dev_db
برای اجرای محیط توسعه:
docker compose -f docker-compose.base.yaml -f docker-compose.dev.yaml up
مزایا:
- سازماندهی عالی: امکان جداسازی پیکربندیهای پایه از پیکربندیهای خاص محیط.
- ادغام قدرتمند: داکر کامپوز به طور خودکار سرویسها را با نام مشابه در فایلهای مختلف ادغام میکند. این ادغام از قوانین مشابه
extendsپیروی میکند. - انعطافپذیری: میتوان فایلهای مختلف را بسته به نیاز به صورت پویا ترکیب کرد.
معایب:
- عدم وراثت سرویس به سرویس: این روش سرویسهای کاملاً جداگانه را ادغام میکند. شما نمیتوانید یک سرویس را در یک فایل از سرویس دیگری در همان فایل (یا فایل دیگر) که نامش یکسان نیست، به ارث ببرید.
extendsبه شما اجازه میدهد که سرویسmy-dbرا ازbase-dbارث ببرید.
نتیجهگیری: استفاده از چندین فایل کامپوز یک روش قدرتمند و بسیار توصیه شده برای مدیریت پیکربندیها است. extends با این روش همافزایی دارد. شما میتوانید یک فایل پایه را با استفاده از extends به صورت داخلی ساختاربندی کنید و سپس از چندین فایل برای اوررایدهای محیطی استفاده کنید. این ترکیب بهترین هر دو جهان را ارائه میدهد.
به طور خلاصه، در حالی که متغیرهای محیطی برای مقادیر کوچک و متغیر و انکرهای YAML برای استفاده مجدد در یک فایل واحد مناسب هستند، extends و استفاده از چندین فایل کامپوز ابزارهای اصلی برای مدیریت استفاده مجدد و ارثبری پیکربندیهای پیچیدهتر در پروژههای داکر کامپوز هستند. extends برای ارثبری سرویس-به-سرویس و چندین فایل برای ترکیب پیکربندیهای مختلف محیطی به کار میروند.
محدودیتها و نکات عیبیابی در استفاده از Extends
با وجود قدرت بالای extends، آگاهی از محدودیتها و چالشهای احتمالی آن برای استفاده مؤثر و جلوگیری از سردرگمی ضروری است.
1. محدودیتهای نامگذاری سرویسها
هنگام استفاده از extends، نام سرویسی که گسترش داده میشود (سرویس "فرزند") میتواند با نام سرویس پایه (سرویس "والد") متفاوت باشد. این یک مزیت بزرگ است، زیرا شما میتوانید یک سرویس پایه عمومی داشته باشید و سپس آن را در پروژههای مختلف با نامهای خاص خود استفاده کنید. اما این میتواند باعث سردرگمی شود اگر به وضوح ندانید کدام سرویس از کجا ارث میبرد.
نکته: همیشه سعی کنید نامگذاری سرویسها را واضح نگه دارید و از کامنتها برای توضیح سلسله مراتب ارثبری استفاده کنید.
2. عدم امکان حذف یا جایگزینی کامل عناصر لیست
همانطور که قبلاً ذکر شد، لیستها (مانند volumes، ports، expose، networks در سطح سرویس) به صورت ادغامشده عمل میکنند؛ یعنی عناصر جدید به لیست پایه اضافه میشوند. شما نمیتوانید به راحتی یک آیتم خاص را از لیست پایه حذف کنید یا آن را با یک لیست کاملاً جدید جایگزین کنید (مگر در موارد خاص مثل پورتها که اگر دقیقا یکسان باشند، جایگزین میشوند). این میتواند یک محدودیت باشد اگر بخواهید پیکربندی لیست را به طور کامل در سرویس فرزند بازنویسی کنید.
راهحل (Workaround): اگر نیاز به جایگزینی کامل یک لیست دارید، باید تمام عناصر لیست جدید را در سرویس فرزند تعریف کنید و از یک لیست خالی در سرویس پایه استفاده کنید (یا آن را تعریف نکنید) اگر میخواهید کاملاً کنترل را به فرزند بدهید. این یک "hack" است و ایدهآل نیست، اما برای سناریوهای خاص کارساز است. راه حل بهتر این است که از قابلیت چند فایل docker compose -f استفاده کنید که در آن یک سرویس در یک فایل کاملاً سرویس دیگری با همان نام را در فایل قبلی رونویسی میکند (به جز مواردی که قوانین ادغام apply میشوند).
3. پیچیدگی مسیردهی فایل (File Path Resolution)
هنگامی که از extends.file استفاده میکنید، مسیر فایل پایه (که سرویس از آن گسترش مییابد) میتواند نسبی یا مطلق باشد.
- مسیرهای نسبی: همیشه نسبت به فایل کامپوزی که حاوی دستور
extendsاست، حل میشوند. این رایجترین و توصیه شدهترین روش است. - مسیرهای مطلق: ممکن است در محیطهای مختلف به مشکلات مسیردهی منجر شوند، به خصوص اگر فایلهای کامپوز در ساختارهای دایرکتوری متفاوتی قرار گیرند.
نکته: همیشه از مسیرهای نسبی استفاده کنید مگر اینکه دلیل محکمی برای استفاده از مسیرهای مطلق داشته باشید و از سازگاری آنها در محیطهای مختلف اطمینان داشته باشید.
4. مسائل مربوط به Build Context
اگر سرویس پایه دارای build context باشد و سرویس فرزند نیز build context خود را تعریف کند، سرویس فرزند این مقدار را اورراید خواهد کرد. مشکل از آنجا ناشی میشود که build context همیشه نسبت به فایل کامپوزی که در آن build تعریف شده است، حل میشود. اگر فایلهای پایه و فرزند در دایرکتوریهای مختلفی قرار داشته باشند، ممکن است build context به درستی ارزیابی نشود.
نکته: در مورد build، بهتر است build context و Dockerfile را در همان فایل کامپوز (یا فایل محیطی) که واقعاً نیاز به ساخت ایمیج دارد، تعریف کنید و از ارثبری build context از طریق extends خودداری کنید یا حداقل با دقت آن را مدیریت کنید.
5. اشکالزدایی (Debugging) پیکربندیهای extends شده
وقتی از چندین سطح extends استفاده میکنید، میتواند دشوار باشد که دقیقاً بفهمید پیکربندی نهایی یک سرویس چگونه خواهد بود. قوانین ادغام ممکن است همیشه واضح نباشند، به خصوص برای کاربران جدید.
نکته: برای اشکالزدایی، میتوانید از دستور docker compose config استفاده کنید. این دستور خروجی نهایی و ادغامشده پیکربندی را نشان میدهد و به شما کمک میکند تا بررسی کنید که آیا extends به درستی عمل کرده است یا خیر.
docker compose -f docker-compose.project.yaml config
این دستور تمام فایلهای کامپوز را (از جمله آنهایی که از طریق extends.file ارجاع داده شدهاند) بارگذاری و ادغام میکند و پیکربندی نهایی را نمایش میدهد. این یک ابزار بسیار ارزشمند برای تأیید رفتار extends است.
6. عدم امکان Extends کردن کلیدهای سطح بالا (Top-Level Keys)
extends فقط میتواند برای سرویسها (services) استفاده شود. شما نمیتوانید کلیدهای سطح بالا مانند volumes، networks یا configs را از یک فایل دیگر به صورت مستقیم extends کنید. این کلیدها باید به صورت جداگانه در هر فایل کامپوز تعریف شوند یا با استفاده از قابلیت چندین فایل docker compose -f ادغام شوند.
نکته: برای اشتراکگذاری volumes و networks بین فایلها، بهتر است از نامگذاری صریح و یکسان در تمام فایلها استفاده کنید و داکر کامپوز به طور خودکار آنها را با هم مرتبط میکند. برای شبکهها، میتوانید از شبکههای خارجی (external: true) برای ارجاع به شبکههایی که از قبل وجود دارند استفاده کنید.
بهترین شیوهها برای استفاده مؤثر از Docker Compose Extends
برای بهرهبرداری حداکثری از extends و جلوگیری از مشکلات رایج، رعایت چند بهترین شیوه میتواند بسیار مفید باشد.
1. ساختاردهی منطقی فایلها
- فایلهای پایه مجزا: پیکربندیهای پایه (مثل دیتابیس، کش، وبسرور عمومی) را در فایلهای کامپوز جداگانه نگهداری کنید. مثلاً
docker-compose.db.yaml،docker-compose.redis.yamlیا یکcommon-services.yaml. - فایلهای محیطی: از فایلهای کامپوز جداگانه برای هر محیط (
docker-compose.dev.yaml،docker-compose.prod.yaml) استفاده کنید که پیکربندیهای پایه را گسترش داده و اورراید میکنند. - فایل پروژه اصلی: فایل
docker-compose.yamlاصلی پروژه باید به عنوان نقطه ورود عمل کند و یا ازextendsبه صورت داخلی استفاده کند یا با سایر فایلهای محیطی ترکیب شود.
2. استفاده از نامگذاری واضح و مختصر
- نام سرویسهای پایه باید واضح باشد (مثلاً
postgres-base،web-app-template). - نام سرویسهای گسترشیافته باید نشاندهنده نقش آنها در پروژه باشد (مثلاً
db،web-app).
3. مستندسازی دقیق
پیچیدگی میتواند به سرعت افزایش یابد، به خصوص با ارثبری زنجیرهای. حتماً فایلهای کامپوز خود را با کامنتها و مستندات مناسب نگهداری کنید تا تیم شما بتواند به راحتی ساختار ارثبری و اوررایدها را درک کند.
4. مدیریت متغیرهای محیطی و فایل .env
متغیرهای محیطی و فایل .env هنوز هم ابزارهای قدرتمندی برای مدیریت مقادیر حساس یا متغیر هستند. extends را با .env ترکیب کنید: از extends برای ارثبری ساختارها و از .env برای پر کردن مقادیر متغیر استفاده کنید.
5. آزمایش و اعتبارسنجی مداوم
همانطور که قبلاً ذکر شد، از docker compose config به طور منظم برای بررسی پیکربندی نهایی استفاده کنید، به خصوص پس از ایجاد تغییرات بزرگ یا اضافه کردن سطوح جدید ارثبری. این کار به شما کمک میکند تا هرگونه مشکل ادغام یا اورراید ناخواسته را به سرعت شناسایی کنید.
6. اجتناب از ارثبری بیش از حد پیچیده
در حالی که extends از ارثبری زنجیرهای پشتیبانی میکند، مراقب باشید که سلسله مراتب را بیش از حد عمیق نکنید. داشتن سه تا چهار سطح ارثبری ممکن است قابل مدیریت باشد، اما بیشتر از آن میتواند به سرعت باعث سردرگمی و دشواری در اشکالزدایی شود. سادگی را در اولویت قرار دهید.
7. استفاده از شبکههای خارجی (External Networks)
برای شبکهها، به جای تلاش برای ارثبری پیچیده از طریق extends (که برای کلیدهای سطح بالا کار نمیکند)، از شبکههای خارجی استفاده کنید. این به شما امکان میدهد شبکهها را یک بار تعریف کرده و سپس در چندین فایل کامپوز به آنها ارجاع دهید.
# docker-compose.yaml
version: '3.8'
services:
my-app:
image: my-app:latest
networks:
- my-shared-network # اتصال به شبکه مشترک
networks:
my-shared-network:
external: true # به یک شبکه که قبلاً ایجاد شده ارجاع میدهد
شما باید این شبکه را قبلاً با docker network create my-shared-network ایجاد کرده باشید.
نتیجهگیری: Extends، ابزاری قدرتمند برای مدیریت پیکربندیهای داکر کامپوز
قابلیت extends در داکر کامپوز یک ویژگی ضروری برای هر تیم توسعهدهنده یا مهندس DevOps است که با پروژههای چند کانتینری در مقیاس بزرگ کار میکند. این ابزار با فراهم کردن مکانیزمی قدرتمند برای استفاده مجدد و ارثبری از پیکربندیهای سرویس، به طور چشمگیری به کاهش تکرار کد، بهبود قابلیت نگهداری و افزایش خوانایی فایلهای کامپوز کمک میکند.
از مدیریت پیکربندیهای محیطی مختلف (توسعه، تست، تولید) گرفته تا اشتراکگذاری سرویسهای پایه در چندین پروژه و ایجاد سلسله مراتب پیچیده از پیکربندیها، extends انعطافپذیری بینظیری را ارائه میدهد. با این حال، همانند هر ابزار قدرتمندی، درک عمیق از نحوه کار، محدودیتها و بهترین شیوههای آن برای جلوگیری از مشکلات و بهرهبرداری کامل از پتانسیل آن حیاتی است.
با ترکیب extends با سایر ویژگیهای داکر کامپوز مانند متغیرهای محیطی و استفاده از چندین فایل کامپوز، میتوانید یک استراتژی مدیریت پیکربندی جامع و قوی ایجاد کنید که به شما کمک میکند تا برنامههای کانتینری خود را با کارایی بیشتر و خطای کمتر توسعه و استقرار دهید.
با تمرین و پیادهسازی الگوهای ارائه شده در این مقاله، شما میتوانید به یک متخصص در استفاده از extends تبدیل شوید و فرآیندهای توسعه و استقرار خود را به سطح جدیدی ارتقا دهید. از این ابزار هوشمندانه استفاده کنید تا زمان کمتری را صرف مدیریت پیکربندیها کنید و زمان بیشتری را به نوآوری و توسعه قابلیتهای اصلی برنامه خود اختصاص دهید.
“تسلط به برنامهنویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT”
"تسلط به برنامهنویسی پایتون با هوش مصنوعی: آموزش کدنویسی هوشمند با ChatGPT"
"با شرکت در این دوره جامع و کاربردی، به راحتی مهارتهای برنامهنویسی پایتون را از سطح مبتدی تا پیشرفته با کمک هوش مصنوعی ChatGPT بیاموزید. این دوره، با بیش از 6 ساعت محتوای آموزشی، شما را قادر میسازد تا به سرعت الگوریتمهای پیچیده را درک کرده و اپلیکیشنهای هوشمند ایجاد کنید. مناسب برای تمامی سطوح با زیرنویس فارسی حرفهای و امکان دانلود و تماشای آنلاین."
ویژگیهای کلیدی:
بدون نیاز به تجربه قبلی برنامهنویسی
زیرنویس فارسی با ترجمه حرفهای
۳۰ ٪ تخفیف ویژه برای دانشجویان و دانش آموزان