Docker: образы и контейнеры
Image (образ) — неизменяемый шаблон файловой системы; container (контейнер) — запущенный изолированный процесс на основе этого образа.
Зачем нужно
Понимание разницы между образом и контейнером — основа работы с Docker. Образ строится один раз и хранится в registry; из одного образа можно запустить сколько угодно контейнеров. Слоевая система образов позволяет переиспользовать общие части и ускоряет сборку.
Где используется
- Сборка образа в CI и публикация в Docker Hub / GitHub Container Registry
- Запуск нескольких контейнеров из одного образа (horizontal scaling)
- Хранение версий образов по тегам для возможности rollback
Основной контент
Слоевая архитектура образов
FROM node:20-alpine ← базовый слой (скачивается из registry)
WORKDIR /app ← добавляет слой
COPY package*.json() ./ ← добавляет слой (кэшируется если не изменился)
RUN npm ci ← добавляет слой (самый долгий, кэшируется!)
COPY . . ← добавляет слой
CMD ["node", "index.js"] ← мета-данные, не добавляет слой
Каждый слой кэшируется. Если package.json не изменился — npm ci не перезапускается.
Многоэтапная сборка (multi-stage build)
# Этап 1: сборка
FROM node:20-alpine AS builder
WORKDIR /app
COPY package*.json() ./
RUN npm ci
COPY . .
RUN npm run build # компиляция TypeScript
# Этап 2: минимальный production-образ
FROM node:20-alpine AS production
WORKDIR /app
COPY package*.json() ./
RUN npm ci --omit=dev # только production зависимости
COPY --from=builder /app/dist ./dist
EXPOSE 3000
CMD ["node", "dist/index.js"]
docker build --target production -t myapp:prod .
Управление образами
# Список образов с деталями
docker images --format "table {{.Repository}}\t{{.Tag}}\t{{.Size}}"
# Тегирование
docker tag myapp:latest myuser/myapp:1.2.3
docker tag myapp:latest myuser/myapp:latest
# Публикация в Docker Hub
docker login
docker push myuser/myapp:1.2.3
docker push myuser/myapp:latest
# Удаление неиспользуемых образов
docker image prune -a
Управление контейнерами
# Запуск с именем и политикой перезапуска
docker run -d \
--name api \
--restart unless-stopped \
-p 3000:3000 \
myapp:latest
# Просмотр ресурсов
docker stats
# Копирование файлов из контейнера
docker cp api:/app/logs/app.log ./app.log
# Inspect: все метаданные контейнера
docker inspect api
.dockerignore
node_modules
.git
.env
*.log
dist
.DS_Store
Частые ошибки
- Не использовать multi-stage builds: production-образ содержит devDependencies и исходники TypeScript (раздувает размер в 5-10 раз)
- Копировать всё приложение до
npm ci: теряется кэш слоёв —npm ciзапускается при любом изменении кода - Запускать контейнер от root-пользователя в продакшне — риск безопасности