Back

Руководство для начинающих по образам и контейнерам Docker

Руководство для начинающих по образам и контейнерам Docker

Вы только что присоединились к frontend-команде, и все говорят о «запуске контейнеров» и «загрузке образов». Ваше React-приложение отлично работает на вашей машине, но развёртывание кажется загадкой. Docker решает именно эту проблему — и понять основы образов Docker проще, чем вы думаете.

Это руководство охватывает, что на самом деле представляют собой образы и контейнеры Docker, как они связаны друг с другом, и как использовать их в вашем frontend-процессе для локальной разработки, тестирования и простого развёртывания.

Ключевые выводы

  • Образы Docker — это шаблоны только для чтения, в то время как контейнеры — это запущенные экземпляры этих образов.
  • Используйте явные теги вроде node:20-alpine вместо latest для предсказуемых и воспроизводимых сборок.
  • Многоэтапные сборки сохраняют ваши production-образы компактными и безопасными.
  • Никогда не храните постоянные данные внутри контейнеров — используйте тома (volumes).
  • Запускайте контейнеры от имени непривилегированных пользователей и регулярно сканируйте образы на уязвимости.

Что такое образы и контейнеры Docker?

Образ Docker — это пакет только для чтения, содержащий всё необходимое для запуска приложения: код, среду выполнения, библиотеки и конфигурацию. Думайте о нём как о классе в объектно-ориентированном программировании — шаблоне, который определяет структуру, но сам по себе ничего не выполняет.

Контейнер — это запущенный экземпляр этого образа. Когда вы выполняете docker run, Docker создаёт изолированную среду из образа, где ваше приложение фактически работает. Вы можете запустить несколько контейнеров из одного образа, каждый из которых работает независимо.

Это различие между образом и контейнером Docker имеет значение: образы — это статические шаблоны, хранящиеся на диске, в то время как контейнеры — это живые процессы со своей собственной файловой системой и сетью.

Образы Docker следуют спецификации OCI (Open Container Initiative), что означает, что они работают в различных средах выполнения контейнеров — не только в Docker. Эта стандартизация обеспечивает портативность ваших образов.

Понимание реестров и тегов

Образы хранятся в реестрах — Docker Hub является наиболее распространённым публичным реестром. Когда вы ссылаетесь на образ вроде node:20-alpine, вы указываете репозиторий (node) и тег (20-alpine).

Вот что сбивает с толку новичков: тег latest — это не магия. Он не указывает автоматически на самую новую версию. Это просто тег по умолчанию, который сопровождающие образа могут обновлять, а могут и не обновлять. Всегда используйте явные теги вроде node:20-alpine для предсказуемых сборок.

Запуск вашего первого контейнера

Давайте запустим простой контейнер, используя официальный образ Node.js:

docker run -it --rm node:20-alpine node -e "console.log('Hello from Docker!')"

Флаги -it включают интерактивный режим с терминалом. Флаг --rm автоматически удаляет контейнер после его завершения.

Для более практичного примера вы можете запустить сервер разработки. Сначала создайте директорию проекта с вашим frontend-кодом, затем:

docker run -d -p 3000:3000 -v $(pwd):/app -w /app node:20-alpine sh -c "npm install && npm run dev"

Флаг -d запускает контейнер в фоновом режиме. -p 3000:3000 связывает порт 3000 внутри контейнера с портом 3000 на вашей машине. Флаг -v монтирует вашу текущую директорию в контейнер, а -w устанавливает рабочую директорию.

Создание пользовательских образов с помощью Dockerfile

Для реальных проектов вы будете создавать пользовательские образы. Вот Dockerfile для React-приложения:

FROM node:20-alpine AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80

Это демонстрирует многоэтапную сборку — ключевую практику Docker. Первый этап собирает ваше приложение; второй этап копирует только production-файлы в минимальный образ nginx. Ваш финальный образ остаётся компактным и безопасным.

Соберите и запустите его:

docker build -t my-frontend-app .
docker run -d -p 8080:80 my-frontend-app

Тома Docker и постоянство данных

Контейнеры эфемерны — когда они останавливаются, любые данные, записанные внутри них, исчезают. Для локальной разработки используйте bind-монтирование для синхронизации вашего исходного кода:

docker run -v $(pwd)/src:/app/src -p 3000:3000 my-frontend-app

Для данных, которые должны сохраняться (например, файлы базы данных), используйте именованные тома:

docker volume create app-data
docker run -v app-data:/data my-app

Понимание томов Docker и постоянства данных критически важно: никогда не храните важные данные исключительно внутри файловой системы контейнера.

Основы безопасности Docker

Несколько практик делают ваши контейнеры безопаснее:

Запускайте от имени непривилегированного пользователя. Добавьте пользователя в ваш Dockerfile:

RUN adduser -D appuser
USER appuser

Используйте минимальные базовые образы. Образы на основе Alpine имеют меньше уязвимостей, чем полные дистрибутивы.

Регулярно сканируйте образы. Инструменты вроде Docker Scout или Trivy выявляют известные уязвимости.

Никогда не встраивайте секреты в образы. Переменные окружения или инструменты управления секретами обрабатывают учётные данные — жёсткое кодирование создаёт риски безопасности, которые сохраняются в слоях образа.

Упрощение настройки нескольких контейнеров с помощью Compose

Когда вашему frontend нужны backend API и база данных локально, Docker Compose оркестрирует всё:

services:
  frontend:
    build: ./frontend
    ports:
      - "3000:3000"
  api:
    build: ./api
    ports:
      - "4000:4000"

Выполните docker compose up, и обе службы запустятся вместе. Используйте docker compose down, чтобы остановить и удалить все контейнеры.

Заключение

Образы Docker — это шаблоны; контейнеры — это запущенные экземпляры. Сохраняйте образы компактными с помощью многоэтапных сборок, используйте явные теги вместо latest, отделяйте состояние от контейнеров с помощью томов и регулярно пересобирайте образы для получения обновлений безопасности. Эти основы будут служить вам независимо от того, запускаете ли вы среду разработки или развёртываете простое frontend-приложение.

Часто задаваемые вопросы

Образ Docker — это шаблон только для чтения, содержащий код вашего приложения, зависимости и конфигурацию. Контейнер — это запущенный экземпляр этого образа. Вы можете создать несколько контейнеров из одного образа, каждый из которых работает независимо со своей собственной изолированной файловой системой и сетью.

Тег latest не обновляется автоматически до новейшей версии. Это просто тег по умолчанию, который сопровождающие могут поддерживать актуальным, а могут и не поддерживать. Использование явных тегов версий вроде node:20-alpine обеспечивает воспроизводимые сборки и предотвращает неожиданные критические изменения при обновлении образов.

Используйте тома Docker для сохранения данных вне файловой системы контейнера. Именованные тома хранят данные в месте, управляемом Docker, в то время как bind-монтирование связывается с конкретными директориями на вашей хост-машине. Никогда не полагайтесь на внутреннюю файловую систему контейнера для важных данных.

Многоэтапные сборки позволяют использовать один образ для сборки вашего приложения и другой, более компактный образ для его запуска. Это сохраняет ваши production-образы лёгкими, исключая инструменты сборки и зависимости, уменьшая как размер образа, так и потенциальные уязвимости безопасности.

Gain control over your UX

See how users are using your site as if you were sitting next to them, learn and iterate faster with OpenReplay. — the open-source session replay tool for developers. Self-host it in minutes, and have complete control over your customer data. Check our GitHub repo and join the thousands of developers in our community.

OpenReplay