Введение

Я очень рад, что существует такая технология, как Docker, и внедряю её в проекты и инфраструктуру клиентов. Однако есть одно «но»: многие не понимают, что это и зачем оно нужно, а объяснять иногда достаточно сложно (особенно повторять каждый раз каждому человеку, да и есть шанс что-то упустить). В этой статье вы узнаете базу по Docker, где найти практику и актуальные знания. Технология будет полезна многим: от специалистов по безопасности до разработчиков. А сама статья будет познавательна для тех, кто только изучает работу Docker и хочет узнать ответы на вопросы, которые часто задаются на собеседованиях, где требуется Docker. Приступим!

1 серия статей по Docker. Docker Fundamentals: теория и базовая эксплуатация

Часть 1: Вводная информация

Docker — что это и зачем он нужен

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

  1. Стабильность

    Представим, что у вас есть веб-приложение: зависимости, конфиги и важные настройки. На вашей машине всё работает идеально, но вы отправляете проект другу, и через некоторое время при попытке развернуть его друг пишет: «У меня не работает». Или другая ситуация: вы сами разворачиваете то же приложение через полгода, и что-то ломается. Обновилась версия библиотеки, поменялся пакет в репозитории, изменилась конфигурация системы. Код тот же, а результат другой.

    Как же Docker решает эти проблемы? Он упаковывает приложение вместе со всем окружением в единый артефакт, который называется образ (англ. image). Внутри образа зафиксировано всё: само приложение, зависимости, конфиги и все настройки, необходимые для работы сервиса. Если в образе используется Python 3.9, то именно эта версия и будет запускаться независимо от обновлений хостовой системы. Этот образ запускается одинаково везде и всегда: на вашей машине, у друга, на сервере.

  2. Изоляция

    Представим, что на одном сервере нужно запустить несколько сервисов: один на Python 3.9, другой на Python 3.11, третий требует PostgreSQL 14, четвёртый — PostgreSQL 16. Без Docker версии конфликтуют, библиотеки перетирают друг друга, один сервис может сломать другой. В Docker каждый контейнер живёт в своём окружении: своя файловая система, своя сеть, свои процессы и библиотеки. Они не знают о существовании друг друга и не конфликтуют.

    Помимо этого, можно явно ограничить ресурсы каждого контейнера, например, разрешить использовать не более 512 МБ памяти и половину ядра процессора. Если контейнер попытается выйти за лимит, Docker его ограничит. Один «прожорливый» сервис не положит остальные.

Это основные преимущества, за которые я рекомендую вам Docker.

Сколько ресурсов нужно, чтобы запустить Docker?

Docker работает на Linux, Windows и macOS. Я предпочитаю и рекомендую Linux.

На Linux Docker работает напрямую через ядро системы, фоновый демон потребляет от ~50 до ~100 МБ ОЗУ. На Windows и macOS запускается Docker Desktop, которому в режиме виртуальной машины нужно около 2–4 ГБ ОЗУ. Есть альтернатива: на Windows можно использовать WSL 2 + Docker Engine, потребление памяти будет поменьше, но настройка чуть сложнее.

Если встанет вопрос с обучением, например, у вас слабая машина, то рекомендую опять же перейти на Linux, чтобы сэкономить ресурсы. Для обучения (как я использовал раньше, когда у меня был слабый ноутбук) достаточно 6 ГБ оперативной памяти и 70 ГБ свободного места на диске.

Установка Docker

Здесь лучше изучить установку самостоятельно (да и в документации Docker всё расписано подробнее).

Это скачает Docker с GUI. В Windows и macOS рекомендую ещё посмотреть permission requirements под вашу ОС.

  • Скачать на Linux

Пример установки под Ubuntu

  1. Смена фаерволла. По умолчанию используется в Ubuntu UFW, но Docker совместим с iptables-nft и iptables-legacy. (Поэтому скачайте iptables, если не скачан.) Более опытные пользователи могут сказать, что Docker можно будет подружить с ufw (я с этим согласен), но всё же давайте будем придерживаться того, что поддерживается.

    sudo apt install iptables

  2. Установка. Если документация показалась сложной для установки Docker, вы можете быстро скачать через скрипт: curl -fsSL https://get.docker.com | sh

Установку вручную я всё же рекомендую научиться делать без скрипта.

После этого можете посмотреть docker version или docker --help, чтобы убедиться, что Docker скачан.

Часть 2: База теории по Docker

Начнём с терминологии

  • ★ Контейнер (англ. Container) — изолированный процесс на вашей машине со своей файловой системой, сетью и переменными окружения.

  • ★ Образ (англ. Image) — шаблон, из которого создаётся контейнер. Содержит всё необходимое для запуска приложения.

  • ★ Слои (англ. Layers) — составные части образа. Каждая инструкция в Dockerfile создаёт новый слой. Слои кэшируются и переиспользуются между образами.

  • ★ Теги (англ. Tags) — метки версий образа. Формат: имя:тег, например nginx:1.25 или python:3.11-alpine. Подробнее о том, как версионировать свои образы, будет написано ниже.

  • ★ Реестр (англ. Registry) — хранилище образов. Публичный пример — Docker Hub, откуда Docker скачивает образы по умолчанию.

  • .Dockerignore — файл, который указывает, что не нужно копировать в образ при сборке. Работает по тому же принципу, что и.gitignore. Создавайте .dockerignore всегда, даже для небольших проектов. Так вы сэкономите кучу времени, место на диске сервера и защитите себя от случайной утечки секретов (например, файла.env) в готовый публичный образ. Что обычно туда пишут? будет написано ниже.

  • ★ Тома (англ. Volumes) — механизм хранения данных вне контейнера. Данные в томе сохраняются даже после удаления контейнера. Docker сам управляет расположением тома на хосте.

  • Монтирование директорий (англ. Bind Mounts) — подключение папки с хостовой машины напрямую в контейнер. В отличие от томов, вы сами указываете путь на хосте. Подробнее о разнице между томами и bind mounts поговорим ниже.

  • ★ Сети (англ. Networks) — механизм взаимодействия контейнеров между собой и с внешним миром. По умолчанию каждый контейнер получает свой IP‑адрес внутри виртуальной сети Docker (bridge‑сеть). Подробно сети будут разобраны в следующей части серии.

  • Демон Docker (англ. Docker Daemon, Dockerd) — фоновый процесс, который управляет всем: создаёт, запускает и удаляет контейнеры. Когда вы вводите любую команду docker — она уходит именно к нему.

  • ★ Dockerfile — текстовый файл с инструкциями, как собрать образ.

  • Docker Engine — сам Docker: демон, CLI и API. То, что вы устанавливаете на Linux (или другую ОС), когда ставите Docker. ★ Docker Compose — инструмент для запуска нескольких контейнеров одной командой через YAML‑файл.

  • Контекст сборки (англ. Build Context) — папка, которую Docker отправляет демону при сборке образа. Обычно это директория, где лежит Dockerfile.

С терминологией пока достаточно для начинающего уровня, будет ещё больше, когда поговорим про Docker Swarm и безопасность Docker в следующей статье серии. ★ отмечены самые частые термины/слова, которые вы будете встречать при обсуждении вопросов в чатах DevOps/Docker и т. д. или видеть их у себя в терминале. Переходим к объяснению, зачем вообще это знать. Знать команды и понимать, как они работают, полезно, к тому же об этом могут спросить на собеседовании.

Контейнер. Он живёт ровно столько, сколько живёт его основной процесс. Завершился процесс = завершился контейнер, аналогично с удалением контейнера: удалили = изменения внутри него пропали, но образ при этом останется нетронутым. Если описывать жизненный цикл контейнера, то он начинается с образа, из него командой docker run создаётся и сразу запускается контейнер. После остановки командой docker stop контейнер не исчезает, он переходит в остановленное состояние, и его можно запустить снова через docker start. Когда контейнер больше не нужен, он удаляется командой docker rm. После удаления все изменения внутри него пропадают, образ при этом остаётся нетронутым.

Под капотом Docker использует два механизма ядра Linux:

  • Namespaces — изолируют контейнер. Каждый контейнер видит только свои процессы, свою сеть и свою файловую систему.

  • cgroups — ограничивают ресурсы. Именно через них Docker позволяет задать лимиты на CPU и память для каждого контейнера.

Образ. Он состоит из слоёв, каждая «инструкция в Dockerfile» (это команды FROM, RUN и т. д.) создаёт свой слой. Например: первый слой — это Alpine Linux, второй — Python поверх него, третий — установленные зависимости, четвёртый — код вашего приложения. И все эти слои неизменяемы, но когда вы запускаете контейнер, Docker добавляет поверх всех этих слоёв образа ещё один — изменяемый (так называемый Copy-on-Write слой: файлы из образа не копируются заранее, а только в момент, когда контейнер пытается их изменить — тогда Docker копирует файл в этот слой и меняет уже там, оригинал в образе остаётся нетронутым). Всё, что происходит внутри контейнера: создаются файлы, пишутся логи, копится кэш — всё уходит в этот верхний слой. Сам образ не трогается. Поэтому из одного образа можно запустить десять контейнеров одновременно: у каждого свой изменяемый слой, а базовые слои общие.

Из этого вытекает ещё одно преимущество, которое мы обсудили: если у вас несколько образов на базе python:3.11-alpine — слой с Python хранится на диске один раз, а не для каждого образа отдельно. Docker скачивает только те слои, которых ещё нет.

Dockerfile. В терминологии уже разобрались, что это такое; добавлю ещё информацию о командах и то, что вы можете посмотреть примеры этих Dockerfile в open-source инструментах. (Если не можете найти: Dokploy) там же вы увидите и Multi-stage builds.

Multi-stage builds — это подход, при котором в одном Dockerfile создаётся несколько этапов сборки. Например, в Dockerfile Dokploy есть этапы base, build и dokploy: сначала собирается приложение, а затем в финальный этап через COPY --from=build переносятся только нужные артефакты. Благодаря этому этапы сборки и запуска разделяются, а Dockerfile становится более гибким и удобным для сопровождения. Сначала Docker собирает всё необходимое в промежуточных этапах, а затем переносит в финальный образ только нужные артефакты. Такой подход делает Dockerfile более аккуратным, удобным для сопровождения и помогает не хранить в финальном образе лишние файлы, использовавшиеся только во время сборки.

Переменные окружения (ENV). Используются для хранения настроек приложения: адресов баз данных, портов, токенов, паролей и других параметров, задать их можно по-разному. Лично я предпочитаю использовать файл .env, где вы пишете, например, DB_PASSWORD=qwerty и всё. Но можно задавать их и через ENV в Dockerfile, и через флаг -e при запуске контейнера docker run -d -e DB_PASSWORD=secret myapp

Тег latest и почему его лучше не использовать в продакшне. Если написать docker pull nginx без указания версии, Docker скачает образ с тегом latest. Удобно, вот только latest меняется. Сегодня он может указывать на одну версию, а через месяц уже на другую.

Из-за этого один и тот же docker-compose.yml при разных деплоях может поднять разные версии приложения. Это может привести к неожиданным изменениям в работе сервиса, проблемам с совместимостью или появлению новых уязвимостей. Поэтому в продакшне лучше всегда указывать конкретный тег, например, container:1.25.5.

Теги: как версионировать свои образы

Отдельно стоит сказать про теги образов. На собеседованиях про это спрашивают редко. Единого правила нет: в одной компании используют версии, в другой — хэши коммитов, а где-то вообще смешивают несколько подходов.

Самый норм(по моему мнению) вариант — семантическое версионирование: myapp:1.4.2. Если у вас есть релизы и changelog, по такому тегу сразу понятно, что перед вами за версия приложения.

Часто встречается и другой подход — тегировать образы хэшем коммита, например myapp:a3f8c1d. Особенно это любят в CI/CD. У каждого коммита получается свой образ, поэтому потом не приходится гадать, какой именно код сейчас крутится на сервере. При необходимости можно быстро найти нужный коммит и откатиться.

Иногда в тег добавляют окружение: myapp:staging или myapp:production. Лично мне такой вариант нравится меньше(ну хотя бы информации по версии добавить), потому что возникает путаница: непонятно, что именно скрывается за этим тегом. Но если один и тот же образ последовательно проходит через несколько стендов, такой подход вполне имеет право на жизнь.

Сам я чаще встречал комбинацию версии и хэша коммита: myapp:1.4.2-a3f8c1d. На мой взгляд, здесь всё четко: видно и релиз приложения, и конкретное состояние кода, из которого собрали образ.

А вот latest для продакшна лучше не использовать. Сегодня этот тег может указывать на одну сборку, а после следующего деплоя — уже на другую. Потом начинается любимая игра: «а что вообще сейчас запущено?». Для локальной разработки и быстрых проверок latest ещё можно оставить, но в боевых окружениях лучше использовать неизменяемые теги.

.dockerignore: что туда писать

КРАТКО: Всё что не должно попасть в продакшн / в шаблон, который будет публиковаться для использование проекта другим человеком. Убирать стоит всё чувствительное и не нужное( к примеру readme.md, кеш, логи.) Docker при сборке отправляет демону всё содержимое контекста. Поэтому чем меньше лишних файлов попадёт туда, тем лучше.

Обычно .dockerignore выглядит примерно так:

.git
.gitignore
.env
.env.*
node_modules
__pycache__
*.pyc
*.pyo
.pytest_cache
.coverage
dist
build
*.log
README.md
.DS_Store

Если не знаете, что добавить в первую очередь, начните хотя бы с .git, .env и каталогов зависимостей. Репозиторий может занимать сотни мегабайт, а секретам из .env внутри образа делать нечего.

Тома и Bind Mounts: что когда использовать

С этим всё проще, чем кажется. Для баз данных я обычно беру volume: Docker сам хранит данные, и не приходится разбираться, в какой каталог на хосте они попали.

Bind mount использую в других случаях — когда нужно подключить конкретную папку с машины. Например, nginx-конфиг или директорию с проектом во время разработки.

Поэтому правило у меня одно: данные самого сервиса — volume, всё, что нужно подцепить с хоста, — bind mount.

docker run -d -v pg-data:/var/lib/postgresql/data postgres
docker run -d -v /home/user/configs:/etc/nginx/conf.d nginx

Есть ещё tmpfs mount, но встречается он редко: данные хранятся только в памяти и на диск не записываются.

Таблица всех инструкций

Команда

Что делает

FROM

С какого образа начинаем сборку. Всегда первая строка.

WORKDIR

Устанавливает рабочую папку внутри контейнера. Все следующие команды выполняются в ней

COPY

Копирует файлы с вашей машины в контейнер

ADD

То же, что COPY, но дополнительно умеет распаковывать архивы и скачивать файлы по URL

RUN

Выполняет команду во время сборки образа. Результат сохраняется в слой

CMD

Команда, которая запускается, когда вы делаете docker run. Можно переопределить

ENTRYPOINT

Как CMD, но сложнее переопределить, и обычно используется как фиксированная точка входа контейнера

ENV

Задаёт переменную окружения внутри контейнера. Приложение может её читать

ARG

Переменная только для сборки. В запущенный контейнер не попадает

EXPOSE

Просто документирует, на каком порту работает приложение. Порт не открывает — это делается через -p при запуске

VOLUME

Объявляет папку внутри контейнера как том. Данные в ней сохранятся после удаления контейнера (но не всегда)

USER

От имени какого пользователя запускать приложение. По умолчанию root — в продакшне так делать не стоит

LABEL

Добавляет метаданные к образу: автор, версия, описание. Ни на что не влияет, просто информация

HEALTHCHECK

Docker будет периодически проверять, живо ли приложение внутри контейнера, и помечать его как healthy или unhealthy

SHELL

Меняет оболочку, в которой выполняются команды RUN. По умолчанию /bin/sh

STOPSIGNAL

Какой сигнал послать приложению, когда контейнер останавливают. По умолчанию SIGTERM

ONBUILD

Команда, которая выполнится не сейчас, а когда кто-то другой использует этот образ как базовый

Частая путаница? CMD, ENTRYPOINT, ARG, ENV

Эти 4 команды часто путают между собой (и по другим причинам) и задают вопросы на собеседованиях про их различие, поэтому стоит вкратце о них сказать и про их отличия.

  • CMD — команда, которая запускается по умолчанию, когда вы делаете docker run. Её можно переопределить прямо в команде запуска.

  • ENTRYPOINT — команда, которая выполняется всегда, независимо от того, что вы передаёте в docker run. Если указать CMD вместе с ENTRYPOINT, CMD становится аргументами по умолчанию для ENTRYPOINT.

Когда использовать что: если контейнер всегда должен запускать одно конкретное приложение и вы хотите только менять аргументы, используйте ENTRYPOINT. Если хотите полную гибкость и возможность запустить внутри контейнера вообще что угодно используйте CMD.

  • ARG — переменная, которая существует только во время сборки образа. В запущенный контейнер она не попадает. Удобно, когда нужно параметризировать сборку, например, передать версию приложения или окружение.

  • ENV — переменная окружения, которая доступна и во время сборки, и в запущенном контейнере. Именно через неё приложение получает конфигурацию: порт, адрес базы данных, режим работы.

Когда использовать что: всё, что нужно приложению во время работы — ENV. Всё, что нужно только во время сборки образа — ARG.

Кэш слоёв

Docker кэширует все слои и инвалидируется каскадно, т. е. изменился один слой — все последующие пересобираются заново. Зачем это знать? На практике, если взять активную разработку, то образ постоянно пересобирается, если кэш не работает, то каждая сборка занимает ~минуты. Поэтому порядок pip install можно сделать по такому принципу: сначала то, что меняется редко, потом то, что меняется часто. Зависимости меняются раз в несколько дней, код — несколько раз в час. Поэтому зависимости копируем и устанавливаем первыми, код копируем в самом конце.

Плохой порядок — pip install запускается при каждом изменении кода:

COPY . .
RUN pip install -r requirements.txt

Хороший порядок — pip install кэшируется отдельно от кода:

COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .

RUN и слои

Когда используется RUN, он создаёт отдельный слой, из-за чего каждый слой увеличит размер образа. Это критично при работе с пакетными менеджерами по типу apt. apt — он оставляет кэш на диске. Если удалить этот кэш в следующем RUN — он уже зафиксирован в предыдущем слое и никуда не денется. Образ будет весить больше. Поэтому установка и очистка должны быть в одной команде — только тогда кэш не попадёт в образ.

# Плохо — три слоя, кэш apt остаётся в образе навсегда
RUN apt-get update
RUN apt-get install -y curl git
RUN rm -rf /var/lib/apt/lists/*

# Хорошо — один слой, кэш удалён в той же команде
RUN apt-get update && \
    apt-get install -y curl git && \
    rm -rf /var/lib/apt/lists/*

USER: не стоит запускать от root

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

Как тогда это сделать? Тут всё зависит от вашего сценария (того, как выглядит инфраструктура), можно создать пользователя в Dockerfile, например, на Ubuntu:

RUN groupadd -r appgroup && useradd -r -g appgroup appuser
USER appuser
# После USER все последующие команды в Dockerfile и сам процесс контейнера будут выполняться от этого пользователя.

Или взять Rootless-режим Docker — это решение запустит сам Docker daemon не от root, а от обычного пользователя. Обычно после установки Docker с помощью curl -fsSL https://get.docker.com | sh у вас появится окно с предложением настроить rootless-режим одной командой: dockerd-rootless-setuptool.sh install. Подробнее в официальной документации.

Rootless-режим имеет ряд ограничений, поэтому изучите, нужен он вам или нет. Ниже то самое «окно».

================================================================================

To run Docker as a non-privileged user, consider setting up the
Docker daemon in rootless mode for your user:

    dockerd-rootless-setuptool.sh install

Visit https://docs.docker.com/go/rootless/ to learn about rootless mode.


To run the Docker daemon as a fully privileged service, but granting non-root
users access, refer to https://docs.docker.com/go/daemon-access/

WARNING: Access to the remote API on a privileged Docker daemon is equivalent
         to root access on the host. Refer to the 'Docker daemon attack surface'
         documentation for details: https://docs.docker.com/go/attack-surface/

================================================================================

HEALTHCHECK

По умолчанию Docker считает контейнер живым, если процесс внутри него запущен. Но процесс может работать, а приложение при этом зависнуть, уйти в дедлок (мёртвая блокировка — ситуация, когда два или больше процесса/потока бесконечно ждут друг друга и никто из них не может продолжить работу) или перестать отвечать на запросы. Docker об этом не узнает и продолжит спокойно считать контейнер здоровым. Поэтому с помощью HEALTHCHECK Docker периодически выполняет указанную команду и по её результату помечает контейнер как healthy или unhealthy. Из практики могу выделить три важных момента, которые часто встречались.

  1. Сам Docker Daemon никогда не перезапускает контейнер автоматически, если тот стал unhealthy. Он просто меняет статус. Чтобы контейнер перезапускался по этому статусу — нужен оркестратор (Docker Swarm, если мы говорим только про Docker) или сторонние решения. Зато в Docker Compose depends_on с условием service_healthy будет ждать именно этого статуса перед запуском зависимых сервисов — и это уже очень полезно.

  2. Отключение проверки. Если вы берёте чужой образ, в котором уже прописан HEALTHCHECK (например, официальный postgres), ваш дочерний образ унаследует эту проверку. Если она мешает — отключается одной строкой: HEALTHCHECK NONE

  3. Не делайте проверку тяжёлой. Каждый HEALTHCHECK — это запуск нового процесса внутри контейнера. Если поставить маленький --interval и написать сложный скрипт с запросами к базе — это будет постоянно есть CPU. Проверка должна быть максимально лёгкой и быстрой: простой HTTP-запрос на /health, который отвечает 200 OK, — идеальный вариант.

Из полезных команд я бы отметил docker ps для колонки STATUS, чтобы посмотреть healthy/unhealthy, и docker inspect <имя контейнера> — там будет полная история последних проверок.

Более подробно в документации Docker.

Основные команды (шпаргалка)

Для базового понимания стоит разобраться в основных командах. В таблице вы можете увидеть часто используемые команды. Вместо примера nginx вы пишете другой контейнер.

Категория

Команда

Назначение

Контейнеры

docker run nginx

Создать и запустить контейнер из образа nginx

Контейнеры

docker run -d nginx

Запустить контейнер в фоне

Контейнеры

docker run -d --name my-nginx -p 8080:80 nginx

Запустить контейнер с именем и пробросом порта

Контейнеры

docker run -it ubuntu bash

Запустить контейнер и открыть терминал

Контейнеры

docker run --rm alpine echo "hello"

Запустить контейнер и автоматически удалить после завершения

Контейнеры

docker run -d --restart unless-stopped nginx

Запустить контейнер с политикой перезапуска

Контейнеры

docker run -d -e KEY=value myapp

Передать переменную окружения при запуске

Контейнеры

docker run -d --env-file .env myapp

Передать переменные окружения из файла

Контейнеры

docker ps

Показать запущенные контейнеры

Контейнеры

docker ps -a

Показать все контейнеры

Контейнеры

docker stop my-nginx

Остановить контейнер

Контейнеры

docker start my-nginx

Запустить остановленный контейнер

Контейнеры

docker restart my-nginx

Перезапустить контейнер

Контейнеры

docker rm my-nginx

Удалить контейнер

Контейнеры

docker rm -f my-nginx

Принудительно удалить контейнер

Контейнеры

docker rm $(docker ps -a -q)

Удалить все контейнеры

Логи и отладка

docker logs my-nginx

Показать логи

Логи и отладка

docker logs -f my-nginx

Смотреть логи в реальном времени

Логи и отладка

docker logs -t my-nginx

Логи с временными метками

Логи и отладка

docker logs --tail 100 my-nginx

Последние 100 строк логов

Логи и отладка

docker exec -it my-nginx bash

Войти в контейнер через Bash

Логи и отладка

docker exec -it my-nginx sh

Войти в контейнер через SH

Логи и отладка

docker inspect my-nginx

Полная информация о контейнере

Логи и отладка

docker stats my-nginx

Использование ресурсов

Логи и отладка

docker cp nginx.conf my-nginx:/etc/nginx/nginx.conf

Копировать файл в контейнер

Логи и отладка

docker cp my-nginx:/var/log/nginx/access.log ./access.log

Копировать файл из контейнера

Образы

docker pull nginx:1.25

Скачать образ

Образы

docker images

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

Образы

docker rmi nginx:1.25

Удалить образ

Образы

docker history nginx:1.25

Посмотреть слои образа

Образы

docker image prune -a

Удалить неиспользуемые образы

Сборка

docker build -t myapp:1.0 .

Собрать образ

Сборка

docker build --no-cache -t myapp:1.0 .

Собрать без кэша

Сборка

docker build --build-arg VERSION=2.0 -t myapp:2.0 .

Передать ARG-переменную

Docker Hub

docker login

Авторизация

Docker Hub

docker tag myapp:1.0 username/myapp:1.0

Добавить тег

Docker Hub

docker push username/myapp:1.0

Загрузить образ

Docker Hub

docker pull username/myapp:1.0

Скачать образ

Сети

docker network ls

Список сетей

Сети

docker network create my-network

Создать сеть

Сети

docker run -d --network my-network myapp

Запустить контейнер в сети

Сети

docker network connect my-network my-nginx

Подключить контейнер к сети

Тома

docker volume ls

Список томов

Тома

docker volume create pg-data

Создать том

Тома

docker run -d -v pg-data:/var/lib/postgresql/data postgres

Запустить контейнер с томом

Тома

docker volume prune

Удалить неиспользуемые тома

Очистка

docker system prune

Базовая очистка

Очистка

docker system prune -a --volumes

Полная очистка Docker

Политики перезапуска (--restart)

По умолчанию, если контейнер упал, он так и остаётся остановленным. Для продакшна это неприемлемо. Docker умеет перезапускать контейнеры автоматически через флаг --restart:

Политика

Поведение

no

Не перезапускать никогда (по умолчанию)

always

Перезапускать всегда, в том числе при старте демона Docker

unless-stopped

Как always, но не перезапускает, если контейнер был остановлен вручную через docker stop

on-failure

Перезапускать только если контейнер завершился с ненулевым кодом

docker run -d --restart unless-stopped nginx

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

Заключение и где искать практику и знания?

Изучать Docker можно по-разному. Лично я рекомендую установить Docker на ваш компьютер и работать с ним через терминал. Если не знаете, что придумать, или нужно больше знаний — обращайтесь к документации Docker!

  1. Практика под разные сценарии

  2. Документация Docker

На этом базовое знакомство с Docker можно считать завершённым. В этой статье мы разобрали, зачем нужен Docker, какие проблемы он решает, как устроены контейнеры и образы, что такое Dockerfile, слои, кэширование, multi-stage builds, HEALTHCHECK и .dockerignore, а также рассмотрели основные команды, политики перезапуска и передачу переменных окружения. В серии статей по Docker от opensophy мы также рассмотрим следующие темы:

  • Часть 1 — Теория и базовая эксплуатация: что такое Docker и зачем он нужен, контейнеры и образы, Docker Engine, Dockerfile и его основные инструкции, слои и кэширование, жизненный цикл контейнера, .dockerignore, переменные окружения (ARG и ENV), CMD и ENTRYPOINT, HEALTHCHECK, политики перезапуска, запуск контейнеров не от root и основные команды Docker.

  • Часть 2 — Хранение данных в Docker: volumes, bind mounts, tmpfs, сравнение подходов, сценарии использования и управление данными контейнеров.

  • Часть 3 — Сети Docker: типы сетей (bridge, host, none, overlay), публикация портов, DNS между контейнерами и service discovery.

  • Часть 4 — Registry и Docker Compose: push/pull образов, приватные реестры, структура Compose-файла, depends_on, env_file, переменные окружения и profiles.

  • Часть 5 — Безопасность: rootless Docker, user namespaces, capabilities, seccomp, secrets и read-only filesystem.

  • Часть 6 — Docker Swarm: nodes, services, stacks, overlay-сети, rolling updates и rollback.

  • Часть 7 — Оптимизация: углублённый multi-stage, BuildKit cache mounts, .dockerignore, уменьшение размера образов, сравнение alpine, distroless и scratch.

  • Часть 8 — Docker под капотом: архитектура Docker, containerd, runc, OCI, cgroups, namespaces и работа BuildKit.

Если у вас есть идеи для следующих материалов или темы, которые вызывают сложности при работе с Docker, напишите о них в комментариях. Возможно, именно они станут основой для следующих статей этой серии.

© 2026 ООО «МТ ФИНАНС»

Комментарии (1)


  1. askmus
    17.06.2026 13:25

    Ну база прям. За шпаргалки плюс, вопросы только на собесах таких не встречал (ну пара есть ладно, самый базовый зачем нужен docker ps и в чем его различие с docker ps -a)