سوال چگونه داکر را نصب کنیم معمولا از جایی شروع می شود که برنامه روی سیستم برنامه نویس درست کار می کند و روی سرور خطا می دهد، یا دو پروژه روی یک سرور سر نسخه PHP و Node با هم تداخل دارند. نصب خود داکر چند دقیقه طول می کشد؛ چیزی که بعدا دردسر می شود، تنظیم نشدن کاربر، لاگ، پورت ها و بکاپ است. در این راهنما نصب را روی Ubuntu و AlmaLinux با مخزن رسمی انجام می دهیم، اجرا با کاربر غیر root را درست می کنیم، اولین سرویس را با Docker Compose بالا می آوریم و نکات امنیتی و لاگ را مرور می کنیم.
از مخزن توزیع نصب کنیم یا مخزن رسمی داکر؟
بسته docker.io که در مخزن اوبونتو هست معمولا نسخه قدیمی تری دارد و افزونه های رسمی مثل Compose و Buildx را با نام و نسخه متفاوت می دهد. برای سرور، مخزن رسمی داکر گزینه درست است: نسخه به روز، بسته های استاندارد و مسیر ارتقای مشخص. اسم بسته ها هم فرق دارد و همین باعث اشتباه رایج می شود: در مخزن رسمی بسته ها docker-compose-plugin و docker-buildx-plugin نام دارند، در مخزن اوبونتو docker-compose-v2 و docker-buildx.
نکته دیگر اینکه دستور قدیمی docker-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
روی AlmaLinux 10 که dnf5 دارد، دستور افزودن مخزن شکل دیگری دارد:
sudo dnf config-manager addrepo --from-repofile=https://download.docker.com/linux/rhel/docker-ce.repo
دو نکته مخصوص خانواده 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 کند. پس این گروه را فقط به کسانی بدهید که همین حالا هم دسترسی مدیریتی دارند.
اگر می خواهید برنامه های تیم را با کاربر معمولی اجرا کنید، حالت 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 دیگر به در دسترس بودن سرویس بیرونی وابسته نیست و کنترل نسخه ایمیج ها هم دست خودتان است. راه اندازی رجیستری و داکرایز کردن پروژه بخشی از سرویس راه اندازی داکر است.
اشتباه های رایج
- نصب همزمان بسته توزیع و بسته رسمی. اول نسخه قدیمی را کامل حذف کنید.
- استفاده از
docker-composeقدیمی در کنار افزونه جدید و سردرگمی بین دو فایل تنظیمات. - نگه داشتن رمز و توکن داخل ایمیج یا در فایل compose بدون فایل جداگانه.
- اتکا به restart: always بدون healthcheck؛ کانتینری که بالا هست ولی سرویس داخلش جواب نمی دهد سالم حساب می شود.
- نداشتن بکاپ از volumeها. کانتینر یک بار حذف می شود و داده همراهش می رود.
- باز کردن پورت دیتابیس روی 0.0.0.0 برای اینکه کار سریع تر راه بیفتد.
نصب داکر شروع کار است؛ چیزی که تفاوت ایجاد می کند، ساختار ایمیج ها، مسیر build و deploy و برنامه نگهداری است. اگر می خواهید پروژه فعلی تان داکرایز شود یا سرور داکر شرکت را با رجیستری خصوصی و مستندات به روزرسانی مرتب کنید، در سرویس راه اندازی داکر و کانتینرسازی وضعیت فعلی را بررسی می کنیم و ساختار پیشنهادی را با شما مرور می کنیم.



