
Введение
Я очень рад, что существует такая технология, как Docker, и внедряю её в проекты и инфраструктуру клиентов. Однако есть одно «но»: многие не понимают, что это и зачем оно нужно, а объяснять иногда достаточно сложно (особенно повторять каждый раз каждому человеку, да и есть шанс что-то упустить). В этой статье вы узнаете базу по Docker, где найти практику и актуальные знания. Технология будет полезна многим: от специалистов по безопасности до разработчиков. А сама статья будет познавательна для тех, кто только изучает работу Docker и хочет узнать ответы на вопросы, которые часто задаются на собеседованиях, где требуется Docker. Приступим!
1 серия статей по Docker. Docker Fundamentals: теория и базовая эксплуатация
Часть 1: Вводная информация
Docker — что это и зачем он нужен
Кратко: Docker — это программная платформа для разработки, доставки и запуска приложений в изолированных средах — контейнерах. Она нужна для изоляции и стабильности. А теперь попробую объяснить.
-
Стабильность
Представим, что у вас есть веб-приложение: зависимости, конфиги и важные настройки. На вашей машине всё работает идеально, но вы отправляете проект другу, и через некоторое время при попытке развернуть его друг пишет: «У меня не работает». Или другая ситуация: вы сами разворачиваете то же приложение через полгода, и что-то ломается. Обновилась версия библиотеки, поменялся пакет в репозитории, изменилась конфигурация системы. Код тот же, а результат другой.
Как же Docker решает эти проблемы? Он упаковывает приложение вместе со всем окружением в единый артефакт, который называется образ (англ. image). Внутри образа зафиксировано всё: само приложение, зависимости, конфиги и все настройки, необходимые для работы сервиса. Если в образе используется Python 3.9, то именно эта версия и будет запускаться независимо от обновлений хостовой системы. Этот образ запускается одинаково везде и всегда: на вашей машине, у друга, на сервере.
-
Изоляция
Представим, что на одном сервере нужно запустить несколько сервисов: один на 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
-
Смена фаерволла. По умолчанию используется в Ubuntu
UFW, но Docker совместим с iptables-nft и iptables-legacy. (Поэтому скачайте iptables, если не скачан.) Более опытные пользователи могут сказать, что Docker можно будет подружить с ufw (я с этим согласен), но всё же давайте будем придерживаться того, что поддерживается.sudo apt install iptables Установка. Если документация показалась сложной для установки Docker, вы можете быстро скачать через скрипт:
curl -fsSLhttps://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, но встречается он редко: данные хранятся только в памяти и на диск не записываются.
Таблица всех инструкций
Команда |
Что делает |
|---|---|
|
С какого образа начинаем сборку. Всегда первая строка. |
|
Устанавливает рабочую папку внутри контейнера. Все следующие команды выполняются в ней |
|
Копирует файлы с вашей машины в контейнер |
|
То же, что COPY, но дополнительно умеет распаковывать архивы и скачивать файлы по URL |
|
Выполняет команду во время сборки образа. Результат сохраняется в слой |
|
Команда, которая запускается, когда вы делаете |
|
Как CMD, но сложнее переопределить, и обычно используется как фиксированная точка входа контейнера |
|
Задаёт переменную окружения внутри контейнера. Приложение может её читать |
|
Переменная только для сборки. В запущенный контейнер не попадает |
|
Просто документирует, на каком порту работает приложение. Порт не открывает — это делается через |
|
Объявляет папку внутри контейнера как том. Данные в ней сохранятся после удаления контейнера (но не всегда) |
|
От имени какого пользователя запускать приложение. По умолчанию root — в продакшне так делать не стоит |
|
Добавляет метаданные к образу: автор, версия, описание. Ни на что не влияет, просто информация |
|
Docker будет периодически проверять, живо ли приложение внутри контейнера, и помечать его как healthy или unhealthy |
|
Меняет оболочку, в которой выполняются команды RUN. По умолчанию |
|
Какой сигнал послать приложению, когда контейнер останавливают. По умолчанию SIGTERM |
|
Команда, которая выполнится не сейчас, а когда кто-то другой использует этот образ как базовый |
Частая путаница? 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. Из практики могу выделить три важных момента, которые часто встречались.
Сам Docker Daemon никогда не перезапускает контейнер автоматически, если тот стал
unhealthy. Он просто меняет статус. Чтобы контейнер перезапускался по этому статусу — нужен оркестратор (Docker Swarm, если мы говорим только про Docker) или сторонние решения. Зато в Docker Composedepends_onс условиемservice_healthyбудет ждать именно этого статуса перед запуском зависимых сервисов — и это уже очень полезно.Отключение проверки. Если вы берёте чужой образ, в котором уже прописан
HEALTHCHECK(например, официальныйpostgres), ваш дочерний образ унаследует эту проверку. Если она мешает — отключается одной строкой:HEALTHCHECK NONEНе делайте проверку тяжёлой. Каждый
HEALTHCHECK— это запуск нового процесса внутри контейнера. Если поставить маленький--intervalи написать сложный скрипт с запросами к базе — это будет постоянно есть CPU. Проверка должна быть максимально лёгкой и быстрой: простой HTTP-запрос на/health, который отвечает200 OK, — идеальный вариант.
Из полезных команд я бы отметил docker ps для колонки STATUS, чтобы посмотреть healthy/unhealthy, и docker inspect <имя контейнера> — там будет полная история последних проверок.
Более подробно в документации Docker.
Основные команды (шпаргалка)
Для базового понимания стоит разобраться в основных командах. В таблице вы можете увидеть часто используемые команды. Вместо примера nginx вы пишете другой контейнер.
Категория |
Команда |
Назначение |
|---|---|---|
Контейнеры |
|
Создать и запустить контейнер из образа nginx |
Контейнеры |
|
Запустить контейнер в фоне |
Контейнеры |
|
Запустить контейнер с именем и пробросом порта |
Контейнеры |
|
Запустить контейнер и открыть терминал |
Контейнеры |
|
Запустить контейнер и автоматически удалить после завершения |
Контейнеры |
|
Запустить контейнер с политикой перезапуска |
Контейнеры |
|
Передать переменную окружения при запуске |
Контейнеры |
|
Передать переменные окружения из файла |
Контейнеры |
|
Показать запущенные контейнеры |
Контейнеры |
|
Показать все контейнеры |
Контейнеры |
|
Остановить контейнер |
Контейнеры |
|
Запустить остановленный контейнер |
Контейнеры |
|
Перезапустить контейнер |
Контейнеры |
|
Удалить контейнер |
Контейнеры |
|
Принудительно удалить контейнер |
Контейнеры |
|
Удалить все контейнеры |
Логи и отладка |
|
Показать логи |
Логи и отладка |
|
Смотреть логи в реальном времени |
Логи и отладка |
|
Логи с временными метками |
Логи и отладка |
|
Последние 100 строк логов |
Логи и отладка |
|
Войти в контейнер через Bash |
Логи и отладка |
|
Войти в контейнер через SH |
Логи и отладка |
|
Полная информация о контейнере |
Логи и отладка |
|
Использование ресурсов |
Логи и отладка |
|
Копировать файл в контейнер |
Логи и отладка |
|
Копировать файл из контейнера |
Образы |
|
Скачать образ |
Образы |
|
Список образов |
Образы |
|
Удалить образ |
Образы |
|
Посмотреть слои образа |
Образы |
|
Удалить неиспользуемые образы |
Сборка |
|
Собрать образ |
Сборка |
|
Собрать без кэша |
Сборка |
|
Передать ARG-переменную |
Docker Hub |
|
Авторизация |
Docker Hub |
|
Добавить тег |
Docker Hub |
|
Загрузить образ |
Docker Hub |
|
Скачать образ |
Сети |
|
Список сетей |
Сети |
|
Создать сеть |
Сети |
|
Запустить контейнер в сети |
Сети |
|
Подключить контейнер к сети |
Тома |
|
Список томов |
Тома |
|
Создать том |
Тома |
|
Запустить контейнер с томом |
Тома |
|
Удалить неиспользуемые тома |
Очистка |
|
Базовая очистка |
Очистка |
|
Полная очистка Docker |
Политики перезапуска (--restart)
По умолчанию, если контейнер упал, он так и остаётся остановленным. Для продакшна это неприемлемо. Docker умеет перезапускать контейнеры автоматически через флаг --restart:
Политика |
Поведение |
|---|---|
|
Не перезапускать никогда (по умолчанию) |
|
Перезапускать всегда, в том числе при старте демона Docker |
|
Как |
|
Перезапускать только если контейнер завершился с ненулевым кодом |
docker run -d --restart unless-stopped nginx
Для большинства сервисов на одиночном сервере оптимальный выбор может быть unless-stopped: контейнер поднимется после перезагрузки сервера, но не будет назойливо рестартовать, если вы сами его остановили.
Заключение и где искать практику и знания?
Изучать Docker можно по-разному. Лично я рекомендую установить Docker на ваш компьютер и работать с ним через терминал. Если не знаете, что придумать, или нужно больше знаний — обращайтесь к документации 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 ООО «МТ ФИНАНС»
askmus
Ну база прям. За шпаргалки плюс, вопросы только на собесах таких не встречал (ну пара есть ладно, самый базовый зачем нужен docker ps и в чем его различие с docker ps -a)