Антон Ларичев

Введение
Docker изменил то, как разработчики создают и доставляют приложения. Вместо того чтобы бороться с «у меня работает, а у тебя нет», Docker упаковывает приложение вместе со всеми зависимостями в изолированный контейнер.
В этом руководстве вы узнаете, что такое Docker, как его установить, создать первый образ и запустить контейнер. Также разберём docker-compose для локальной многосервисной разработки.
Что такое Docker и зачем он нужен
Docker — платформа для контейнеризации приложений. Контейнер — это изолированная среда, которая содержит приложение и все необходимые зависимости: библиотеки, переменные окружения, конфигурационные файлы.
Чем контейнер отличается от виртуальной машины:
- ВМ эмулирует целый компьютер с отдельной ОС — это тяжело и медленно
- Контейнер использует ядро хост-системы, но изолирует процессы — легко и быстро
- Контейнер запускается за секунды, ВМ — за минуты
Основные понятия:
- Image (образ) — неизменяемый шаблон, из которого создаётся контейнер. Как класс в ООП.
- Container (контейнер) — запущенный экземпляр образа. Как объект из класса.
- Dockerfile — файл с инструкциями для сборки образа.
- Registry — хранилище образов. Docker Hub — публичный реестр от Docker.
Установка Docker
Linux (Ubuntu/Debian)
# Обновляем пакеты и устанавливаем зависимости
sudo apt-get update
sudo apt-get install ca-certificates curl gnupg
# Добавляем GPG-ключ Docker
sudo install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
# Добавляем репозиторий
echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
# Устанавливаем Docker Engine
sudo apt-get update
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-compose-plugin
# Добавляем текущего пользователя в группу docker (чтобы не писать sudo)
sudo usermod -aG docker $USER
macOS и Windows
Скачайте и установите Docker Desktop с официального сайта. Он включает Docker Engine, Docker Compose и удобный GUI для управления контейнерами.
Первые шаги с Docker
Запуск первого контейнера
# Проверяем, что Docker установлен и работает
docker --version
# Запускаем тестовый контейнер — он загрузится и выведет приветствие
docker run hello-world
# Запускаем nginx и пробрасываем порт наружу
docker run -d -p 8080:80 --name my-nginx nginx
# -d — запуск в фоне (detached mode)
# -p 8080:80 — порт хоста:порт контейнера
# --name — задаём имя для удобства
Откройте браузер и перейдите на http://localhost:8080 — увидите страницу приветствия Nginx.
Основные команды
# Просмотр запущенных контейнеров
docker ps
# Просмотр всех контейнеров (включая остановленные)
docker ps -a
# Остановить контейнер
docker stop my-nginx
# Удалить контейнер
docker rm my-nginx
# Просмотр локальных образов
docker images
# Удалить образ
docker rmi nginx
# Просмотр логов контейнера в реальном времени
docker logs -f my-nginx
# Выполнить команду внутри работающего контейнера
docker exec -it my-nginx bash
# -it — интерактивный режим с псевдотерминалом
Создание своего Dockerfile
Dockerfile — набор инструкций для сборки образа. Рассмотрим пример для Node.js приложения.
# Базовый образ — Node.js 20 на Alpine Linux (минимальный размер)
FROM node:20-alpine
# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /app
# Копируем файлы зависимостей отдельно — это кэширует слой при повторной сборке
COPY package*.json ./
# Устанавливаем только продакшн-зависимости
RUN npm ci --only=production
# Копируем остальной код приложения
COPY . .
# Документируем порт (реально не пробрасывает — только для читателя Dockerfile)
EXPOSE 3000
# Команда запуска при старте контейнера
CMD ["node", "src/index.js"]
Сборка и запуск образа
# Собрать образ из текущей директории
docker build -t my-app:1.0 .
# -t — тег образа в формате имя:версия
# точка в конце — контекст сборки (текущая директория)
# Запустить контейнер из собранного образа
docker run -d -p 3000:3000 --name my-app my-app:1.0
# Проверяем ответ
curl http://localhost:3000
Файл .dockerignore
Создайте .dockerignore, чтобы не копировать лишнее в образ:
node_modules
.git
.env
*.log
dist
coverage
Docker Compose для локальной разработки
В реальных проектах приложение состоит из нескольких сервисов: бэкенд, база данных, кэш. Docker Compose позволяет описать и запустить их все одной командой.
Пример docker-compose.yml
services:
# Наше Node.js приложение
app:
build: .
ports:
- "3000:3000"
environment:
- NODE_ENV=development
- DATABASE_URL=postgresql://user:password@db:5432/mydb
depends_on:
- db
- redis
volumes:
# Монтируем исходный код для горячей перезагрузки
- .:/app
- /app/node_modules
# База данных PostgreSQL
db:
image: postgres:16-alpine
environment:
POSTGRES_USER: user
POSTGRES_PASSWORD: password
POSTGRES_DB: mydb
volumes:
# Данные сохраняются между перезапусками контейнера
- postgres_data:/var/lib/postgresql/data
ports:
- "5432:5432"
# Кэш Redis
redis:
image: redis:7-alpine
ports:
- "6379:6379"
volumes:
postgres_data:
Команды docker compose
# Запустить все сервисы в фоне
docker compose up -d
# Посмотреть логи всех сервисов
docker compose logs -f
# Остановить и удалить контейнеры
docker compose down
# Пересобрать образы и перезапустить
docker compose up -d --build
# Выполнить команду в конкретном сервисе
docker compose exec app sh
Частые ошибки
1. Запуск процессов от root внутри контейнера
По умолчанию процессы в контейнере запускаются от root. Это небезопасно в продакшне. Добавьте в Dockerfile:
# Создаём непривилегированного пользователя и переключаемся на него
RUN addgroup -S appgroup && adduser -S appuser -G appgroup
USER appuser
2. Хранение секретов в образе
Никогда не копируйте .env файлы с паролями и токенами в образ — они останутся в истории слоёв. Передавайте секреты через переменные окружения при запуске или используйте Docker Secrets.
3. Большой размер образа
Используйте многоэтапную сборку (multi-stage build): первый этап компилирует код, второй — содержит только финальные артефакты:
# Этап сборки — полный образ с инструментами разработки
FROM node:20 AS builder
WORKDIR /app
COPY . .
RUN npm ci && npm run build
# Финальный образ — только то, что нужно для запуска
FROM node:20-alpine
WORKDIR /app
COPY --from=builder /app/dist ./dist
COPY --from=builder /app/package*.json ./
RUN npm ci --only=production
CMD ["node", "dist/index.js"]
4. Использование тега latest
Тег latest меняется со временем — это ломает воспроизводимость сборок. Всегда закрепляйте конкретную версию: node:20.11-alpine3.19.
5. Отсутствие .dockerignore
Без .dockerignore в контекст сборки попадут node_modules, .git и другие ненужные файлы. Сборка замедлится, а образ вырастет в размере.
Заключение
Docker — обязательный инструмент современного разработчика. Он решает проблему несоответствия окружений, упрощает онбординг новых участников команды и делает деплой предсказуемым и воспроизводимым.
Вы освоили основы: что такое образы и контейнеры, как писать Dockerfile, как использовать Docker Compose для многосервисной разработки и каких ошибок избегать.
Следующий шаг — изучить оркестрацию контейнеров с Kubernetes для управления ими в продакшне: автоматическое масштабирование, rolling-деплои и self-healing из коробки.






Комментарии
0