Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Опыт работы с Docker
Да, я активно использую Docker в своей работе. Это критически важный инструмент для современного backend-разработчика. Расскажу как я его применяю.
Основные концепции
Docker — это контейнеризация приложений. Я упаковываю приложение вместе со всеми зависимостями в образ, который гарантированно работает везде: на локальной машине, в CI/CD, на сервере.
# Основные компоненты Docker
# 1. Dockerfile — рецепт как собрать образ
# 2. Image — готовый образ (бинарник)
# 3. Container — запущенный образ (процесс)
# 4. Registry — хранилище образов (Docker Hub, GitHub Registry)
Dockerfile для Node.js приложения
# Используем официальный образ Node
FROM node:20-alpine
# Устанавливаем рабочую директорию
WORKDIR /app
# Копируем package файлы
COPY package*.json ./
# Устанавливаем зависимости
RUN npm ci --only=production
# Копируем исходный код
COPY . .
# Выстраиваем приложение (если нужно)
RUN npm run build
# Открываем порт
EXPOSE 3000
# Запускаем приложение
CMD ["node", "dist/server.js"]
Почему alpine?
- Размер: 40MB против 150MB для ubuntu
- Безопасность: минимум зависимостей
- Скорость: быстрее скачивается и загружается
Docker Compose для локальной разработки
# docker-compose.yml
version: '3.9'
services:
# Node приложение
app:
build:
context: .
dockerfile: Dockerfile.dev
ports:
- "3000:3000"
environment:
NODE_ENV: development
DATABASE_URL: postgresql://user:pass@postgres:5432/db
volumes:
- .:/app
- /app/node_modules
depends_on:
- postgres
- redis
command: npm run dev
# PostgreSQL
postgres:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: db
ports:
- "5432:5432"
volumes:
- postgres_data:/var/lib/postgresql/data
# Redis для кэша
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
Команды которые я использую:
# Запустить все сервисы
docker compose up
# Запустить в background
docker compose up -d
# Остановить
docker compose down
# Удалить volumes (очистить БД)
docker compose down -v
# Посмотреть логи
docker compose logs -f app
# Запустить команду в контейнере
docker compose exec app npm test
Multi-stage build для production
Этот подход уменьшает размер финального образа.
# Stage 1: Build
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
# Stage 2: Production
FROM node:20-alpine
WORKDIR /app
# Копируем только prod зависимости
COPY package*.json ./
RUN npm ci --only=production
# Копируем собранное приложение из builder
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/server.js"]
Результат: образ в 2-3 раза меньше т.к. не содержит dev-зависимостей и исходный код.
Оптимизация Dockerfile
# Плохо: все в одном слое, кэш не используется
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN npm install
RUN npm run build
# Хорошо: слои оптимизированы для кэша
FROM node:20-alpine
WORKDIR /app
# Зависимости меняются редко
COPY package*.json ./
RUN npm ci --only=production
# Исходный код меняется часто
COPY . .
RUN npm run build
CMD ["node", "dist/server.js"]
Почему это важно? Docker использует слои. Если я меняю исходный код, переиспользуются слои с зависимостями. Если я меняю зависимости, пересчитываются только нужные слои.
Health checks
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production
COPY . .
# Health check — Docker проверит жив ли контейнер
HEALTHCHECK --interval=30s --timeout=3s --start-period=10s --retries=3 \
CMD node -e "require('http').get('http://localhost:3000/health', (r) => {if (r.statusCode !== 200) throw new Error(r.statusCode)})"
EXPOSE 3000
CMD ["node", "dist/server.js"]
// server.ts — добавляю health check endpoint
app.get('/health', (req, res) => {
res.json({ status: 'ok', timestamp: new Date() });
});
Примеры команд
# Собрать образ
docker build -t my-app:1.0 .
# Запустить контейнер
docker run -d -p 3000:3000 --name app my-app:1.0
# Посмотреть логи
docker logs -f app
# Зайти в контейнер
docker exec -it app /bin/sh
# Остановить
docker stop app
# Удалить
docker rm app
# Залить на Docker Hub
docker tag my-app:1.0 myusername/my-app:1.0
docker push myusername/my-app:1.0
Лучшие практики
- Используй alpine образы — меньше размер, безопаснее
- Pinned versions — не используй latest в production
- Multi-stage builds — уменьшай размер образа
- WORKDIR первым — помогает документации
- Не запускай от root — создай пользователя
# Правильно
RUN addgroup -g 1001 -S nodejs
RUN adduser -S nodejs -u 1001
USER nodejs
CMD ["node", "dist/server.js"]
- Минимизируй слои — используй && для объединения команд
# Плохо
RUN apt-get update
RUN apt-get install -y curl
RUN rm -rf /var/lib/apt/lists/*
# Хорошо
RUN apt-get update && apt-get install -y curl && rm -rf /var/lib/apt/lists/*
- Используй .dockerignore — исключай ненужные файлы
node_modules
npm-debug.log
.git
.gitignore
README.md
.env
Integration с CI/CD
# GitHub Actions пример
name: Build and Push Docker Image
on:
push:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build image
run: docker build -t my-app:${{ github.sha }} .
- name: Run tests in Docker
run: docker run my-app:${{ github.sha }} npm test
- name: Login to registry
run: echo ${{ secrets.DOCKER_PASSWORD }} | docker login -u ${{ secrets.DOCKER_USERNAME }} --password-stdin
- name: Push image
run: |
docker tag my-app:${{ github.sha }} myusername/my-app:latest
docker push myusername/my-app:latest
Networking в Docker Compose
services:
app:
environment:
# Обращаюсь к postgres по имени сервиса
DATABASE_URL: postgresql://user:pass@postgres:5432/db
# Redis по имени
REDIS_URL: redis://redis:6379
Docker автоматически создаёт сеть и разрешает обращение по имени сервиса.
Debugging в контейнере
# Зайти в shell контейнера
docker compose exec app /bin/sh
# Или с bash
docker compose exec app bash
# Запустить команду
docker compose exec app npm test
docker compose exec app node -e "console.log('test')"
# Посмотреть переменные окружения
docker compose exec app env
Мой workflow
- Разработка: docker compose up для запуска зависимостей
- Тестирование: docker compose exec app npm test
- Сборка: docker build на CI
- Push: на Docker Hub или GitHub Registry
- Deployment: docker pull и docker run на сервере
Дocker позволяет гарантировать что приложение работает одинаково везде. Это экономит время на debug production issues и делает разработку предсказуемой.