Docker / Compose service тохируулах

Compose service тохируулах

docker-compose.yml-д service бүрийн тохиргоог нарийвчлан заах боломжтой. Энэ хичээлд хамгийн чухал тохиргоонуудыг Node.js + PostgreSQL жишээгээр судална.

image — бэлэн image ашиглах

yaml
services:
  db:
    image: postgres:16

  cache:
    image: redis:7-alpine

  proxy:
    image: nginx:1.25-alpine

Tag заавал зааж байхыг зөвлөдөг — latest tag нь хуучин cache болж болзошгүй.

build — Dockerfile-аас build хийх

yaml
services:
  app:
    build: .                    # Одоогийн директорын Dockerfile

  app:
    build:
      context: ./app            # Build context директор
      dockerfile: Dockerfile.prod  # Dockerfile нэр
      args:
        NODE_ENV: production    # Build аргумент

image ба build хамт байвал build хийгдсэн image-д нэр өгнө:

yaml
services:
  app:
    build: .
    image: myapp:1.0 # Build хийсний дараа энэ нэртэй болно

ports — port mapping

yaml
services:
  app:
    ports:
      - "3000:3000" # HOST:CONTAINER
      - "9229:9229" # Debug port

  nginx:
    ports:
      - "80:80"
      - "443:443"
      - "127.0.0.1:8080:80" # Зөвхөн localhost

environment — environment variable

yaml
services:
  db:
    image: postgres:16
    environment:
      # Map хэлбэр
      POSTGRES_PASSWORD: secret
      POSTGRES_DB: mydb
      POSTGRES_USER: admin

  app:
    image: myapp:1.0
    environment:
      # Жагсаалт хэлбэр
      - NODE_ENV=production
      - PORT=3000
      - DB_HOST=db

  # .env файлаас авах
  app2:
    image: myapp:1.0
    env_file:
      - .env
      - .env.production

depends_on — ачааллах дараалал

Service ямар дараалалд эхлэхийг тодорхойлно:

yaml
services:
  app:
    image: myapp:1.0
    depends_on:
      - db
      - redis

  db:
    image: postgres:16

  redis:
    image: redis:7-alpine

app нь db ба redis эхэлсний дараа эхэлнэ.

Анхаар: depends_on нь container эхэлснийг хүлээнэ — service бэлэн болснийг биш. PostgreSQL эхлэхэд цөөн секунд шаардагдана. Үүний тулд condition ашиглана:

yaml
services:
  app:
    depends_on:
      db:
        condition: service_healthy # Healthcheck давтал хүлээнэ
      redis:
        condition: service_started # Анхдагч — зөвхөн эхэлснийг хүлээнэ

  db:
    image: postgres:16
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 5s
      timeout: 5s
      retries: 5

restart — дахин эхлүүлэх бодлого

yaml
services:
  app:
    restart: no # Дахин эхлүүлэхгүй (анхдагч)

  db:
    restart: always # Үргэлж дахин эхлүүлнэ

  worker:
    restart: on-failure # Алдаатай зогссон үед л дахин эхлүүлнэ

  api:
    restart: unless-stopped # Гараар зогсоох хүртэл дахин эхлүүлнэ

Production-д unless-stopped эсвэл always ашиглана.

volumes — хадгалалт

yaml
services:
  db:
    volumes:
      - pg-data:/var/lib/postgresql/data # Named volume
      - ./init.sql:/docker-entrypoint-initdb.d/init.sql:ro # Bind mount

  app:
    volumes:
      - ./src:/app/src # Хөгжүүлэлтийн bind mount
      - /app/node_modules # Anonymous volume (node_modules хамгаалах)

volumes:
  pg-data: # Named volume тодорхойлолт

Бүтэн жишээ — Node.js + PostgreSQL

Файл бүтэц:

код
myapp/
├── docker-compose.yml
├── docker-compose.dev.yml
├── .env
├── app/
│   ├── Dockerfile
│   ├── package.json
│   └── index.js
└── nginx/
    └── nginx.conf

.env:

env
POSTGRES_PASSWORD=supersecret
POSTGRES_DB=myapp_db
POSTGRES_USER=myapp_user
NODE_ENV=production

app/index.js:

javascript
const express = require("express");
const { Pool } = require("pg");

const pool = new Pool({
  host: process.env.DB_HOST,
  port: 5432,
  database: process.env.DB_NAME,
  user: process.env.DB_USER,
  password: process.env.DB_PASSWORD,
});

const app = express();

app.get("/", async (req, res) => {
  const result = await pool.query("SELECT NOW()");
  res.json({ time: result.rows[0].now });
});

app.listen(3000, () => console.log("3000 port дээр ажиллаж байна"));

app/Dockerfile:

dockerfile
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm install --omit=dev
COPY . .
EXPOSE 3000
CMD ["node", "index.js"]

docker-compose.yml:

yaml
services:
  app:
    build: ./app
    ports:
      - "3000:3000"
    environment:
      - NODE_ENV=production
      - DB_HOST=db
      - DB_NAME=${POSTGRES_DB}
      - DB_USER=${POSTGRES_USER}
      - DB_PASSWORD=${POSTGRES_PASSWORD}
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
      POSTGRES_DB: ${POSTGRES_DB}
      POSTGRES_USER: ${POSTGRES_USER}
    volumes:
      - pg-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U ${POSTGRES_USER} -d ${POSTGRES_DB}"]
      interval: 5s
      timeout: 5s
      retries: 5
    restart: unless-stopped

volumes:
  pg-data:

Ажиллуулах:

bash
docker compose up -d
docker compose logs -f app

Хөгжүүлэлтийн override файл

Production Compose файлыг өөрчлөхгүйгээр хөгжүүлэлтийн тохиргоо нэмэхэд docker-compose.dev.yml ашиглана:

docker-compose.dev.yml:

yaml
services:
  app:
    build:
      target: development
    volumes:
      - ./app:/app
      - /app/node_modules
    environment:
      - NODE_ENV=development
    command: npm run dev
bash
# Хоёр файлыг нэгтгэж ажиллуулах
docker compose -f docker-compose.yml -f docker-compose.dev.yml up

Дараагийн хичээлд:

Compose дахь volume ба network-ийн дэлгэрэнгүй тохиргоо, service discovery механизмыг судална.