برنامه روی سیستم برنامه نویس درست کار می کند و روی سرور خطا می دهد، یا دو پروژه روی یک سرور سر نسخه PHP و Node با هم تداخل دارند: سوال چگونه داکر را نصب کنیم معمولا از همین جا پیدا می شود. خود نصب چند دقیقه کار دارد. دردسر بعدا از کاربر، لاگ، پورت ها و بکاپی شروع می شود که کسی تنظیمشان نکرده است. نصب را روی Ubuntu و AlmaLinux از مخزن رسمی انجام می دهیم، اجرا با کاربر غیر root را راه می اندازیم، اولین سرویس را با Docker Compose بالا می آوریم و آخر کار سراغ لاگ و نکات امنیتی می رویم.
از مخزن توزیع نصب کنیم یا مخزن رسمی داکر؟
بسته docker.io که در مخزن اوبونتو هست معمولا نسخه قدیمی تری دارد و افزونه های رسمی مثل Compose و Buildx را با نام و نسخه متفاوت می دهد. برای سرور از مخزن رسمی داکر استفاده کنید که نسخه به روز و بسته های استاندارد دارد و مسیر ارتقایش مشخص است. اسم بسته ها هم در دو مخزن فرق دارد و اشتباه رایج از همین جا می آید: در مخزن رسمی بسته ها docker-compose-plugin و docker-buildx-plugin نام دارند، در مخزن اوبونتو docker-compose-v2 و docker-buildx.
دستور قدیمی docker-compose (با خط تیره) هم کنار گذاشته شده است. Compose حالا افزونه خود داکر است و با docker compose (با فاصله) اجرا می شود.
نصب داکر روی Ubuntu
مراحل زیر روی نسخه های LTS اوبونتو، یعنی 22.04، 24.04 و 26.04، یکسان است. اول بسته های ناسازگار قدیمی را حذف کنید:
sudo apt remove docker.io docker-doc docker-compose docker-compose-v2 docker-buildx podman-docker containerd runc
حالا کلید GPG و مخزن رسمی را اضافه کنید:
sudo apt update
sudo apt install ca-certificates curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF
sudo apt update
و بسته ها را نصب کنید:
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
sudo docker run hello-world
اگر دستور آخر پیام خوش آمد را چاپ کرد، نصب درست انجام شده است.
نصب داکر روی AlmaLinux
روی AlmaLinux 9 مخزن docker-ce را اضافه کنید و بسته ها را نصب کنید:
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now docker
همین دستور dnf config-manager --add-repo روی AlmaLinux و Rocky نسخه 9 و 10 کار می کند. شکل addrepo --from-repofile فقط برای سیستم هایی است که dnf5 دارند، مثل Fedora 41 به بعد.
در خانواده RHEL اگر firewalld فعال است، داکر قوانین خودش را اضافه می کند و رفتار شبکه کانتینرها با چیزی که در firewalld می بینید یکی نیست. بعد از نصب، پورت های باز را از بیرون سرور تست کنید. SELinux را هم خاموش نکنید: داکر با SELinux کار می کند و برای volumeها گزینه :z یا :Z را دارید.
اجرای داکر با کاربر غیر root
بعد از نصب، فقط root و اعضای گروه docker می توانند دستور docker را اجرا کنند. برای اضافه کردن کاربر خودتان:
sudo usermod -aG docker $USER
newgrp docker
docker run hello-world
عضویت در گروه docker عملا همان دسترسی root روی سرور است، چون عضو این گروه می تواند کانتینری بسازد که کل فایل سیستم میزبان را mount کند. این نکته امنیتی معمولا نادیده گرفته می شود. گروه docker را فقط به کسانی بدهید که همین حالا هم دسترسی مدیریتی دارند.
اگر می خواهید برنامه های تیم را با کاربر معمولی اجرا کنید، حالت rootless گزینه بهتری است. در این حالت دیمن داکر با کاربر عادی اجرا می شود:
dockerd-rootless-setuptool.sh install
حالت rootless محدودیت هایی دارد، مثلا استفاده از پورت های زیر 1024 و بعضی تنظیمات شبکه، ولی برای سرور توسعه و محیط های چندکاربره ارزش بررسی دارد.
اولین سرویس با Docker Compose
برای یک سرویس تکی هم بهتر است به جای دستور طولانی docker run، فایل compose بنویسید تا تنظیمات جایی ثبت شود. یک نمونه ساده با یک وب سرور و یک دیتابیس:
services:
web:
image: nginx:1.29-alpine
restart: unless-stopped
ports:
- "127.0.0.1:8080:80"
volumes:
- ./site:/usr/share/nginx/html:ro
healthcheck:
test: ["CMD", "wget", "-qO-", "http://localhost/"]
interval: 30s
timeout: 5s
retries: 3
db:
image: mariadb:11
restart: unless-stopped
environment:
MARIADB_ROOT_PASSWORD_FILE: /run/secrets/db_root
volumes:
- db_data:/var/lib/mysql
secrets:
- db_root
volumes:
db_data:
secrets:
db_root:
file: ./secrets/db_root.txt
و اجرای آن:
docker compose up -d
docker compose ps
docker compose logs -f web
پورت در این فایل روی 127.0.0.1 منتشر شده، پس سرویس از بیرون سرور مستقیم در دسترس نیست و ترافیک باید از یک reverse proxy بگذرد. تگ ایمیج مشخص است و از latest استفاده نشده تا رفتار سرور با هر بار pull عوض نشود. رمز دیتابیس هم به جای متغیر محیطی ساده، از فایل خوانده می شود.
داده ها کجا می مانند؟
هر چیزی که داخل کانتینر نوشته شود با حذف کانتینر از بین می رود، پس داده ماندگار باید در volume باشد. برای بکاپ، از volume بکاپ بگیرید یا برای دیتابیس از دستور dump خود دیتابیس استفاده کنید. گرفتن کپی از دایرکتوری داده دیتابیس در حال اجرا روش قابل اعتمادی نیست.
لاگ، فضای دیسک و تنظیمات دیمن
داکر به طور پیش فرض لاگ کانتینرها را بدون سقف اندازه نگه می دارد و روی سروری که ماه ها روشن است، همین لاگ ها دیسک را پر می کنند. فایل /etc/docker/daemon.json را بسازید:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "10m",
"max-file": "3"
},
"live-restore": true
}
سپس sudo systemctl restart docker را اجرا کنید. گزینه live-restore باعث می شود کانتینرها هنگام ری استارت خود دیمن در حال اجرا بمانند.
برای پایش فضا و پاک سازی دوره ای:
docker system df
docker image prune -a
docker builder prune
دستور docker system prune -a همه چیز بلااستفاده را پاک می کند، پس قبل از اجرا روی سرور مشترک بدانید چه چیزی در حال استفاده است. این پاک سازی ها و پایش دیسک جزو نگهداری منظمی است که در مدیریت سرور لینوکس انجام می شود.
چک لیست امنیتی بعد از نصب
| مورد | کار درست |
|---|---|
| دسترسی گروه docker | فقط برای مدیران سرور، چون معادل root است |
| انتشار پورت | پورت داخلی روی 127.0.0.1، ورودی عمومی فقط از reverse proxy |
| فایروال | پورت های منتشرشده داکر را از بیرون تست کنید؛ قوانین داکر در زنجیره جداگانه ای در iptables اضافه می شوند و ممکن است UFW آن ها را نبیند |
| کاربر داخل کانتینر | تعریف USER در Dockerfile، اجرا نکردن سرویس با root |
| گزینه های اجرا | استفاده از no-new-privileges و read-only در جایی که ممکن است |
| محدودیت منابع | تعیین سقف حافظه و CPU برای هر سرویس |
| تگ ایمیج | نسخه مشخص به جای latest |
| اسکن ایمیج | بررسی دوره ای ایمیج ها با ابزاری مثل Trivy |
| سوکت داکر | هرگز /var/run/docker.sock را داخل کانتینری که لازم ندارد mount نکنید |
مشکلی که در ایران زیاد پیش می آید
دسترسی مستقیم به Docker Hub همیشه برقرار نیست و build در وسط کار متوقف می شود. برای این مشکل می توانید یک mirror داخلی برای رجیستری تنظیم کنید، یا رجیستری خصوصی مثل Harbor را روی سرور خودتان راه بیندازید و ایمیج های پروژه را در آن push کنید. با رجیستری خصوصی، build و deploy دیگر به در دسترس بودن سرویس بیرونی وابسته نیست و کنترل نسخه ایمیج ها هم دست خودتان است. راه اندازی رجیستری و داکرایز کردن پروژه بخشی از سرویس راه اندازی داکر است.
وقتی برنامه کانتینری شد، قدم بعدی خودکار کردن ساخت و استقرار آن است (CI/CD چیست) و گذاشتن Nginx جلوی آن به عنوان reverse proxy (نصب Nginx روی اوبونتو).
اشتباه هایی که در نصب داکر زیاد می بینیم
- نصب همزمان بسته توزیع و بسته رسمی. اول نسخه قدیمی را کامل حذف کنید.
- استفاده از
docker-composeقدیمی در کنار افزونه جدید و سردرگمی بین دو فایل تنظیمات. - نگه داشتن رمز و توکن داخل ایمیج یا در فایل compose بدون فایل جداگانه.
- اتکا به restart: always بدون healthcheck؛ کانتینری که بالا هست ولی سرویس داخلش جواب نمی دهد سالم حساب می شود.
- نداشتن بکاپ از volumeها. کانتینر یک بار حذف می شود و داده همراهش می رود.
- باز کردن پورت دیتابیس روی 0.0.0.0 برای اینکه کار سریع تر راه بیفتد.
اجرای Redis داخل کانتینر در Redis چیست آمده است.
اجرای چند کانتینر با یک فایل YAML در Docker Compose چیست توضیح داده شده است.
منابع و مستندات رسمی
وقتی چند سرور و سرویس دارید، مرحله بعد نصب کلاستر کوبرنتیز روی اوبونتو است.
بعد از نصب، کار اصلی روی ساختار ایمیج ها، مسیر build و deploy و برنامه نگهداری است. اگر پروژه فعلی تان باید داکرایز شود، یا سرور داکر شرکت به رجیستری خصوصی و مستندات به روزرسانی نیاز دارد، سرویس راه اندازی داکر و کانتینرسازی را ببینید. کار از وضعیت فعلی سرور شروع می شود و بعد ساختار پیشنهادی را با هم مرور می کنیم.



