Биз жөнүндөБлогБайланыш
DevOps жана инфраструктура2026-ж., 17-апрель 5 минЖаңыланды: 2026-ж., 1-июль

Docker менен Node.js тиркемесин production'го чыгаруу: толук колдонмо

AunimedaAunimeda
📋 Мазмуну

Docker жок болгондо серверге деплой мындай болчу: сервердеги Node.js версиясы локалдыкынан айырмаланат, npm пакеттери бузулат, environment variable'дар жетишпейт. «Менде иштейт» - программисттин жамандык тилеги.

Docker бул маселени жапырт чечет: тиркемеңиз өзүнүн бардык dependency'лери менен бирге, изоляцияланган контейнерде иштейт. Ар кандай серверде, ар кандай облакта - бирдей.


Жөнөкөй Dockerfile эмне үчүн начар

Башталгыч иштеп чыгуучулар мындай жазат:

FROM node:20
WORKDIR /app
COPY . .
RUN npm install
EXPOSE 3000
CMD ["node", "server.js"]

Проблема: node:20 base image - бул Debian Linux, бардык build инструменттери менен. Мындай image'дин өлчөмү 1.2GBдан ашат. Production'до тиркемени иштетүү үчүн бул файлдардын 90%ы кереги жок.


Multi-stage Dockerfile: 1.2GB → 180MB

Multi-stage build - бул Dockerfile ичинде бир нече FROM этапы. Биринчи этапта куруп, экинчи этапта гана зарыл нерселерди алабыз.

# ===== ЭТАП 1: Build =====
FROM node:20-alpine AS builder

WORKDIR /app

# Алгач package файлдарды гана көчүр - docker layer cache үчүн
# Эгер package.json өзгөрбөсө, npm ci кайра аткарылбайт
COPY package.json package-lock.json ./
RUN npm ci --only=production

# Код TypeScript болсо - compile этиш:
COPY tsconfig.json ./
COPY src/ ./src/
RUN npm run build
# dist/ папкасы пайда болот

# ===== ЭТАП 2: Production image =====
FROM node:20-alpine AS production

# Security: root эмес, өзүнчө колдонуучу менен иштет
RUN addgroup -S appgroup && adduser -S appuser -G appgroup

WORKDIR /app

# Курулган builder этабынан гана керектүү файлдарды алабыз:
COPY --from=builder /app/node_modules ./node_modules
COPY --from=builder /app/dist ./dist
COPY package.json ./

# Ага чейин туура чөйрө орнотуу:
ENV NODE_ENV=production
ENV PORT=3000

# Колдонуучуга которулуу (root эмес)
USER appuser

EXPOSE 3000

# Healthcheck: Docker контейнердин ден соолугун текшерет
HEALTHCHECK --interval=30s --timeout=10s --start-period=20s --retries=3 \
  CMD wget --no-verbose --tries=1 --spider http://localhost:3000/health || exit 1

CMD ["node", "dist/server.js"]

Жыйынтык:

Этап Өлчөм
node:20 (стандарт) ~1.2 GB
node:20-alpine (multi-stage жок) ~180 MB
Multi-stage (биздин жол) ~95 MB

Alpine Linux - минималистик дистрибутив, бирок production'до жетиштүү.


.dockerignore - маанилүү файл

.gitignore сыяктуу - бирок Docker build контексти үчүн. Мунсуз Docker node_modules (1GB+), .git папкаларын, тест файлдарын image'ге киргизип жиберет.

# .dockerignore
node_modules/
dist/
.git/
.gitignore
*.log
.env
.env.*
coverage/
.nyc_output/
*.test.ts
*.spec.ts
__tests__/
README.md
docker-compose*.yml
Dockerfile*
.dockerignore

Environment variables жана secrets

Туура эмес жол - environment variable'дарды Dockerfile'га hardcode кылуу:

# ЖОЙ: image'ге credentials кирип кетет
ENV DATABASE_URL=postgresql://user:password@localhost/db

Туура жол - .env файлы docker-compose'та, production'до сервердин environment'ы же Docker secrets:

# .env.production (serverде гана, git'те ЖОК)
DATABASE_URL=postgresql://appuser:strongpassword@postgres:5432/myapp
REDIS_URL=redis://redis:6379
JWT_SECRET=your-256-bit-secret-here
NODE_ENV=production

docker-compose.yml: толук production stack

# docker-compose.yml
version: '3.9'

services:

  # ===== Node.js Application =====
  app:
    build:
      context: .
      dockerfile: Dockerfile
      target: production
    container_name: myapp_api
    restart: unless-stopped
    env_file:
      - .env.production
    environment:
      - NODE_ENV=production
    depends_on:
      postgres:
        condition: service_healthy
      redis:
        condition: service_healthy
    networks:
      - app_network
    # Сыртка порт ачпайбыз - Nginx'тен гана кирет
    expose:
      - "3000"
    volumes:
      # Uploads папкасы: контейнер өчкөндө жоголбосун
      - uploads_data:/app/uploads
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "5"

  # ===== PostgreSQL =====
  postgres:
    image: postgres:16-alpine
    container_name: myapp_postgres
    restart: unless-stopped
    environment:
      POSTGRES_DB: myapp
      POSTGRES_USER: appuser
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres_data:/var/lib/postgresql/data
      # Init скриптери (биринчи жүргүзүлгөндө):
      - ./db/init.sql:/docker-entrypoint-initdb.d/init.sql:ro
    networks:
      - app_network
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U appuser -d myapp"]
      interval: 10s
      timeout: 5s
      retries: 5
    logging:
      driver: "json-file"
      options:
        max-size: "5m"
        max-file: "3"

  # ===== Redis =====
  redis:
    image: redis:7-alpine
    container_name: myapp_redis
    restart: unless-stopped
    command: redis-server --maxmemory 256mb --maxmemory-policy allkeys-lru --requirepass ${REDIS_PASSWORD}
    volumes:
      - redis_data:/data
    networks:
      - app_network
    healthcheck:
      test: ["CMD", "redis-cli", "--no-auth-warning", "-a", "${REDIS_PASSWORD}", "ping"]
      interval: 10s
      timeout: 5s
      retries: 5

  # ===== Nginx Reverse Proxy =====
  nginx:
    image: nginx:alpine
    container_name: myapp_nginx
    restart: unless-stopped
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./nginx/nginx.conf:/etc/nginx/nginx.conf:ro
      - ./nginx/conf.d:/etc/nginx/conf.d:ro
      - certbot_certs:/etc/letsencrypt:ro
      - certbot_www:/var/www/certbot:ro
    depends_on:
      - app
    networks:
      - app_network

networks:
  app_network:
    driver: bridge

volumes:
  postgres_data:
  redis_data:
  uploads_data:
  certbot_certs:
  certbot_www:

Nginx конфигурациясы SSL менен

# nginx/conf.d/app.conf
upstream nodejs_backend {
    server app:3000;
    keepalive 64;
}

# HTTP → HTTPS redirect
server {
    listen 80;
    server_name api.myapp.kg www.myapp.kg;

    # Let's Encrypt verification
    location /.well-known/acme-challenge/ {
        root /var/www/certbot;
    }

    location / {
        return 301 https://$host$request_uri;
    }
}

# HTTPS
server {
    listen 443 ssl http2;
    server_name api.myapp.kg;

    ssl_certificate /etc/letsencrypt/live/api.myapp.kg/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/api.myapp.kg/privkey.pem;

    # SSL security settings
    ssl_protocols TLSv1.2 TLSv1.3;
    ssl_ciphers HIGH:!aNULL:!MD5;
    ssl_prefer_server_ciphers on;
    ssl_session_cache shared:SSL:10m;

    # Security headers
    add_header X-Frame-Options "SAMEORIGIN" always;
    add_header X-XSS-Protection "1; mode=block" always;
    add_header X-Content-Type-Options "nosniff" always;
    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

    # Проксилоо
    location /api/ {
        proxy_pass http://nodejs_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection 'upgrade';
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
        proxy_cache_bypass $http_upgrade;

        # Timeouts
        proxy_connect_timeout 60s;
        proxy_send_timeout 60s;
        proxy_read_timeout 60s;
    }

    # File uploads - чоңураак limit
    location /api/upload {
        proxy_pass http://nodejs_backend;
        client_max_body_size 50M;
        proxy_read_timeout 300s;
    }

    # Static files (эгер Next.js же React build болсо)
    location / {
        root /var/www/html;
        try_files $uri $uri/ /index.html;
        expires 1d;
        add_header Cache-Control "public, immutable";
    }
}

Деплой скрипти

#!/bin/bash
# deploy.sh - production серверде иштетилет

set -e  # Каталада токтот

echo "=== Pulling latest code ==="
git pull origin main

echo "=== Building Docker images ==="
docker compose build --no-cache app

echo "=== Running database migrations ==="
docker compose run --rm app node dist/migrations/run.js

echo "=== Restarting app container ==="
docker compose up -d --no-deps app

echo "=== Waiting for health check ==="
sleep 10
docker compose ps

echo "=== Cleaning up old images ==="
docker image prune -f

echo "=== Deploy complete! ==="

Логдорду башкаруу

# Реалдуу убакытта логдорду карау:
docker compose logs -f app

# Акыркы 100 сап:
docker compose logs --tail=100 app

# Конкреттүү убакыт аралыгы:
docker compose logs --since="2026-04-17T10:00:00" app

# Бардык контейнерлер:
docker compose logs --since="1h" --tail=50

Production'до Loki + Grafana же Papertrail сыяктуу централизованный лог жыйноо сунушталат - контейнер өчсө логдор жоголбосун.


Aunimeda - Docker, Node.js жана production деплой боюнча тажрыйбалуу команда. Тиркемеңизди сервердеги ишенимдүү инфраструктурага которобуз.

Долбооруңузду талкуулайлы же WhatsApp аркылуу жазыңыз.

Ошондой эле окуңуз

Node.js'теги таза архитектура: бизнес логиканы инфраструктурадан бөлүп алууaunimeda
Веб-иштеп чыгуу

Node.js'теги таза архитектура: бизнес логиканы инфраструктурадан бөлүп алуу

Алты айдан кийин Node.js долбоору спагетти кодго айланбасын десеңиз - Use Cases, Repository Pattern жана Dependency Inversion. Маалымат базасыз тестирленген бизнес логика - реалдуу код мисалдары менен.

Supabase vs Firebase: Кыргызстан стартабы үчүн кайсын тандоо керекaunimeda
Веб-иштеп чыгуу

Supabase vs Firebase: Кыргызстан стартабы үчүн кайсын тандоо керек

Supabase - PostgreSQL менен open-source BaaS. Firebase - Google'дун зрелый платформасы. PocketBase - бир бинардык файл, MVP үчүн идеал. Маалымат моделдери, баалар, realtime жана Кыргызстан долбоорлору үчүн кайсы тандоо туура экенин карайбыз.

Node.js vs Bun vs Deno 2026: кайсы JavaScript runtime тандоо керекaunimeda
Веб-иштеп чыгуу

Node.js vs Bun vs Deno 2026: кайсы JavaScript runtime тандоо керек

Bun 1.x продакшн стабилдүү. Deno 2.0 npm колдойт. Node.js 22 TypeScript'ти нативдүү иштетет. Реалдуу benchmark'тар, экосистема салыштыруусу жана Кыргызстандагы долбоорлор үчүн конкреттүү сунуштамалар.

Бизнесиңизге IT иштеп чыгуу керекпи?

Веб-сайттарды, мобилдик тиркемелерди жана AI чечимдерин иштеп чыгабыз. Акысыз консультация.

DevOps кызматтары

Консультация алуу Бардык макалалар