Эта статья — ваш первый шаг в мир Docker: вы узнаете, что такое контейнеры и образы, как происходит установка Docker на Linux, как запустить первый контейнер всего за пару команд. Просто, понятно и без воды — идеально для новичков!
Теория
Docker — это инструмент для запуска приложений в изолированных контейнерах. Он делает разработку и развертывание проще, быстрее и безопаснее. Нужен он для: изоляции приложений и их переносимости.
Плюсы:
- простота развёртывания,
- экономия ресурсов по сравнению с виртуальными машинами,
- стандартизация окружения.
Минусы:
- не подходит для задач, требующих полной виртуализации;
- не оптимален для GUI-приложений (да, запустить GUI в docker контейнере возможно, но нужно будет выполнять дополнительные действия, например пробрасывать X11-сокет в контейнер и т.п.);
- требует грамотной настройки безопасности (следить за пробросом портов, запускать приложение в контейнере не от root пользователя, грамотно передавать пароли в контейнер).
Основной компонент Docker — это служба (daemon). Служба работает в фоне и управляет контейнерами, образами, сетями, томами и другими ресурсами. Также она слушает запросы от клиентов, и выполняет задания (например: запускает новый контейнер, показывает запущенные контейнеры и т.п.).
Docker CLI — это клиент, который формирует запросы и отправляет их службе. А также получает и отображает ответы.
Вся коммуникация между клиентом и службой идёт через Docker Engine API.
- По умолчанию такое взаимодействие происходит по Unix-сокету — это безопасно (только локальный доступ).
- Но можно настроить управление и по сети (TCP-сокету) — тогда вы сможете выполнять команды по сети.
В технологии Docker существуют образы и контейнеры.
- Образ — это шаблон, содержащий всё необходимое для запуска приложения: код, зависимости, окружение, инструкции запуска и т.д. Образ неизменяем (immutable): после создания его содержимое нельзя изменить.
- На основе образа запускается контейнер — это уже работающий экземпляр, который можно останавливать, запускать, удалять.
Существует централизованное хранилище образов — Docker Hub (https://hub.docker.com/).
Docker изначально разрабатывался для Linux и использует нативные возможности ядра Linux, такие как cgroups и namespaces. Однако Docker можно использовать и на Windows, для этого устанавливают Docker Desktop for Windows. Но для работы используется подсистема WSL2, которая предоставляет настоящее ядро Linux.
Практика
На практике установим Docker на Linux. Я опишу установку на дистрибутивы Debian и Ubuntu.
Устанавливаем зависимости:
$ sudo apt update $ sudo apt install ca-certificates curl gnupg
ca-certificates— управляет корневыми сертификатами в системе;curl— необходим для скачивания ключей репозитория docker;gnupg— утилита для шифрования (gpg) , понадобится для установки ключей репозитория Docker.
Скачиваем ключи репозитория:
- Для Debian
$ curl -fsSL https://download.docker.com/linux/debian/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
- Для Ubuntu (Mint)
$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg --dearmor -o /etc/apt/keyrings/docker.gpg
Разберём комнду:
curl— утилита для скачивания:-f(fail) — в случае ошибки команда завершится с не нулевым кодом возврата;-s(silent) иS(show error) — команда будет работать в тихом режиме, но в случае ошибки покажет её;-L(location) — команда будет следовать редиректам, если вдруг файл будет перемещён.
gpg— утилита для обработки ключей:--dearmor— сервер отдаёт ключ в текстовом формате, а эта опция преобразует его в бинарный формат (aptтребует бинарный формат);-o— определяет куда положить файл.
Прописываем репозиторий в файл /etc/apt/sources.list.d/docker.list:
- Для Debian 12
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/debian bookworm stable
- Для Ubuntu 22.04
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu jammy stable
- Для Ubuntu 24.04
deb [arch=amd64 signed-by=/etc/apt/keyrings/docker.gpg] https://download.docker.com/linux/ubuntu noble stable
Устанавливаем docker:
$ sudo apt update $ sudo apt install docker-ce docker-compose-plugin
docker-ce— Docker CE (Community Edition) — это основной движок контейнеризации;docker-compose-plugin— это официальный плагин, который позволяет использовать командуdocker compose(без дефиса) как часть CLI Docker. Это современный и рекомендуемый способ работы с Compose-файлами.
Проверим установленную версию Docker:
$ sudo docker version Client: Version: 20.10.24+dfsg1 API version: 1.41 Go version: go1.19.8 Git commit: 297e128 Built: Fri Jun 6 14:40:45 2025 OS/Arch: linux/amd64 Context: default Experimental: true Server: Engine: Version: 20.10.24+dfsg1 API version: 1.41 (minimum version 1.12) Go version: go1.19.8 Git commit: 5d6db84 Built: Fri Jun 6 14:40:45 2025 OS/Arch: linux/amd64 Experimental: false containerd: Version: 1.6.20~ds1 GitCommit: 1.6.20~ds1-1+deb12u1 runc: Version: 1.1.5+ds1 GitCommit: 1.1.5+ds1-1+deb12u1 docker-init: Version: 0.19.0 GitCommit:
Проверим установленную версию docker compose:
$ sudo docker compose version Docker Compose version v2.40.2
Как вы могли заметить выше, мы используем sudo для работы с docker. По умолчанию работать с docker может только root или пользователи из группы docker. Так что мы можем добавить своего пользователя в группу docker чтобы работать с ним без sudo:
$ sudo usermod -aG docker alex
- Стоит отметить, что это даст пользователю почти root права, это можно использовать только в доверенных средах.
После этого необходимо перелогинеться в системе, или просто выполним:
$ su - alex
alex— это мой пользователь, у вас может быть другой.
Проверим работу запустив контейнер из образа hello-world:
$ docker run hello-world
Эта команда проделает следующее:
- Попытается найти образ локально, но не найдёт.
- Загрузит образ hello-world из Docker Hub.
- Из образа запустится контейнер.
- Контейнер выведет на экран:
Hello from Docker! This message shows that your installation appears to be working correctly.
- Контейнер завершит свою работу, и останется в выключенном состоянии.
- Образ останется храниться локально.
Посмотрим на скачанные образы:
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE hello-world latest 1b44b5a3e06a 5 weeks ago 10.1kB
Основные команды Docker
Посмотреть на загруженные образы (images) можно с помощью команды — docker images.
$ docker images REPOSITORY TAG IMAGE ID CREATED SIZE ubuntu latest 802541663949 3 weeks ago 78.1MB hello-world latest 1b44b5a3e06a 5 weeks ago 10.1kB
Посмотреть на контейнеры можно с помощью команды — docker ps .
- Без опции
-a— только запущенные. - C опцией
-a— все, включая остановленные.
$ docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 583c53738bf1 ubuntu "bash" 26 minutes ago Exited (2) flamb_margulis a4a162b35da3 hello-world "/hello" 43 minutes ago Exited (0) silly_khorana
Каждый контейнер имеет своё уникальное имя (flamb_margulis, silly_khorana и т.д.). Если мы, при создании контейнера, сами не указали имя, то контейнер получит случайное имя. Желательно создавать контейнеры с осмысленными именами. Это можно сделать с помощью опции --name при создании контейнера (docker run):
$ docker run --name my-hello-world hello-world
docker run— создаём контейнер;--name my-hello-world— назначаем имя контейнеру;hello-world— используем образ контейнера.
Запустить контейнер можно с помощью команды docker start, а остановить с помощью команды docker stop. Так как контейнер из образа hello-world, после выполнения сразу останавливается, создадим другой контейнер из образа ubuntu. Но запустим внутри какой-нибудь долгоиграющий процесс, потому что если не будет процесса, то контейнер сразу завершится.
$ docker run -d --name my_ubuntu ubuntu sleep 600
docker run -d— создаём и запускаем контейнер в фоне (-d);--name my_ubuntu— назначаем имя контейнеру;ubuntu— используем образ;sleep 600— запускаем процесс в контейнере.
Посмотрим на запущенные контейнеры:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES daf21abc8131 ubuntu "sleep 600" About a minute ago Up About a minute my_ubuntu
Остановим и запустим контейнер:
$ docker stop my_ubuntu $ docker start my_ubuntu
Кстати! Если в контейнере завершается основной процесс (в примеhе выше sleep 600), то контейнер завершается. Контейнер сам по себе, без процессов, не может быть запущенным.
Команда docker logs показывает stdout или stderr основного процесса в контейнере. Для примера создадим другой контейнер, который в цикле будет писать текущее время.
$ docker run -d --name my_ubuntu_date ubuntu bash -c "while true; do date; sleep 2; done"
bash -c "while true; do date; sleep 2; done"— в контейнере будет запущен цикл, который будет писать текущее время в stdout каждые 2-е секунды.
И посмотрим stdout и stderr контейнера:
$ docker logs my_ubuntu_date Mon Sep 15 13:08:23 UTC 2025 Mon Sep 15 13:08:25 UTC 2025 Mon Sep 15 13:08:27 UTC 2025
- можно использовать опцию
-f— чтобы следить за логами в реальном времени. Это аналог командыtail -f.
Команда docker attach подключается к консоли основного процесса контейнера (видим его stdout и stderr), при этом никакие дополнительные процессы в контейнере не запускаются:
$ docker attach my_ubuntu_date Mon Sep 15 13:11:03 UTC 2025 Mon Sep 15 13:11:05 UTC 2025 Mon Sep 15 13:11:07 UTC 2025
- Чтобы выйти нам придётся нажать Ctrl+C, но это оборвёт процесс в контейнере и он остановится. Это происходит, потому-что мы подключились к основному процессу контейнера.
Если мы хотим создать контейнер к которому можно будет подключаться и что-то выполнять, то при создании используем опции -it:
$ docker run -d -it --name my_ubuntu_it ubuntu bash $ docker attach my_ubuntu_it root@f04ece951373:/# exit $ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
- Эти опции (
-it) создают внутри контейнера что-то вроде виртуального терминал. Чтобы мы могли с запущенным процессом (bash) взаимодействовать. - Как только мы выходим из такого контейнера с помощью команды
exit, мы завершаем его процесс (bash) и контейнер останавливается. - Запомните
attachподключается к основному процессу контейнера, и не создаёт дополнительных процессов.
Чтобы удалить контейнер используем команду docker rm, но удалять можно только остановленные контейнеры:
$ docker rm my_ubuntu_it
Чтобы удалить образ используем команду docker rmi. Для удаления образа нужно чтобы не было даже остановленных контейнеров использующих этот образ:
$ docker rmi ubuntu
По умолчанию сеть внутри контейнера с хоста не доступна. Но есть возможность пробросить порт в контейнер. Например, запустим контейнер из образа nginx, и с помощью опции -p 8080:80 пробросим 8080 порт хоста на 80 порт контейнера.
$ docker run -d -p 8080:80 --name web nginx
docker run -d— запускаем контейнер в фоне;-p 8080:80— пробрасываем порт из хоста 8080 на 80 порт контейнера;--name web— имя контейнера;nginx— используемый образ.
Подключиться к такому контейнеру (который не создан с опциями -it) можно с помощью команды exec:
$ docker exec -it web bash root@c5557348fc92:/#
-it(interactive, tty) — интерактивно с псевдо-терминалом;web— имя контейнера;bash— запустить дополнительный процесс bash.
Exec в отличие от attach создаёт новый дополнительный процесс, а attach подключается к основному процессу контейнера (не запускает дополнительных процессов). То есть exec лучше подходит для отладки, просмотра логов и подобных вещей.
Attach — больше подходит для просмотра stdout приложения в реальном времени. Редко нужен, так-как можно заменить на docker logs -f.
Заключение
Поздравляем! Вы установили Docker, запустили первый контейнер и разобрались с базовыми понятиями. Дополнительно мы пробежались по основным командам Docker CLI. В следующих статьях мы научимся создавать свои образы, работать с Dockerfile и использовать Docker Compose для запуска многоконтейнерных приложений.
Если понравилась статья, подпишись на мой канал в VK или Telegram.