Docker روش ساختن، ارسال و اجرای نرمافزار را تغییر داد. به جای "روی دستگاه من کار میکند"، Docker تضمین میکند که اپلیکیشن شما در همه جا یکسان اجرا شود - روی لپتاپ شما، روی دستگاه همکار، در CI/CD و در تولید. در این راهنما، از صفر تا دیپلوی یک اپلیکیشن واقعی پیش خواهیم رفت.
Docker چیست؟
Docker پلتفرمی است که اپلیکیشن شما و تمام وابستگیهایش را در یک واحد استاندارد به نام کانتینر بستهبندی میکند. کانتینر یک فرآیند ایزوله و سبک است که هسته سیستم عامل میزبان را به اشتراک میگذارد اما سیستم فایل، شبکه و فضای فرآیند خود را دارد.
کانتینرها در مقابل ماشینهای مجازی
| جنبه | کانتینرها | ماشینهای مجازی |
|---|---|---|
| راهاندازی | ثانیه | دقیقه |
| اندازه | مگابایت | گیگابایت |
| سیستم عامل | هسته میزبان را به اشتراک میگذارد | سیستم عامل مهمان کامل |
| ایزولاسیون | سطح فرآیند | سطح سختافزار |
| عملکرد | تقریبا بومی | سربار از هایپروایزر |
| تراکم | صدها در هر میزبان | دهها در هر میزبان |
نصب Docker
# macOS brew install --cask docker # Ubuntu/Debian curl -fsSL https://get.docker.com | sh sudo usermod -aG docker $USER # Verify installation docker --version docker run hello-world
مفاهیم اصلی
ایمیجها
ایمیج یک قالب فقط خواندنی با دستورالعملهای ایجاد کانتینر است. آن را مانند یک عکس فوری از اپلیکیشن و محیط آن در نظر بگیرید.
# Pull an image from Docker Hub docker pull node:20-alpine # List local images docker images # Remove an image docker rmi node:20-alpine
کانتینرها
کانتینر یک نمونه در حال اجرا از یک ایمیج است. میتوانید کانتینرها را ایجاد، راهاندازی، متوقف و حذف کنید.
# Run a container docker run -d --name my-app -p 3000:3000 node:20-alpine # List running containers docker ps # List all containers (including stopped) docker ps -a # Stop a container docker stop my-app # Remove a container docker rm my-app # View logs docker logs my-app # Execute a command inside a running container docker exec -it my-app sh
نوشتن Dockerfile
Dockerfile یک فایل متنی با دستورالعملهایی برای ساخت ایمیج است. هر دستورالعمل یک لایه ایجاد میکند.
Dockerfile پایه برای یک اپلیکیشن Node.js
# Use an official Node.js runtime as base image FROM node:20-alpine # Set working directory WORKDIR /app # Copy package files first (better caching) COPY package.json package-lock.json ./ # Install dependencies RUN npm ci --only=production # Copy application code COPY . . # Expose the port the app runs on EXPOSE 3000 # Command to run the application CMD ["node", "server.js"]
ساخت و اجرا
# Build the image docker build -t my-node-app . # Run the container docker run -d -p 3000:3000 my-node-app # Visit http://localhost:3000
بیلد چند مرحلهای
بیلدهای چند مرحلهای با جداسازی محیط بیلد از محیط اجرا، ایمیجهای تولید شما را کوچک نگه میدارند.
# Stage 1: Build FROM node:20-alpine AS builder WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci COPY . . RUN npm run build # Stage 2: Production FROM node:20-alpine AS runner WORKDIR /app COPY /app/dist ./dist COPY /app/node_modules ./node_modules COPY /app/package.json ./ EXPOSE 3000 CMD ["node", "dist/server.js"]
این یک ایمیج تولید میکند که فقط شامل خروجی کامپایل شده و وابستگیهای تولید است - بدون کد منبع، بدون وابستگیهای توسعه، بدون ابزارهای بیلد.
مثال چند مرحلهای Next.js
FROM node:20-alpine AS deps WORKDIR /app COPY package.json package-lock.json ./ RUN npm ci FROM node:20-alpine AS builder WORKDIR /app COPY /app/node_modules ./node_modules COPY . . RUN npm run build FROM node:20-alpine AS runner WORKDIR /app ENV NODE_ENV=production COPY /app/public ./public COPY /app/.next/standalone ./ COPY /app/.next/static ./.next/static EXPOSE 3000 CMD ["node", "server.js"]
والیومها: دادههای پایدار
به طور پیشفرض، دادههای داخل کانتینر هنگام حذف کانتینر از بین میروند. والیومها این مشکل را حل میکنند.
# Create a named volume docker volume create my-data # Run with a volume docker run -d -v my-data:/app/data my-app # Bind mount (map host directory to container) docker run -d -v $(pwd)/data:/app/data my-app # List volumes docker volume ls
شبکه
Docker شبکههای ایزوله برای ارتباط کانتینرها ایجاد میکند.
# Create a custom network docker network create my-network # Run containers on the same network docker run -d --name api --network my-network my-api docker run -d --name db --network my-network postgres:16 # Containers can reach each other by name # From "api" container: postgres://db:5432
Docker Compose
Docker Compose به شما امکان میدهد اپلیکیشنهای چند کانتینری را با یک فایل YAML تعریف و اجرا کنید.
docker-compose.yml
services: api: build: ./api ports: - "3000:3000" environment: - DATABASE_URL=postgres://user:pass@db:5432/mydb depends_on: - db db: image: postgres:16-alpine environment: - POSTGRES_USER=user - POSTGRES_PASSWORD=pass - POSTGRES_DB=mydb volumes: - pgdata:/var/lib/postgresql/data ports: - "5432:5432" redis: image: redis:7-alpine ports: - "6379:6379" volumes: pgdata:
دستورات
# Start all services docker compose up -d # View logs docker compose logs -f # Stop all services docker compose down # Rebuild and restart docker compose up -d --build # Scale a service docker compose up -d --scale api=3
.dockerignore
مانند .gitignore، این فایل از کپی شدن فایلهای غیرضروری در ایمیج جلوگیری میکند.
node_modules .git .env *.md .next dist coverage
بهترین شیوههای تولید
1. از ایمیجهای پایه کوچک استفاده کنید
# Bad: 1GB+ FROM node:20 # Good: ~180MB FROM node:20-alpine
2. با کاربر Root اجرا نکنید
FROM node:20-alpine RUN addgroup -S app && adduser -S app -G app USER app WORKDIR /home/app COPY . .
3. از تگهای ایمیج مشخص استفاده کنید
# Bad: can change unexpectedly FROM node:latest # Good: pinned version FROM node:20.11-alpine3.19
4. از کش بیلد بهره ببرید
دستورالعملهای Dockerfile خود را از کمترین تا بیشترین تغییر مرتب کنید:
FROM node:20-alpine WORKDIR /app # These change rarely - cached COPY package.json package-lock.json ./ RUN npm ci --only=production # This changes often - not cached COPY . .
5. بررسی سلامت
HEALTHCHECK \ CMD wget -qO- http://localhost:3000/health || exit 1
6. از متغیرهای محیطی استفاده کنید
ENV NODE_ENV=production ENV PORT=3000
برگه تقلب دستورات رایج Docker
# Images docker build -t name:tag . # Build image docker images # List images docker rmi image_name # Remove image docker image prune # Remove unused images # Containers docker run -d -p 3000:3000 image # Run detached docker ps # List running docker stop container_name # Stop docker rm container_name # Remove docker logs -f container_name # Follow logs docker exec -it container sh # Shell into container # Compose docker compose up -d # Start services docker compose down # Stop services docker compose logs -f # Follow all logs docker compose ps # List services # Cleanup docker system prune -a # Remove everything unused
از Docker به Kubernetes
Docker کانتینرهای جداگانه را مدیریت میکند. وقتی نیاز دارید صدها کانتینر را در چندین سرور هماهنگ کنید، به Kubernetes نیاز دارید. Docker و Kubernetes مکمل یکدیگر هستند:
- Docker: کانتینرها را میسازد و اجرا میکند
- Kubernetes: کانتینرها را در مقیاس بزرگ هماهنگ میکند (زمانبندی، مقیاسپذیری، خودترمیمی)
اگر به مرحله بعدی علاقهمندید، مقاله من درباره مقدمهای بر Kubernetes را ببینید.
نتیجهگیری
Docker یک مهارت اساسی برای توسعهدهندگان مدرن است. ناسازگاریهای محیطی را از بین میبرد، دیپلوی را ساده میکند و پایهای برای هماهنگی کانتینرها با Kubernetes است. با یک Dockerfile ساده شروع کنید، به Docker Compose برای اپلیکیشنهای چند سرویسی بروید، و با رشد خود بیلدهای چند مرحلهای و بهترین شیوههای امنیتی را بپذیرید.
بهترین راه یادگیری Docker، کانتینری کردن پروژهای است که در حال حاضر روی آن کار میکنید. همین امروز شروع کنید.