Первое знакомство с Docker — установка и базовые понятия

Эта статья — ваш первый шаг в мир 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

Эта команда проделает следующее:

  1. Попытается найти образ локально, но не найдёт.
  2. Загрузит образ hello-world из Docker Hub.
  3. Из образа запустится контейнер.
  4. Контейнер выведет на экран:
Hello from Docker!
This message shows that your installation appears to be working correctly.
  1. Контейнер завершит свою работу, и останется в выключенном состоянии.
  2. Образ останется храниться локально.

Посмотрим на скачанные образы:

$ 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_margulissilly_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 (interactivetty) — интерактивно с псевдо-терминалом;
  • web — имя контейнера;
  • bash — запустить дополнительный процесс bash.

Exec в отличие от attach создаёт новый дополнительный процесс, а attach подключается к основному процессу контейнера (не запускает дополнительных процессов). То есть exec лучше подходит для отладки, просмотра логов и подобных вещей.

Attach — больше подходит для просмотра stdout приложения в реальном времени. Редко нужен, так-как можно заменить на docker logs -f.

Заключение

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

Если понравилась статья, подпишись на мой канал в VK или Telegram.

Мы используем cookie-файлы для наилучшего представления нашего сайта. Продолжая использовать этот сайт, вы соглашаетесь с использованием cookie-файлов.
Принять
Отказаться
Политика конфиденциальности