docker run با ده گزینه را هیچکس یادش نمیماند. Docker Compose همهٔ سرویسها، تنظیمات، volumeها و شبکه را در یک فایل متنی به اسم compose.yaml مینویسد. این فایل را در گیت نگه میدارید و هر وقت و روی هر سروری، با یک دستور همهٔ سرویسها دقیقاً همانطور بالا میآیند.
مثال کامل: وردپرس و MariaDB
یک پوشه بسازید، مثلاً /opt/blog، و دو فایل در آن بگذارید. اول .env برای رمزها (این فایل را در گیت نگذارید):
DB_PASSWORD=change-me-long-random
DB_ROOT_PASSWORD=change-me-too-long-randomبعد compose.yaml:
services:
db:
image: mariadb:11.4
restart: unless-stopped
environment:
MARIADB_DATABASE: wordpress
MARIADB_USER: wordpress
MARIADB_PASSWORD: ${DB_PASSWORD}
MARIADB_ROOT_PASSWORD: ${DB_ROOT_PASSWORD}
volumes:
- db_data:/var/lib/mysql
healthcheck:
test: ["CMD", "healthcheck.sh", "--connect", "--innodb_initialized"]
interval: 10s
retries: 5
wordpress:
image: wordpress:php8.3-apache
restart: unless-stopped
depends_on:
db:
condition: service_healthy
environment:
WORDPRESS_DB_HOST: db
WORDPRESS_DB_NAME: wordpress
WORDPRESS_DB_USER: wordpress
WORDPRESS_DB_PASSWORD: ${DB_PASSWORD}
volumes:
- wp_data:/var/www/html
ports:
- "127.0.0.1:8080:80"
volumes:
db_data:
wp_data:cd /opt/blog
docker compose up -d
docker compose psهر بخش چه میکند
- services: هر سرویس یک کانتینر است. اسم سرویس (
db) در شبکهٔ داخلی compose، اسم میزبان هم هست؛ برای همین وردپرس دیتابیس را باWORDPRESS_DB_HOST: dbپیدا میکند. - restart: unless-stopped: بعد از ریاستارت سرور یا کرش، کانتینر خودش بالا میآید.
- volumes: دیتابیس و فایلهای وردپرس بیرون از کانتینر میمانند؛ کانتینر را پاک و دوباره بسازید، دادهها سر جایشان است.
- healthcheck و depends_on: وردپرس صبر میکند تا دیتابیس واقعاً آماده شود، نه فقط روشن.
- 127.0.0.1:8080:80: پورت فقط روی خود سرور باز است، نه روی اینترنت. چرا؟ در مقالهٔ امنیت توضیح دادهایم؛ خلاصهاش این است که داکر فایروال UFW را دور میزند.
- دیتابیس هیچ
portsندارد: فقط وردپرس به آن دسترسی دارد.
دستورهای روزمره
docker compose ps # وضعیت سرویسها
docker compose logs -f wordpress # لاگ یک سرویس
docker compose restart wordpress # ریاستارت
docker compose exec db mariadb -u root -p # کنسول دیتابیس
docker compose down # توقف و حذف کانتینرها (volumeها میمانند)آپدیت
docker compose pull # دانلود نسخهٔ تازهٔ imageها
docker compose up -d # ساختن دوبارهٔ فقط کانتینرهایی که image تازه دارند
docker image prune -f # پاک کردن imageهای قدیمیبرای سرویسهای مهم، به جای latest نسخهٔ مشخص بگذارید (mariadb:11.4) تا یک آپدیت بزرگ ناخواسته، مثلاً جهش نسخهٔ اصلی دیتابیس، سرویس را خراب نکند. قبل از آپدیت بکاپ بگیرید.
بکاپ
دیتابیس را با dump بگیرید، نه با کپی فایلها وقتی دیتابیس روشن است:
docker compose exec -T db sh -c 'mariadb-dump -u root -p"$MARIADB_ROOT_PASSWORD" --all-databases' \
| gzip > /backup/db-$(date +%F).sql.gzvolume فایلها را با یک کانتینر موقت فشرده کنید:
docker run --rm -v blog_wp_data:/data:ro -v /backup:/backup alpine \
tar czf /backup/wp-files-$(date +%F).tar.gz -C /data .اسم واقعی volume را با docker volume ls ببینید (Compose اسم پوشه را جلویش میگذارد). این دو دستور را در cron بگذارید و نسخه را بیرون از سرور هم نگه دارید؛ همان قانون ۳-۲-۱ در مقالهٔ بکاپ وردپرس. فایل compose و .env را هم فراموش نکنید.
پشت دامنه با SSL
پورت ۸۰۸۰ فقط روی خود سرور باز است؛ یک reverse proxy روی سرور، دامنه و گواهی SSL را مدیریت میکند و درخواستها را به آن میدهد. سادهترین گزینهها Caddy (گواهی Let's Encrypt را خودکار میگیرد) یا Nginx با certbot است. نمونهٔ Caddyfile:
blog.example.ir {
reverse_proxy 127.0.0.1:8080
}قبلش رکورد A دامنه باید به IP سرور اشاره کند؛ تنظیم DNS دامنه را ببینید.
منابع
- Docker Docs — Compose file reference docs.docker.com/reference/compose-file
- Docker Hub — WordPress official image hub.docker.com/_/wordpress
- Docker Hub — MariaDB official image hub.docker.com/_/mariadb
- Caddy — Reverse proxy quick-start caddyserver.com/docs/quick-starts/reverse-proxy