چرا داکر برای توسعهدهندگان وب ضروری است؟
اگر تا به حال جمله «روی سیستم من کار میکند» را شنیده یا گفتهاید، دقیقاً با مشکلی مواجه بودهاید که داکر (Docker) برای حل آن ساخته شده است. داکر به شما اجازه میدهد نرمافزار را همراه با تمام وابستگیهایش — کتابخانهها، نسخه زبان برنامهنویسی، متغیرهای محیطی و حتی سیستمعامل پایه — در بستهای به نام ایمیج (Image) بستهبندی کنید. سپس این ایمیج را بهصورت یک کانتینر (Container) اجرا میکنید که در هر محیطی، از لپتاپ شخصی تا سرور ابری، رفتاری یکسان دارد.
برای توسعهدهندگان وب، این یعنی پایان دردسر نصب و پیکربندی MySQL، PHP، Nginx یا Node.js روی سیستمعاملهای مختلف. بهجای نصب مستقیم، فقط یک فایل docker-compose.yml مینویسید و با یک دستور، کل زیرساخت برنامه بالا میآید. در این مقاله، با یک مثال واقعی از یک اپلیکیشن PHP، مفاهیم اصلی داکر را از صفر یاد میگیرید: ساخت ایمیج با Dockerfile، اجرای کانتینر، مدیریت دادهها با ولوم (Volume) و در نهایت orchestration سبک با Docker Compose.
پیشنیازها و نصب داکر
فرض میکنیم با مفاهیم پایه لینوکس و خط فرمان آشنا هستید. برای نصب، به مستندات رسمی داکر مراجعه کنید. روی ویندوز و macOS، داکر دسکتاپ (Docker Desktop) را نصب کنید؛ روی لینوکس، بسته داکر انجین (Docker Engine) را. بعد از نصب، صحت نصب را با دستور زیر بررسی کنید:
docker --version
docker run hello-world
دستور دوم یک کانتینر آزمایشی اجرا میکند و اگر همهچیز درست باشد، پیام خوشآمدگویی چاپ میشود.
مفهوم ایمیج در برابر کانتینر
یک ایمیج را مانند یک قالب یا snapshot تصور کنید: فقطخواندنی است و شامل سیستمعامل پایه، کد برنامه و تنظیمات است. یک کانتینر نمونهای در حال اجرا از آن ایمیج است که لایه قابلنوشتنی خودش را دارد. میتوانید از یک ایمیج، چند کانتینر مجزا اجرا کنید؛ مثل اینکه از یک قالب، چند کیک یکسان بپزید.
ساخت اولین Dockerfile برای اپ PHP
بیایید یک اپلیکیشن ساده PHP با یک صفحه خوشآمد و اتصال به MySQL بسازیم. ابتدا ساختار پروژه را ایجاد کنید:
my-php-app/
├── src/
│ └── index.php
├── Dockerfile
└── docker-compose.yml
محتوای src/index.php را اینطور مینویسیم:
<?php
$host = getenv('DB_HOST') ?: 'db';
$user = getenv('DB_USER') ?: 'root';
$pass = getenv('DB_PASS') ?: 'secret';
$db = getenv('DB_NAME') ?: 'app_db';
try {
$pdo = new PDO("mysql:host=$host;dbname=$db;charset=utf8mb4", $user, $pass);
$stmt = $pdo->query("SELECT 'Connected to MySQL successfully!' AS message");
echo "<h1>" . $stmt->fetch()['message'] . "</h1>";
} catch (PDOException $e) {
http_response_code(500);
echo "<h1>DB Connection Failed: </h1>" . htmlspecialchars($e->getMessage());
}
حالا فایل Dockerfile را میسازیم. این فایل دستورالعمل ساخت ایمیج است:
# استفاده از ایمیج رسمی PHP با FPM و mysqli
FROM php:8.3-fpm
# نصب افزونههای لازم
RUN docker-php-ext-install pdo_mysql mysqli
# کپی کد برنامه به داخل کانتینر
COPY src/ /var/www/html/
# تعیین پوشه کاری
WORKDIR /var/www/html
# کاربر غیر ریشه برای امنیت بیشتر
RUN useradd -m appuser && chown -R appuser:appuser /var/www/html
USER appuser
# پورت پیشفرض FPM
EXPOSE 9000
هر خط از Dockerfile یک لایه (Layer) در ایمیج ایجاد میکند. داکر این لایهها را کش میکند؛ پس ترتیب دستورات مهم است. دستوراتی که کمتر تغییر میکنند (مثل نصب افزونه) را بالاتر ببرید تا در ساختهای بعدی زمان کمتری صرف شود.
دستورات پرکاربرد Dockerfile
FROM: ایمیج پایه را مشخص میکند. همیشه از نسخههای رسمی و مشخص استفاده کنید، نهlatest.RUN: دستوری که هنگام ساخت ایمیج اجرا میشود (مثل نصب پکیج).COPY: فایلها را از سیستم میزبان به داخل ایمیج کپی میکند.WORKDIR: پوشه پیشفرض برای دستورات بعدی.EXPOSE: فقط مستندسازی پورت است؛ پورت را واقعاً باز نمیکند.CMDیاENTRYPOINT: دستور پیشفرض هنگام اجرای کانتینر.
اجرای کانتینر و مدیریت ولومها
برای ساخت ایمیج از Dockerfile و اجرای کانتینر، دستورات زیر را اجرا کنید:
# ساخت ایمیج با نام my-php-app و تگ v1
docker build -t my-php-app:v1 .
# اجرای کانتینر در پسزمینه
docker run -d --name my-app -p 8080:80 my-php-app:v1
با -p 8080:80 پورت 8080 سیستم میزبان را به پورت 80 کانتینر نگاشت میکنید. حالا در مرورگر http://localhost:8080 را باز کنید.
ولومها؛ ذخیرهسازی دادهها
کانتینرها ذاتاً بیحالت (Stateless) هستند؛ هر تغییری در فایلسیستم کانتینر با حذف آن از بین میرود. برای دادههای ماندگار — مثل فایلهای آپلودی یا دیتابیس — از ولوم استفاده میکنیم. دو نوع اصلی داریم:
- Named Volume: توسط داکر مدیریت میشود و در
/var/lib/docker/volumesذخیره میشود. - Bind Mount: یک پوشه از سیستم میزبان را مستقیماً به کانتینر متصل میکند. برای توسعه عالی است چون تغییرات کد بلافاصله اعمال میشود.
مثال Bind Mount برای توسعه:
docker run -d --name my-app-dev \
-p 8080:80 \
-v $(pwd)/src:/var/www/html \
my-php-app:v1
حالا هر تغییری در src/index.php بدون نیاز به rebuild ایمیج، در کانتینر اعمال میشود. این گردش کار توسعه را بسیار سریع میکند.
docker-compose down تمام دادهها پاک میشوند. همیشه برای سرویسهای دادهمحور، ولوم تعریف کنید.
اتصال چند کانتینر با Docker Compose
اپ واقعی فقط PHP نیست؛ به MySQL، Redis یا Nginx هم نیاز دارد. بهجای اجرای جداگانه هر کانتینر و اتصال دستی آنها، از Docker Compose استفاده میکنیم. فایل docker-compose.yml را اینطور مینویسیم:
services:
web:
build: .
ports:
- "8080:80"
volumes:
- ./src:/var/www/html
environment:
DB_HOST: db
DB_USER: root
DB_PASS: secret
DB_NAME: app_db
depends_on:
- db
db:
image: mysql:8.0
restart: always
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: app_db
volumes:
- db_data:/var/lib/mysql
ports:
- "3306:3306"
volumes:
db_data:
حالا با یک دستور، کل زیرساخت را بالا میآورید:
docker-compose up -d
داکر یک شبکه خصوصی بین سرویسها ایجاد میکند؛ پس کانتینر web میتواند با نام سرویس db به MySQL متصل شود. این دقیقاً همان مقداری است که در کد PHP بهعنوان DB_HOST تنظیم کردیم.
دستورات پرکاربرد Compose
docker-compose up -d: ساخت و اجرای همه سرویسها در پسزمینه.docker-compose logs -f web: مشاهده لاگهای زنده سرویس web.docker-compose exec web bash: ورود به شل کانتینر در حال اجرا.docker-compose down: توقف و حذف کانتینرها و شبکه (ولومها باقی میمانند).docker-compose down -v: حذف کامل همراه با ولومها — با احتیاط استفاده کنید.
اشتباهات رایج و نکات عیبیابی
در ادامه چند مشکل متداول و راهحل آنها را میبینید:
1. پورت از قبل استفاده شده است
اگر خطای port is already allocated دیدید، یا سرویس دیگری روی آن پورت است یا کانتینر قبلی هنوز اجراست. بررسی کنید:
docker ps
docker stop <container_id>
2. اتصال به دیتابیس برقرار نمیشود
مطمئن شوید DB_HOST دقیقاً برابر نام سرویس در Compose است (اینجا db)، نه localhost. داخل شبکه داکر، localhost به خود کانتینر اشاره میکند، نه به میزبان.
3. ایمیجهای حجیم و کندی ساخت
از ایمیجهای سبک مثل php:8.3-fpm-alpine استفاده کنید. همچنین فایل .dockerignore بسازید تا پوشههایی مثل vendor یا node_modules وارد context ساخت نشوند:
vendor/
node_modules/
.git/
*.log
4. تغییرات کد اعمال نمیشود
اگر از Bind Mount استفاده نمیکنید، بعد از هر تغییر کد باید ایمیج را دوباره بسازید: docker-compose up -d --build. در حالت توسعه، حتماً ولوم را طبق مثال بالا تعریف کنید.
بهبود امنیت و عملکرد ایمیجها
چند نکته حرفهای برای تولید:
- همیشه از تگ نسخه مشخص استفاده کنید، نه
latest. این کار reproducibility را تضمین میکند. - از کاربر غیر ریشه در کانتینر استفاده کنید (مثل
USER appuserدر Dockerfile). - متغیرهای محیطی حساس مثل رمز عبور را در فایل
.envنگه دارید و آن را به git اضافه نکنید. در Compose ازenv_fileاستفاده کنید. - برای کاهش حجم ایمیج، از multi-stage build استفاده کنید؛ مخصوصاً برای اپهای Node.js یا Go.
جمعبندی و گام بعدی
در این مقاله یاد گرفتید که با داکر، یک اپ PHP را همراه با MySQL در چند دقیقه بالا بیاورید. مفاهیم کلیدی — ایمیج، کانتینر، ولوم و Docker Compose — پایه هر پروژه داکری هستند. حالا میتوانید همین الگو را برای هر زبان و فریمورکی تکرار کنید.
برای گام بعدی، این تمرینها را انجام دهید: یک سرویس Nginx بهعنوان reverse proxy به Compose اضافه کنید، یا یک کانتینر Redis برای کش اضافه کنید. اگر به دنبال محیطهای ابری برای اجرای کانتینرهای خود هستید، سرویسهای ابری سرورنت میتوانند گزینه مناسبی برای استقرار باشند. اما مهمترین چیز این است که همین حالا دست به کار شوید و اولین Dockerfile خود را بنویسید.
دیدگاهها ۰
هنوز دیدگاهی ثبت نشده؛ اولین نفر باشید!