با استفاده از YAML، دستورالعملهای سرویسهای مختلف را نوشته و با یک دستور همهی آنها را با هم اجرا مینماییم. از compose در تمامی مراحل production, staging, development, testing و همچنین CI workflow استفاده میشود.
برای استفاده از compose سه عمل زیر باید انجام شود:
1- ساخت و تعریف dockerfile برای هر سرویس.
2- ساخت و تعریف docker-compose.yml. بنابراین هر سرویس میتواند در محیط ایزولهی خود اجرا شود.
3- اجرای دستور docker-compose up.
در قسمتهای قبلی مراحل ساخت و اجرای imageها درون کانتینر و همچنین متصل کردن آنها را به شبکه، بررسی کرده ایم؛ اما در این قسمت میخواهیم با استفاده از docker-compose مدیریت build و اجرای همهی imageها را بر عهده بگیریم.
عملا با این ساختار، قابلیت ایجاد شبکه، volume و غیره را خواهیم داشت. بنابراین با استفاده از این config توانایی توزیع برنامه را فقط با یک فایل YAML، خواهیم داشت.
ایجاد پروژه:
فرض کنید نرم افزار ما از دو سرویس Nodejsی همچنین یک دیتابیس Mongo تشکیل شده است. در نهایت باید به چیزی شبیه به تصویر زیر برسیم:
دایرکتوری root این پروژه از دو پوشه به نامهای nodeapp1 و nodeapp2 تشکیل شده است که داخل هر کدام یک فایل index.js و همچنین package.json و dockerfile وجود دارد؛ همانند مطالب پیشین.
اما چیزی که اینجا اضافه شده است، فایل docker-compose.yml جهت مدیریت و اجرای این برنامه میباشد که حاوی ساختار زیر است:
version: '3' networks: shared-network: services: nodeapp1: image: nodeapp1 build: context: nodeapp1 dockerfile: dockerfile ports: - "8181:80" networks: - shared-network nodeapp2: image: nodeapp2 build: context: nodeapp2 dockerfile: dockerfile ports: - "8182:80" networks: - shared-network mongo: image: mongo ports: - "27017:27017" networks: - shared-network
2) برای مشخص کردن سرویسهای این برنامه از services استفاده کرده و آنها را تعریف مینماییم.
3) سرویس nodeapp1 که قرار است تصویری به نام nodeapp1 را ایجاد کند (هدف آن build کردن اولین سرویس میباشد. همانطور که مشخص است context برنامه، اسم پوشهی nodeapp1 درون ریشهی پروژه است. ضمن اینکه نام dockerfile را هم درون آن پوشه بدان اضافه کردهایم).
4) پورت 8181 را بر روی پورت 80 درون این کانتینر هدایت میکنیم.
5) این سرویس، درون شبکهی ایجاد شدهی shared-network قرار میگیرد.
5) سرویس nodeapp2 را هم به همین شکل اضافه میکنیم.
6) سرویس mongo قرار نیست هیچ کدی را build کند و هدف، فقط اجرای mongo درون شبکهی shared-network است که بقیه سرویسها بتوانند بدان وصل شوند.
برای ساخت و اجرا نیز در ریشهی این پروژه، ترمینال خود را باز کرده و دستورات زیر را وارد مینماییم:
برای build کردن:
docker-compose build
docker-compose up
docker-compose down
docker-compose stop
docker-compose start
و اگر بخواهیم بعد از build کردن، بصورت خودکار نیز اجرا شود، از دستور زیر استفاده میکنیم:
docker-compose run --build
dockerfile هر دو سرویس نیز بصورت ساده همانند مطالب پیشین در نظر گرفته شدهاست:
FROM node COPY . /var/www WORKDIR /var/www RUN npm i EXPOSE 80 ENTRYPOINT node index
در صورتیکه بخواهیم نگاهی هم به کدهای نوشته شده بیندازیم، نکتهی جالبی مد نظر قرار میگیرد؛ بطور مثال از آنجائیکه همهی کانتینرهای اجرا شده، درون یک شبکه هستند، برای فراخوانی سرویسهای دیگر کافیست با نامشان صدا زده شوند. بطور مثال در nodeapp1 برای فراخوانی nodeapp2 به راحتی با نام صدا زده شده است و احتیاجی به فراخوانی با ip نیست. کدهای زیر مربوط به فایل index.js در سرویس nodeapp1 میباشند (بدلیل اینکه روی پورت 80 درون کانتینر قرار گرفتهاست، دیگر لازم به وارد نمودن پورت نبودیم؛ در غیر اینصورت بطور مثال باید درخواستی بصورت http://nodeapp2:5000 را ارسال مینمودیم):
const express = require('express'); const fetch = require('node-fetch'); const app = express(); app.get('/', async (req, res) => { let response = await fetch("http://nodeapp2/"); text = await response.text(); res.send(text); }) app.listen(80, () => console.log(`listening on port 80!`))
نکته: override کردن composeها نیز قابل انجام است. بدین معنا که شما یک نسخه برای build و استفاده در محیط development و نسخههای دیگری بطور مثال برای production خود تعریف مینمایید؛ مثلا روی پروداکشن، environment variablesهای متفاوتی را در نظر میگیرید. YAML زیر را مشاهده کنید:
version: '3' services: nodeapp1: environment: - PRODUCTION: 'true' nodeapp2: environment: - PRODUCTION: 'true'
فرض کنید که قرار است YAML فوق بر روی فایل قبلی، بازنویسی شود؛ با استفاده از دستور زیر:
docker-compose -f docker-compose.yml -f docker-compose.prod.yml up
تمام کدهای فوق از اینجا «node.rar» قابل دریافت میباشد.