Docker для начинающих: что это такое и как пользоваться. daemon.. daemon. DevOps.. daemon. DevOps. docker.. daemon. DevOps. docker. docker desktop.. daemon. DevOps. docker. docker desktop. docker hub.. daemon. DevOps. docker. docker desktop. docker hub. docker run.. daemon. DevOps. docker. docker desktop. docker hub. docker run. docker контейнер.. daemon. DevOps. docker. docker desktop. docker hub. docker run. docker контейнер. docker установка.. daemon. DevOps. docker. docker desktop. docker hub. docker run. docker контейнер. docker установка. docker-compose.. daemon. DevOps. docker. docker desktop. docker hub. docker run. docker контейнер. docker установка. docker-compose. dockerfiles.. daemon. DevOps. docker. docker desktop. docker hub. docker run. docker контейнер. docker установка. docker-compose. dockerfiles. entrypoint.. daemon. DevOps. docker. docker desktop. docker hub. docker run. docker контейнер. docker установка. docker-compose. dockerfiles. entrypoint. Блог компании Нетология.. daemon. DevOps. docker. docker desktop. docker hub. docker run. docker контейнер. docker установка. docker-compose. dockerfiles. entrypoint. Блог компании Нетология. Веб-разработка.. daemon. DevOps. docker. docker desktop. docker hub. docker run. docker контейнер. docker установка. docker-compose. dockerfiles. entrypoint. Блог компании Нетология. Веб-разработка. Виртуализация.. daemon. DevOps. docker. docker desktop. docker hub. docker run. docker контейнер. docker установка. docker-compose. dockerfiles. entrypoint. Блог компании Нетология. Веб-разработка. Виртуализация. Системное администрирование.

Статей про Docker много не бывает.

В этом материале мы разберём базу: что такое Docker, как он работает и зачем нужен, а затем пошагово пройдём путь от установки до запуска первого контейнера.

С подготовкой статьи помог:

Docker для начинающих: что это такое и как пользоваться - 1

Андрей Хомутов

Эксперт-разработчик в Ростелеком ИТ, дипломный руководитель в Нетологии (Python, JS), эксперт в ИТ–школе Ростелекома (DevOps)

Для навигации:

Что такое Docker простыми словами

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

Docker решает эту проблему — он создаёт единый и воспроизводимый способ запускать приложения.

Основная идея: Docker — это платформа контейнеризации. Она позволяет упаковать приложение вместе со всеми зависимостями в изолированную среду — контейнер

Такой контейнер можно запустить где угодно: на локальной машине, сервере или в облаке, и результат всегда будет одинаковым.

Чем отличается виртуализация от контейнеризации

До появления Docker основным способом изоляции приложений были виртуальные машины. 

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

Подход надёжный, но тяжёлый. Каждая ВМ занимала сотни мегабайт или гигабайты памяти, запускалась медленно и требовала отдельного обслуживания.

Docker работает иначе. Он использует подход OS-level virtualization — контейнеризацию на уровне операционной системы. Вместо того чтобы поднимать отдельную ОС под каждое приложение, Docker создаёт изолированные контейнеры, которые делят ядро хостовой системы, но имеют собственное пространство процессов, файлов и сетей.

Если упрощённо:

  • виртуальная машина изолирует железо и поднимает целую операционную систему;

  • контейнер изолирует процессы в рамках одной ОС.

Как это выглядит на схеме:

Источник

5 причин, зачем нужен Docker

1. Стабильное окружение. Docker гарантирует, что приложение будет работать одинаково везде — на ноутбуке разработчика, тестовом сервере или в продакшене. Всё, что нужно для запуска, уже собрано в контейнер, поэтому код не зависит от различий в системах и настройках.

2. Лёгкость и скорость. Контейнеры используют общее ядро операционной системы и не создают отдельную копию ОС. За счёт этого они занимают меньше места и запускаются за секунды. Один сервер может без труда обслуживать десятки контейнеров.

3. Масштабирование. При росте нагрузки можно просто запустить дополнительные контейнеры — система быстро увеличит мощность и перераспределит ресурсы без изменения кода.

4. Изоляция процессов. Каждый контейнер работает независимо от других. Если в одном произойдёт сбой или утечка памяти, это не затронет другие контейнеры и систему в целом.

5. Удобная интеграция в CI/CD. Контейнеры уже стали стандартом в современных пайплайнах. Приложение можно собрать, протестировать и запустить в одинаковой среде — от локальной машины до продакшена. Благодаря этому меньше неожиданных багов, а релизы проходят быстрее и спокойнее.

Архитектура Docker: как он устроен и как работает

В основе Docker лежит Docker Engine — система, которая управляет контейнерами, образами, сетями и томами. Она состоит из трёх ключевых компонентов: 

  1. CLI (Command Line Interface) — интерфейс командной строки. 

  2. Docker Daemon (dockerd) — фоновый процесс, который выполняет все реальные действия: создаёт, запускает и удаляет контейнеры.

  3. REST API — интерфейс, который предоставляет Docker Daemon для управления. В локальной установке CLI общается с демоном напрямую через сокет, но API следует REST-архитектуре.

Когда вы вводите команду вроде docker run, клиент CLI отправляет запрос в dockerd через сокет. Фоновый процесс получает эту команду, проверяет наличие нужного образа, готовит окружение, настраивает сеть, монтирует тома и запускает контейнер. Вся работа по созданию и управлению контейнерами происходит именно внутри демона (Docker Daemon) — он оркестрирует остальные части системы.

Внутри dockerd используются вспомогательные среды:

  • containerd отвечает за жизненный цикл контейнеров — создание, запуск, остановку и удаление

  • runc делает сам запуск контейнера: изолирует процессы и использует механизмы ядра Linux  которые отвечают за изоляцию и контроль ресурсов (namespaces, cgroups и другие). О них поговорим дальше.

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

При этом работающие контейнеры не зависят от dockerd: если демон перезапустить, они продолжат работу — за них отвечает containerd.

Вся эта цепочка выглядит так:  CLI → Docker Daemon (dockerd) → containerd → runc → процессы контейнера.

Docker Desktop

Архитектура Docker отличается в зависимости от операционной системы.

На Linux Docker Engine устанавливается напрямую и работает как системная служба (systemd). Об этом писали выше.

На Windows и macOS контейнеризация не встроена в ядро, поэтому Docker запускается через Docker Desktop.

Это настольное приложение, которое устанавливает Docker Engine внутри лёгкой виртуальной машины (в Windows — через WSL 2, в macOS — через HyperKit или Apple Virtualization Framework) и предоставляет удобный интерфейс для управления контейнерами, образами и настройками.

Docker Desktop объединяет всё в единую среду:

  • внутри работает Linux с установленным Docker Engine;

  • снаружи доступны привычный CLI и графический интерфейс;

  • настройки сети, проброс портов, управление томами и обновления выполняются автоматически.

Для новичков это самый удобный способ начать работу — установить Docker Desktop и сразу перейти к практике, без ручной настройки окружения.

Как Docker работает с образами

Контейнеры запускаются из образов (image) — шаблонов, в которых уже собраны все зависимости, библиотеки и настройки, нужные приложению.

Образ состоит из слоёв, и каждый слой — это отдельный шаг сборки: установка пакета, копирование файлов, настройка окружения.

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

При сборке Docker складывает слои в определённом порядке и объединяет их в единую файловую систему с помощью драйвера overlay2. Он накладывает слои друг на друга так, что контейнер видит их как один диск, хотя физически это отдельные части.

Главное преимущество такого подхода — повторное использование слоёв. Если два образа используют один и тот же базовый слой, Docker хранит его на диске только один раз. 

Например, слой ubuntu:20.04 — это минимальная версия Ubuntu, собранная специально для Docker. В нём нет лишних программ, только базовая файловая система Linux. Его используют сотни тысяч других образов, но на диске у разработчика этот слой лежит в единственном экземпляре, и Docker просто ссылается на него.

Это экономит место и ускоряет работу: если слой уже есть, Docker не скачивает его повторно.

Как работает кэширование слоёв при сборке образа

Когда Docker собирает образ из Dockerfile, он проходит инструкции сверху вниз и создаёт слой для каждой из них. 

Источник

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

Из-за этого порядок инструкций в Dockerfile критически важен:

  • то, что меняется редко (установка системных пакетов, базовые настройки), лучше размещать выше;

  • то, что меняется часто (исходный код приложения), — ниже.

Например:

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install -r requirements.txt
COPY . .

Если изменился только код, Docker пересоберёт только последний слой, а установку зависимостей возьмёт из кэша.

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

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

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

Чтобы данные не пропадали между перезапусками, Docker хранит их вне контейнера, но с доступом к ним изнутри. Делается это двумя способами:

  • С помощью томов (volumes) — Docker создаёт отдельные области на диске и управляет ими. Контейнер может читать данные из тома и записывать их в него, а при удалении контейнера том остаётся. 

  • С помощью монтирований (bind mounts) — к контейнеру подключается папка на хостовой системе. Например, можно смонтировать локальный каталог с кодом, чтобы контейнер работал с ним напрямую.

Хранилища образов: Docker Hub и Registry

Docker хранит образы в реестрах (registries) — это серверы, которые принимают, хранят и отдают образы по запросу.

Работают они по простому принципу: при сборке образа команда docker build сохраняет его локально, а при публикации (docker push) отправляет копию в выбранный реестр (как если бы вы выкладывали проект в GitHub). Позже этот же образ можно скачать (docker pull) на другой машине и запустить как контейнер.

Самый известный и используемый реестр — Docker Hub. В нём размещаются миллионы готовых образов: как официальные (от Docker и разработчиков языков или фреймворков), так и пользовательские. Например, образы nginx, Redis, Python, PostgreSQL — все они загружаются именно оттуда.

Hub также поддерживает приватные репозитории, если образ должен оставаться внутри команды.

Для корпоративных сценариев Docker предлагает установить собственный Docker Registry. Он разворачивается локально или в облаке, работает по тому же API, что и Hub, и поддерживает аутентификацию, разграничение прав и контроль версий образов. Это полезно, когда образы содержат закрытый код или конфигурации, которые нельзя выкладывать в публичный доступ.

Жизненный цикл Docker-образа:

Схема показывает, как образ собирается из Dockerfile, сохраняется локально, загружается в реестр (push), скачивается обратно (pull) и запускается как контейнер. Источник

Схема показывает, как образ собирается из Dockerfile, сохраняется локально, загружается в реестр (push), скачивается обратно (pull) и запускается как контейнер. Источник

Каждый образ в реестре состоит из манифеста и набора слоёв. 

Манифест — это файл-описание, в котором указано, какие слои входят в образ и как их собрать. Сами слои хранятся отдельно — как архивы, каждый со своим уникальным идентификатором (sha256).

При загрузке или скачивании Docker проверяет, не были ли повреждены файлы образа. 

Каждый слой имеет свою контрольную сумму (sha256), и система сверяет их перед установкой. Если хотя бы один байт отличается от ожидаемого, хэш не совпадает — и такой образ не принимается. Так Docker гарантирует, что загруженные данные точно совпадают с оригиналом.

У каждого образа есть тег — вроде latest, v1.0 или dev. Тег — это просто метка, которая указывает на конкретную версию образа. Но за этой меткой всегда стоит digest — уникальный хэш (sha256), по которому Docker определяет точный набор слоёв. 

Даже если тег изменится, digest остаётся прежним — и Docker понимает, какой именно образ нужно использовать.

Сеть контейнеров

При запуске Docker автоматически подключает контейнер к внутренней виртуальной сети. По умолчанию используется bridge-сеть — изолированная среда, где каждый контейнер получает свой IP-адрес и может обмениваться данными с другими участниками этой сети.

С точки зрения контейнера это выглядит как отдельная машина с полноценным сетевым интерфейсом, маршрутизацией и DNS.

Bridge-сеть создаётся на стороне хоста: Docker поднимает виртуальный интерфейс, назначает подсеть и настраивает NAT, чтобы контейнеры могли выходить в интернет. 

Как контейнеры находят друг друга внутри сети

В пользовательских bridge-сетях Docker поднимает встроенный DNS-сервер. Благодаря этому контейнеры могут обращаться друг к другу по имени, а не по IP-адресу.

Например, если в одной сети запущены два контейнера — web и db, — то приложение внутри web может подключиться к базе по адресу db:5432. Docker сам сопоставит имя контейнера с его текущим IP-адресом, так что вручную настраивать адреса не нужно.

Доступ к контейнеру снаружи

Если приложению нужно принимать запросы извне, при запуске указывают флаг -p, чтобы пробросить порт хоста внутрь контейнера (например, -p 8080:80 делает порт 80 контейнера доступным по адресу 8080 на хосте).

Кроме стандартной сети есть и другие режимы:

  • host — контейнер работает в сетевом пространстве хоста и использует его IP-адрес и интерфейсы. Режим без изоляции, зато с максимальной производительностью. Подходит, если сервису нужен прямой доступ к сети.

  • none — сеть полностью отключена. Контейнер не получает IP, не выходит в интернет и не принимает входящие запросы. Подходит для задач, которые работают изолированно и не используют сеть. 

  • overlay — объединяет контейнеры, запущенные на разных машинах, в одну виртуальную сеть. Такой тип используется, когда приложение развёрнуто на нескольких серверах и между ними нужно наладить связь.

  • macvlan — каждому контейнеру назначается собственный MAC-адрес, и в локальной сети он виден как отдельное устройство. Это удобно для тестирования сетевых сервисов или если контейнер должен работать наравне с другими машинами.

Сетью управляет Docker Daemon: он создаёт интерфейсы, подключает контейнеры и автоматически настраивает сетевые правила.Благодаря этому контейнеры остаются изолированными друг от друга, но при этом могут безопасно взаимодействовать через чётко заданные правила.

Логи и события

Все процессы внутри контейнера работают так же, как в обычной системе Linux. Всё, что они выводят в стандартные потоки (stdout и stderr), Docker перенаправляет в драйвер логирования — систему, которая отвечает за сбор и хранение логов.

По умолчанию используется драйвер json-file: логи записываются на хосте в файл в формате JSON. Это удобно для локальной отладки и просмотра через команду docker logs.

В продакшене часто выбирают другие драйверы:

  • journald — чтобы писать логи в системный журнал Linux;

  • syslog — для отправки логов на внешний сервер;

  • fluentd — для сбора и анализа данных в распределённых системах.

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

Помимо логов Docker фиксирует события — всё, что происходит в системе: запуск или остановка контейнера, создание или удаление, загрузка образа, подключение тома. Эти данные доступны через API или команду docker events.

На практике события используют для мониторинга и интеграций: например, CI/CD-система может автоматически запускать тесты при создании контейнера или отправлять уведомления о сбоях.

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

Безопасность 

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

Namespaces

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

Например, процесс с PID 1 внутри контейнера не имеет ничего общего с системным PID 1 на хосте.

То же и с сетью: у контейнера свой IP и таблицы маршрутов, и он не видит соседей, пока их явно не объединят в одну сеть.

Cgroups (control groups)

Отвечают за контроль ресурсов. Они задают, сколько CPU, оперативной памяти и дисковых операций контейнер может использовать. 

Если приложение начнёт потреблять слишком много, cgroups ограничат его, не давая перегрузить систему или повлиять на другие контейнеры.

Помимо этого, Docker использует дополнительные механизмы безопасности:

  • Capabilities — система тонкой настройки прав. Она ограничивает возможности root-пользователя внутри контейнера. Например, процесс может записывать файлы, но не может менять сетевые настройки.

  • AppArmor и SELinux — инструменты контроля доступа. Они определяют, какие файлы и операции разрешены процессам контейнера.

  • seccomp — фильтр системных вызовов, который блокирует потенциально опасные обращения к ядру, например попытки загрузить модули или изменить сетевые интерфейсы.

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

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

На чём написан Docker

Docker написан на Go — простом и быстром языке, удобном для создания системных инструментов. На нём легко работать с потоками и собирать программы, которые запускаются без внешних библиотек.

На Go построены все основные части Docker:

  • dockerd — демон, который принимает команды и управляет контейнерами;

  • containerd — служба, отвечающая за запуск и работу контейнеров;

  • runc — утилита, которая создаёт изолированные процессы в Linux;

  • BuildKit — инструмент для сборки образов.

Docker использует стандарты OCI (Open Container Initiative). Они описывают, из чего состоит контейнер и как его запускать. Поэтому образы, собранные в Docker, можно использовать и в других системах — например, в Podman или CRI-O.

Исходный код Docker открыт и распространяется по лицензии Apache 2.0. Она разрешает использовать код в любых целях — в личных, учебных или коммерческих проектах. Можно изменять исходники, собирать собственные версии Docker и включать его части в другие продукты. Единственное требование — сохранять уведомление об авторских правах, текст лицензии и указывать, если вносились изменения.

Имя и логотип Docker использовать без разрешения нельзя.

Основные понятия Docker: краткий справочник

Мы уже разобрались, как устроен Docker и из чего он состоит.

Теперь соберём ключевые термины в одном месте, чтобы было проще ориентироваться, когда перейдём к практике.

Образ (Image) 

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

Образ не меняется — Docker использует его как основу и добавляет поверх слой, куда попадают изменения, сделанные во время работы. Так один и тот же образ можно использовать многократно, не затрагивая исходное содержимое.

Контейнер (Container)

Это изолированная среда, в которой работает приложение. Контейнер можно запускать, останавливать и удалять, не затрагивая исходный образ.

Когда он удаляется, его данные исчезают — поэтому для постоянного хранения используется следующий механизм.

Том (Volume) 

Это место для данных, которые должны сохраняться между перезапусками. Тома подключаются к контейнерам как внешние диски: всё, что записано в них, остаётся даже после удаления контейнера.

Так обычно хранят базы данных, логи и другие важные файлы.

Сеть (Network) 

Отвечает за взаимодействие контейнеров между собой и с внешним миром. Docker автоматически создаёт bridge-сеть, где каждый контейнер получает свой IP-адрес.

Можно объединять контейнеры в собственные сети или, наоборот, изолировать их, если требуется полная автономность.

Реестр (Registry) 

Реестр — это место, где хранятся Docker-образы. 

Публичный вариант — Docker Hub, в нём размещены миллионы готовых сборок, включая официальные (nginx, Redis, Python).  Если образы должны оставаться внутри компании, разворачивают собственный Docker Registry — тот же сервер хранения, но с ограниченным доступом.

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

Чтобы начать работать с Docker, нужно установить Docker Engine. В него входят фоновый процесс dockerd, интерфейс командной строки и набор инструментов для работы с образами и сетями.

На macOS и Windows установка выполняется через приложение Docker Desktop. Скачайте его с официального сайта

На Linux Docker устанавливается из официальных репозиториев пакетов.

Для Debian и Ubuntu команда выглядит так:

sudo apt update
sudo apt install docker-ce docker-ce-cli containerd.io

Подробные инструкции для других дистрибутивов есть в документации Docker.

Проверка установки

После установки убедитесь, что Docker работает корректно.  Для этого выполните команду:

docker version

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

Client:
 Version:           28.4.0
 API version:       1.51
 Go version:        go1.25.1
 Git commit:        d8eb465f86
 OS/Arch:           linux/amd64

Server:
 Engine:
  Version:          28.4.0
  API version:      1.51 (minimum version 1.24)
  Go version:       go1.25.1
 containerd:
  Version:          v2.1.4
 runc:
  Version:          1.3.1

Главное, чтобы в выводе присутствовали обе части: Client и Server, что означает, что dockerd запущен и Docker Engine работает.

Первый тест

Для проверки можно запустить тестовый контейнер, который выводит приветственное сообщение. Используйте команду:

docker run hello-world

Docker загрузит с Hub тестовый образ и запустит контейнер, который выведет сообщение Hello from Docker! — это значит, что система установлена правильно и демон отвечает на запросы.

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

Когда Docker установлен, можно сразу попробовать запустить приложение. Например, веб-сервер Nginx — лёгкий, стабильный и идеально подходит для первого теста.

Выполните команду:

docker run -d -p 8080:80 nginx

Что здесь происходит:

  1. docker run — создаёт контейнер из указанного образа (в данном случае nginx);

  2. если образа нет локально, Docker автоматически скачает его с Docker Hub;

  3. флаг -d запускает контейнер в фоновом режиме (detached);

  4. -p 8080:80 пробрасывает порт 80 внутри контейнера на порт 8080 вашей машины.

После запуска Docker создаст контейнер и выведет его идентификатор. Теперь можно открыть http://localhost:8080 и увидеть стандартную стартовую страницу Nginx.

Чтобы убедиться, что контейнер работает, выполните:

docker ps

В списке будет строка с именем nginx и статусом Up, который означает, что сервер запущен.

Интерактивный запуск контейнера

Иногда нужно не просто запустить контейнер, а зайти внутрь него ― посмотреть файлы, проверить окружение, выполнить команды. Для этого используют флаг -it.

Например:

docker run -it ubuntu bash

Что делает эта команда:

  • -i — оставляет стандартный ввод открытым,

  • -t — выделяет псевдотерминал,

  • ubuntu — образ, который нужно запустить,

  • bash — команда, которая будет выполнена внутри контейнера.

После запуска вы попадёте в оболочку контейнера и сможете выполнять обычные Linux-команды.

Чтобы выйти, используйте:

exit

Важно: если нужно зайти в уже работающий контейнер, используется другая команда:

docker exec -it <id> bash

Как следить за контейнерами

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

Для этого используем уже знакомую команду:

docker ps

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

Чтобы узнать подробнее, как запущен контейнер и какие у него настройки, выполните:

docker inspect <id>

Она выводит полное описание: от сетевых параметров до переменных окружения и точной команды запуска.

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

docker logs <id>

Но если всё-таки нужно заглянуть внутрь, например, проверить файлы или конфигурацию, — можно открыть интерактивную консоль:

docker exec -it <id> /bin/bash

Если в образе нет Bash (например, в Alpine), вместо него используют:

docker exec -it <id> /bin/sh

Так вы попадёте в среду контейнера, где доступны обычные Linux-команды.

Управление контейнерами

Контейнеры можно запускать, останавливать и удалять — так же просто, как обычные процессы в системе.

Если контейнер нужно приостановить, используйте:

docker stop <id>

Docker отправит сигнал завершения процессу внутри контейнера и аккуратно его остановит.

Контейнер останется в списке и при желании его можно снова запустить командой:

docker start <id>

Когда контейнер больше не нужен, его можно удалить:

docker rm <id>

Важно: если попытаться удалить запущенный контейнер, Docker выдаст ошибку, чтобы не потерять данные.

Для принудительного удаления (остановка и удаление одной командой) используйте флаг -f:

docker rm -f <id>

Помимо контейнеров, система хранит образы, из которых они создаются. Посмотреть список локальных образов можно так:

docker images

А удалить ненужные с помощью команды:

docker rmi <image>

Чтобы быстро очистить всё, что не используется (остановленные контейнеры, старые образы, неактивные сети), есть команда:

docker system prune

Она освободит место на диске и оставит только то, что нужно для работы.

Создание своего образа: работа с Dockerfile

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

Пример простого Dockerfile:

FROM python:3.11-slim
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD ["python", "app.py"]

Что здесь происходит:

  • FROM — задаёт базовый образ, от которого наследуется ваш;

  • WORKDIR — создаёт рабочую директорию внутри контейнера;

  • COPY — копирует файлы проекта с компьютера в образ;

  • RUN — выполняет команды при сборке (например, установка библиотек);

  • CMD — указывает, что делать при запуске контейнера.

Важно: когда контейнер запускается, процессы внутри него по умолчанию работают с правами root

Для обучения или экспериментов этого вполне достаточно. Но в продакшене такое поведение создаёт лишние риски: если приложение внутри контейнера уязвимо, злоумышленник получает те же привилегии, что и root-процесс.

Чтобы снизить эти риски, в Dockerfile часто добавляют собственного пользователя и запускают приложение уже от его имени. Сделать это можно буквально в пару строк:

RUN useradd -m appuser
USER appuser

ENTRYPOINT: второй способ задать команду запуска

В Dockerfile есть две инструкции, которые определяют, что выполняется при старте контейнера — CMD и ENTRYPOINT.

Чем отличаются:

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

  • ENTRYPOINT — это фиксированная основа команды. Она всегда выполняется, а аргументы из docker run просто добавляются к ней.

Пример:

ENTRYPOINT ["python", "app.py"]
CMD ["--port", "8000"]

ENTRYPOINT задаёт программу, которую контейнер запускает всегда —
в нашем случае это python app.py. CMD добавляет аргументы по умолчанию. 

То есть Docker склеивает их и при обычном запуске выполнит:

python app.py --port 8000

Если при запуске указать свои параметры:

docker run myapp --port 9000

Docker возьмёт ENTRYPOINT и добавит ваши аргументы, заменив CMD:

python app.py --port 9000

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

CMD используют как набор аргументов по умолчанию. Если при запуске передать свои параметры, CMD полностью заменится.

Разобрались с основами, а теперь перейдём к практике.

Практический пример

Разберём, как создать и запустить свой первый контейнер.

Сначала в папке проекта должны лежать три файла:

myapp/
├─ app.py
├─ requirements.txt
└─ Dockerfile

В app.py напишем простейшее приложение на Python. Оно будет показывать строку “Hello from Docker!”, когда вы откроете страницу в браузере:

from http.server import HTTPServer, BaseHTTPRequestHandler

class Handler(BaseHTTPRequestHandler):
    def do_GET(self):
        self.send_response(200)
        self.end_headers()
        self.wfile.write(b"Hello from Docker!")

if __name__ == "__main__":
    HTTPServer(("0.0.0.0", 8000), Handler).serve_forever()

Файл requirements.txt нужен, чтобы перечислить зависимости проекта. Если их нет — можно оставить его пустым.

Собираем образ

Теперь откройте терминал, перейдите в папку myapp и выполните:

docker build -t myapp .

Флаг -t задаёт имя образа, а точка в конце указывает путь к контексту сборки — папке, где лежит Dockerfile и файлы проекта. После выполнения команды Docker по шагам прочитает Dockerfile и соберёт новый образ.

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

Мы уже пробовали запускать контейнер с Nginx. Теперь сделаем то же самое, но с собственным образом:

docker run -d -p 8000:8000 myapp

Docker создаст контейнер и запустит внутри него ваш app.py.

Откройте http://localhost:8000, и вы увидите сообщение: “Hello from Docker!”.

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

Чтобы их различать, Docker использует теги — о них поговорим дальше.

Зачем нужны теги

Тег — это просто метка версии. Если его не указать, Docker присвоит latest, но лучше явно обозначать версии:

docker build -t myapp:1.0 .

Так проще поддерживать несколько вариантов образа — например, стабильный (1.0) и тесто��ый (dev).

Передача и хранение образов 

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

1. Создайте репозиторий на Docker Hub

Зайдите в свой аккаунт на https://hub.docker.com и вручную создайте новый репозиторий — так же, как создают новый проект на GitHub.

Название репозитория должно совпадать с тем, что вы будете использовать в команде docker push.

Это важный шаг: Docker не создаёт репозитории автоматически.

2. Переименуйте образ

Перед загрузкой образ нужно оформить в правильном формате:

username/repository:tag

где:

  • username — ваш логин на Docker Hub,

  • repository — имя проекта,

  • tag — версия образа (например, 1.0).

Пример:

docker tag myapp:1.0 username/myapp:1.0

3. Войдите в Docker Hub

Авторизуйтесь через команду:

docker login

Docker попросит ввести логин и пароль от вашего аккаунта. После успешного входа появится сообщение вроде Login Succeeded.

4. Отправьте образ в репозиторий

Выполните команду:

docker push username/myapp:1.0

Docker начнёт загружать образ в ваш репозиторий на Docker Hub.

Когда загрузка закончится, образ появится в вашем профиле и станет доступен другим (если репозиторий публичный).

5. Загрузите образ на другом компьютере

Чтобы использовать тот же образ на другой машине, выполните:

docker pull username/myapp:1.0

Docker скачает только нужные слои — если часть уже есть локально, она не будет загружаться заново.

После этого образ можно запустить как обычно:

docker run -d -p 8000:8000 username/myapp:1.0

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

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

Docker Compose позволяет описать все нужные контейнеры и их настройки в одном файле — docker-compose.yml. После этого весь проект можно запустить одной командой.

Пример простого docker-compose.yml:  

services:
  web:
    build: .
    ports:
      - "8000:8000"

  redis:
    image: redis:alpine

Что здесь происходит:

  • services — список контейнеров, которые нужно запустить;

  • web — наш основной сервис, собирается из текущей директории (build: .) и открывает порт 8000;

  • redis — дополнительный контейнер, разворачивается из готового образа redis:alpine.

Как это работает

Сохраните файл и выполните команду:

docker compose up

Docker соберёт образы, создаст контейнеры, подключит сеть и запустит всё вместе.

Чтобы остановить проект, выполните команду: 

docker compose down

Что изучать дальше

Следующие шаги зависят от того, что вы хотите делать дальше:

  • Для разработки — попробуйте написать собственный Dockerfile для своего проекта и оптимизировать его размер. Изучите многоэтапную сборку (multi-stage build) и работу с кэшем.

  • Для деплоя — посмотрите, как запускать контейнеры на сервере: настройка автозапуска через systemd, передача переменных окружения, управление логами.

  • Для продакшена — изучите оркестраторы: Docker Swarm или Kubernetes. Они позволяют управлять десятками контейнеров и масштабировать сервисы.

  • Для безопасности — разберитесь с rootless-режимом, настройкой прав доступа и сканированием образов на уязвимости (например, с помощью docker scan).

  • Для автоматизации — посмотрите, как Docker используется в CI/CD-сценариях: тестирование, сборка и публикация образов через GitHub Actions или GitLab CI.

Ну, вот и всё. Теперь у вас уже есть рабочая база Docker: вы понимаете, как устроены образы и контейнеры, умеете собирать собственные образы и запускать сервисы через Compose. Этого достаточно, чтобы уверенно продолжать и постепенно подключать более сложные вещи.


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

Или можно стать востребованным сотрудником и открыть открыть бóльшие перспективы в карьере с профессиональным обучением:

Автор: kirakirap

Источник

Rambler's Top100