suchkov.tech
Интерактивная статья · с терминалом и Dockerfile-эксплейнером

Docker – быстрый старт

Денис Сучков

Docker — это инструмент, который упаковывает приложение вместе со всеми его зависимостями в изолированный «контейнер» и запускает его одинаково на любой машине. Если ты разрабатываешь бэкенд — Docker нужен будет почти везде: для локальной разработки, для тестов, для CI/CD, для прода.

В этой статье разберём базу за 20 минут — что такое контейнер и образ, основные команды CLI, и как написать свой первый Dockerfile.

Основные понятия

Docker Engine — ядро Docker'а, фоновый сервис (демон dockerd), который умеет создавать образы и контейнеры и управлять ими. Состоит из трёх частей:

  • сервер — длительно работающий процесс dockerd, который реально создаёт образы и контейнеры;
  • API — интерфейс для общения с этим процессом;
  • CLI — командная строка docker, которой ты пользуешься в терминале.
  • Dockerfile — текстовый файл с инструкциями «как собрать образ». Это рецепт.
  • Docker image — собранный по рецепту шаблон. Набор файлов и метаданных, из которого можно запускать контейнеры. Это «торт по рецепту».
  • Docker container — запущенный экземпляр образа. Изолированный процесс с собственной файловой системой и сетевым стеком. Это «съеденный кусок торта». Контейнер можно остановить, удалить, перезапустить — образ при этом остаётся.

Базовые команды — попробуй прямо здесь

Ниже — симулированный Docker-терминал. Печатай команды, нажимай Enter. В фоне уже работает контейнер nginx — попробуй docker ps, чтобы его увидеть. Дальше — docker run hello-world, docker pull redis, docker images.

docker @ playground (симуляция)● live
Docker terminal (симуляция). Введи "help" для списка команд.
Уже работает: контейнер nginx на порту 8080.

Попробуй:  docker ps   |   docker run hello-world   |   docker pull redis
$

ⓘ Это симулятор: команды не запускают настоящий Docker, но возвращают правдоподобные выводы для типичных команд.

Что важно понимать про эти команды:

  • docker run nginx делает две вещи: если образа nginx нет локально — скачивает его из Docker Hub, потом создаёт из него новый контейнер и запускает.
  • docker ps показывает только работающие контейнеры. Чтобы увидеть остановленные — нужен флаг -a (all).
  • docker stop <id> отправляет процессу внутри контейнера сигнал SIGTERM и ждёт 10 секунд. Если процесс не завершился — добивает SIGKILL. Это важно для graceful shutdown в твоих сервисах.
  • ID контейнера можно сокращать: вместо a3f9d8e1c7b2 хватит первых 3-4 символов, если они уникальны.

Полезные флаги

  • -d (detached) — запустить в фоне, не «прицепляться» к выводу контейнера. Без него docker run блокирует терминал.
  • -p HOST:CONTAINER — пробросить порт из хоста в контейнер. -p 8080:80 = «когда я обращаюсь на localhost:8080, веди меня на порт 80 внутри контейнера». Без этого порт контейнера наружу не виден.
  • -it — интерактивно + псевдо-TTY. Нужно чтобы войти в shell контейнера: docker run -it ubuntu bash.
  • --name myapp — дать контейнеру читаемое имя вместо случайного angry_einstein.
  • -v /host/path:/container/path — монтировать папку с хоста внутрь контейнера. Так данные не исчезают при пересоздании контейнера.
  • -e VAR=value — передать переменную окружения.
  • --rm — автоматически удалить контейнер после завершения. Удобно для одноразовых запусков.

Канонический пример «на каждый день»:

docker run -d --name web -p 8080:80 -v $(pwd)/html:/usr/share/nginx/html nginx

Расшифровка: запустить nginx в фоне (-d), назвать контейнер web, пробросить порт 8080 на 80, смонтировать локальную папку html внутрь контейнера в директорию, откуда nginx раздаёт файлы. Через секунду открываешь localhost:8080 и видишь свой index.html.

Свой Dockerfile

Dockerfile — это текстовый файл с инструкциями «как собрать образ». Каждая строка — отдельный шаг (слой), который Docker выполняет последовательно.

Ниже — живой Dockerfile для Go-приложения. Кликни по любой строке — справа появится объяснение, что эта инструкция делает и какие у неё подводные камни.

Интерактивный Dockerfile

Кликни по строке — справа объяснение. Можешь редактировать.

Dockerfileстрока 1

Сборка и запуск

Когда Dockerfile готов, собираем образ:

docker build -t myapp .

Здесь -t myapp — даём образу имя (тег), . в конце — путь к контексту сборки (текущая директория). Контекст — это набор файлов, которые Docker может видеть на этапе сборки. Из этого контекста инструкции COPY копируют файлы в образ.

Запускаем:

docker run -d -p 8080:8080 --name myapp myapp

Частые ошибки и проблемы

  1. Контейнер запустился и сразу остановился. Контейнер живёт ровно столько, сколько работает его основной процесс. Если основной процесс — это echo hello, контейнер живёт секунду. Чтобы держать контейнер «навсегда», основной процесс должен быть долгоживущим: nginx, ваш сервер, sleep infinity.
  2. Поменял код, пересобрал — изменения не появились. Скорее всего проблема в кешировании. Если ты меняешь только Go-файл, а перед ним стоит RUN go mod download, Docker использует кешированный слой go mod download — это нормально. Но если меняется go.mod, кеш должен слететь. Если не слетает — попробуй docker build --no-cache.
  3. Образ весит 1.5 GB. Используй базовые образы поменьше: golang:1.21-alpine вместо golang:1.21. Или ещё лучше — multi-stage builds: сборка в одном контейнере, рантайм — в маленьком scratch или alpine.
  4. Контейнер не видит сервис на хосте. Из контейнера localhost — это сам контейнер, не твой ноут. Чтобы обратиться к процессу на хосте, на Docker Desktop используй host.docker.internal, на Linux — --network=host или адрес 172.17.0.1.
  5. Данные исчезли после перезапуска. Файловая система контейнера эфемерна. Всё, что записал внутрь — теряется при удалении контейнера. Для постоянных данных используй volumes: -v mydata:/data или -v /host/path:/data.
  6. «Permission denied» при монтировании папки. Процесс в контейнере работает от UID 1 (root) или какого-то другого пользователя — он может не иметь прав на твою папку с хоста. На Linux это решается через --user $(id -u):$(id -g).

Что дальше

Базы тебе хватит, чтобы начать. Дальше копаешь по запросу:

  • Multi-stage builds — как делать маленькие production-образы (сборка в одном слое, рантайм в другом). У меня есть отдельная статья: Многоступенчатая сборка Docker.
  • Docker Compose — чтобы поднять несколько сервисов одной командой (бэкенд + Postgres + Redis).
  • Volumes и сети — управление данными и связь между контейнерами.
  • Kubernetes — следующий шаг, когда контейнеров много и их надо оркестрировать. Конспект по K8s.
Бесплатная предзапись

Забронируй место на курсе System Design

Заполни форму — когда курс будет готов, ты первым узнаешь о запуске и получишь лучшую цену. Предзапись ни к чему не обязывает.

Или напишите напрямую в Telegram.