«У меня на компьютере всё работает» — фраза, которую хотя бы раз говорил каждый разработчик. А потом проект попадает на сервер, и там ничего не запускается. Другая версия Node.js, нет нужной библиотеки, конфликт портов. Docker решает эту проблему раз и навсегда.
Проблема окружений
Допустим, вы пишете проект на Node.js 20. У вас на машине стоит PostgreSQL 15, Redis 7, и всё прекрасно работает. Потом вы отдаёте код коллеге — а у него Node.js 18, PostgreSQL 14, и проект падает с непонятными ошибками.
Или другая ситуация: у вас два проекта. Один требует Node.js 18, другой — Node.js 20. Ставить оба? Использовать nvm? А если ещё Python разных версий нужен?
Проблема одна: окружение разработки не совпадает с окружением продакшена. И чем сложнее проект, тем больше несовпадений.
Можно, конечно, написать инструкцию по настройке на 3 страницы. Но её никто не читает, а если читает — половина шагов устаревает за месяц.
Что такое Docker и контейнер
Docker — это инструмент, который упаковывает приложение вместе со всем окружением в изолированный контейнер.
Контейнер — это как виртуальная машина, только легче. Он содержит всё, что нужно приложению: операционную систему (обычно минимальный Linux), рантайм, библиотеки и сам код. При этом контейнер весит мегабайты, а не гигабайты, и запускается за секунды.
Ключевые понятия:
- Image (образ) — шаблон для создания контейнера. Как ISO-файл для виртуальной машины. Образ неизменяемый.
- Container (контейнер) — работающий экземпляр образа. Можно создать сколько угодно контейнеров из одного образа.
- Dockerfile — текстовый файл с инструкциями для сборки образа. Какую ОС взять, что установить, какие файлы скопировать.
- Docker Hub — публичный реестр готовых образов. Нужен PostgreSQL? Просто скачиваете образ и запускаете.
Базовые команды
Вот минимальный набор, который нужно знать:
Скачать образ:
docker pull node:20-alpine
Скачивает образ Node.js 20 на базе Alpine Linux (самый лёгкий вариант).
Запустить контейнер:
docker run -d -p 3000:3000 --name my-app node:20-alpine
Флаг -d — запуск в фоне. -p 3000:3000 — проброс порта. --name — имя контейнера.
Посмотреть запущенные контейнеры:
docker ps
Остановить контейнер:
docker stop my-app
Посмотреть логи:
docker logs my-app
Удалить контейнер:
docker rm my-app
Пример простого Dockerfile для Node.js-приложения:
FROM node:20-alpine
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
EXPOSE 3000
CMD ["npm", "start"]
Собрать образ из Dockerfile:
docker build -t my-app .
Docker Compose: когда сервисов несколько
Реальные проекты редко состоят из одного приложения. Обычно есть база данных, кеш, может быть очередь сообщений. Запускать каждый контейнер вручную — неудобно.
Docker Compose решает эту задачу. Вы описываете все сервисы в одном файле docker-compose.yml:
services:
app:
build: .
ports:
- "3000:3000"
depends_on:
- db
- redis
environment:
DATABASE_URL: postgres://user:pass@db:5432/mydb
REDIS_URL: redis://redis:6379
db:
image: postgres:15-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: pass
POSTGRES_DB: mydb
volumes:
- pgdata:/var/lib/postgresql/data
redis:
image: redis:7-alpine
volumes:
pgdata:
Одна команда запускает всё:
docker compose up -d
И одна — останавливает:
docker compose down
Новый разработчик в команде? Клонирует репозиторий, делает docker compose up — и через минуту у него работает полное окружение. Никаких инструкций на 3 страницы.
Практические советы
Используйте alpine-образы. node:20-alpine весит около 50 МБ вместо 350 МБ у полного образа. Для большинства задач этого хватает.
Не храните данные внутри контейнера. Контейнер можно удалить и создать заново. Данные базы должны лежать в volumes — именованных томах, которые живут отдельно от контейнера.
Используйте .dockerignore. Аналог .gitignore — указывает, какие файлы не копировать в образ. Обязательно добавьте node_modules, .git, .env.
Разделяйте dev и prod конфигурации. Для разработки можно монтировать локальную папку внутрь контейнера, чтобы изменения в коде применялись без пересборки. Для продакшена — только копирование файлов.
Не запускайте процессы от root. Добавьте в Dockerfile создание отдельного пользователя — это базовая мера безопасности.
Когда Docker не нужен
Docker — не серебряная пуля. Вот когда он избыточен:
- Простой скрипт, который запускается раз в день
- Статический сайт на Tilda или WordPress
- Локальный прототип на коленке
Но как только в проекте появляется больше одного сервиса, или вы работаете в команде, или вам нужен предсказуемый деплой — Docker становится стандартом.
Итог
Docker убирает проблему «у меня работает». Вы описываете окружение один раз в Dockerfile, и оно одинаковое везде: на вашей машине, у коллеги, на сервере. Docker Compose позволяет поднять сложную инфраструктуру одной командой. Порог входа невысокий — базовые команды осваиваются за пару часов.
Если вы ещё не используете Docker — начните со своего следующего проекта. Потратите час на настройку, сэкономите десятки часов в будущем.