15%

Сэкономьте 15% на всех хостинговых услугах

Проверьте свои навыки и получите скидку на любой тарифный план

Используйте код:

Skills
Начать
08.10.2024

Docker на Ubuntu: Полное руководство по установке и использованию

Docker — это платформа контейнеризации с открытым исходным кодом, которая упаковывает приложения и их зависимости в изолированные переносимые единицы, называемые контейнерами. В отличие от виртуальных машин, контейнеры используют ядро ОС хоста совместно, что делает их значительно легче, быстрее в запуске и эффективнее с точки зрения использования ресурсов — критически важное отличие для тех, кто запускает рабочие нагрузки в среде VPS Хостинга, где вычислительные ресурсы напрямую влияют на стоимость и производительность.

Это руководство охватывает полный процесс установки Docker на Ubuntu 20.04, 22.04 и 24.04 LTS, включая усиление безопасности после установки, рабочие процессы Docker Compose и производственно-релевантные шаблоны команд, которые большинство руководств упускают.

Предварительные требования и системные требования

Прежде чем выполнять какую-либо команду, проверьте следующее:

  • Версия Ubuntu: 20.04 LTS (Focal), 22.04 LTS (Jammy) или 24.04 LTS (Noble). Команда `lsb_release -cs`, используемая при настройке репозитория, автоматически определит ваше кодовое имя.
  • Архитектура: `amd64`, `arm64` или `armhf` — все поддерживаются официальным репозиторием Docker.
  • Версия ядра: Docker требует ядро Linux версии 3.10 или выше. Выполните `uname -r` для проверки.
  • Привилегии пользователя: `sudo` или root-доступ обязательны для установки и управления демоном.
  • Дисковое пространство: Минимум 2 GB свободного места на разделе, где расположен `/var/lib/docker` — именно там Docker хранит образы, контейнеры, тома и кэш сборки. В производственных системах монтируйте этот каталог на отдельный раздел или том.

Критически важный шаг перед установкой: Если вы ранее устанавливали Docker из стандартного репозитория `apt` Ubuntu (пакет `docker.io`), сначала удалите его, чтобы избежать конфликтов с официальными пакетами Docker CE:

“`bash

sudo apt remove docker docker-engine docker.io containerd runc

“`

Шаг 1: Обновление системных пакетов

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

“`bash

sudo apt update

sudo apt upgrade -y

“`

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

Шаг 2: Установка Docker Engine из официального репозитория

Стандартные репозитории `apt` Ubuntu содержат пакет `docker.io`, который поддерживается Canonical и, как правило, отстаёт на несколько версий от официального релиза Docker. Для производственного использования всегда устанавливайте из собственного репозитория Docker.

2.1 Установка зависимостей для транспорта и верификации

“`bash

sudo apt install apt-transport-https ca-certificates curl software-properties-common gnupg lsb-release -y

“`

Зачем нужен `gnupg`? Начиная с Ubuntu 22.04, `gpg` не всегда присутствует по умолчанию. Явное его включение предотвращает скрытый сбой при импорте GPG-ключа.

2.2 Добавление официального GPG-ключа Docker

“`bash

sudo install -m 0755 -d /usr/share/keyrings

curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo gpg –dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

sudo chmod a+r /usr/share/keyrings/docker-archive-keyring.gpg

“`

Шаг `chmod a+r` часто пропускается в руководствах, но необходим в системах, где `apt` работает в контексте ограниченного пользователя — без него менеджер пакетов не сможет прочитать связку ключей и выдаст ошибку `NO_PUBKEY` при выполнении `apt update`.

2.3 Добавление стабильного репозитория Docker

“`bash

echo

"deb [arch=$(dpkg –print-architecture) signed-by=/usr/share/keyrings/docker-archive-keyring.gpg]

https://download.docker.com/linux/ubuntu

$(lsb_release -cs) stable" |

sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

“`

Подстановка `arch=$(dpkg –print-architecture)` необходима на серверах на базе ARM. Жёсткое указание `amd64` — распространённая ошибка, которая приводит к скрытым сбоям разрешения пакетов на ARM-экземплярах.

2.4 Установка Docker Engine, CLI и плагинов

“`bash

sudo apt update

sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin -y

“`

Описание пакетов:

ПакетРоль
`docker-ce`Демон Docker Engine (`dockerd`)
`docker-ce-cli`Клиентский CLI (команда `docker`)
`containerd.io`Низкоуровневая среда выполнения контейнеров (совместимая с OCI)
`docker-buildx-plugin`Расширенные возможности сборки (мультиплатформенность, BuildKit)
`docker-compose-plugin`Compose V2, интегрированный как плагин Docker CLI

Примечание о `containerd.io`: Это не то же самое, что пакет `containerd` в стандартном репозитории Ubuntu. `containerd.io` от Docker — это конкретная, протестированная версия среды выполнения containerd. Смешивание двух версий является известной причиной сбоев при запуске демона.

Шаг 3: Проверка установки

Убедитесь, что демон активен и настроен на запуск при загрузке:

“`bash

sudo systemctl status docker

sudo systemctl enable docker

“`

Проверьте установленную версию:

“`bash

sudo docker –version

sudo docker info

“`

`docker info` более информативен, чем `–version` — он показывает используемый драйвер хранилища (обычно `overlay2`), драйвер cgroup (`systemd` или `cgroupfs`), а также количество CPU и объём памяти, доступных Docker.

Запустите стандартный тест:

“`bash

sudo docker run hello-world

“`

При успешном выполнении выводится сообщение «Hello from Docker!», подтверждающее корректную работу демона Docker, загрузки образа из Docker Hub и выполнения контейнера.

Шаг 4: Настройка Docker для доступа без прав root

По умолчанию сокет Docker (`/var/run/docker.sock`) принадлежит `root` и группе `docker`. Любой пользователь, не входящий в группу `docker`, должен использовать `sudo` для каждой команды Docker.

“`bash

sudo usermod -aG docker $USER

“`

Примените членство в группе без выхода из системы:

“`bash

newgrp docker

“`

Проверьте:

“`bash

docker run hello-world

“`

Предупреждение безопасности: Членство в группе `docker` фактически эквивалентно `sudo` без пароля. Пользователь в группе `docker` может легко смонтировать файловую систему хоста в контейнер и обойти все средства контроля доступа на уровне файловой системы. В многопользовательских системах или на общих серверах рассмотрите использование rootless Docker:

“`bash

dockerd-rootless-setuptool.sh install

“`

Режим rootless запускает демон Docker и контейнеры в непривилегированном пространстве имён пользователя, значительно сокращая поверхность атаки. Это рекомендуемая конфигурация для любой среды, где несколько пользователей используют один хост.

Шаг 5: Справочник основных команд Docker

Управление образами

“`bash

Pull a specific image version from Docker Hub

docker pull nginx:1.27-alpine

List locally cached images

docker images

Remove a specific image

docker rmi nginx:1.27-alpine

Remove all dangling (untagged) images to reclaim disk space

docker image prune

Remove all unused images (not just dangling)

docker image prune -a

“`

Совет для продакшена: Всегда используйте версионированные теги (например, `nginx:1.27-alpine`), а не `latest` в любых автоматизированных или производственных рабочих процессах. Тег `latest` является изменяемым — он может указывать на другой образ после отправки в реестр, нарушая воспроизводимость.

Жизненный цикл контейнера

“`bash

Run a container interactively with a pseudo-TTY

docker run -it ubuntu:22.04 /bin/bash

Run a container in detached mode with port mapping and a name

docker run -d -p 8080:80 –name my-nginx nginx:1.27-alpine

List running containers

docker ps

List all containers (including stopped)

docker ps -a

Stop a running container gracefully (SIGTERM, then SIGKILL after timeout)

docker stop my-nginx

Start a stopped container

docker start my-nginx

Remove a stopped container

docker rm my-nginx

Force-remove a running container (sends SIGKILL immediately)

docker rm -f my-nginx

View real-time logs

docker logs -f my-nginx

Execute a command inside a running container

docker exec -it my-nginx /bin/sh

“`

Инспекция ресурсов и системы

“`bash

Display real-time resource usage statistics

docker stats

Inspect detailed container metadata (JSON)

docker inspect my-nginx

Display disk usage by Docker objects

docker system df

Remove all stopped containers, unused networks, dangling images, and build cache

docker system prune

“`

`docker system prune` — одна из наиболее важных команд обслуживания для долго работающих серверов. Без периодической очистки кэш сборки Docker и остановленные контейнеры могут занять десятки гигабайт на активном хосте разработки или CI.

Шаг 6: Docker Compose — оркестрация многоконтейнерных приложений

Docker Compose V2 (пакет `docker-compose-plugin`, установленный ранее) вызывается как `docker compose` (с пробелом), а не устаревший `docker-compose` (с дефисом). Оба синтаксиса работают при наличии установленного плагина, но V2 является текущим стандартом.

6.1 Понимание структуры файла Compose

Создайте каталог проекта и файл `compose.yml` (предпочтительное имя файла в Compose V2; `docker-compose.yml` поддерживается для обратной совместимости):

“`bash

mkdir ~/my-web-app && cd ~/my-web-app

nano compose.yml

“`

Реалистичный для продакшена пример с Nginx и серверным сервисом:

“`yaml

services:

web:

image: nginx:1.27-alpine

ports:

  • "8080:80"

volumes:

  • ./nginx.conf:/etc/nginx/nginx.conf:ro
  • ./html:/usr/share/nginx/html:ro

depends_on:

  • app

restart: unless-stopped

app:

image: node:20-alpine

working_dir: /usr/src/app

volumes:

  • ./app:/usr/src/app

command: node server.js

environment:

  • NODE_ENV=production

restart: unless-stopped

“`

Пояснение ключевых директив Compose:

  • `restart: unless-stopped` — Контейнер автоматически перезапускается после сбоя или перезагрузки системы, если только он не был явно остановлен оператором. Это правильная политика для долго работающих сервисов; `always` будет перезапускать даже намеренно остановленные контейнеры.
  • `depends_on` — Управляет порядком запуска, но не ожидает готовности сервиса (например, базы данных, принимающей подключения). Для ожидания готовности используйте `healthcheck` в сочетании с `condition: service_healthy`.
  • `volumes` с `:ro` — Монтирование файлов конфигурации в режиме только для чтения предотвращает изменение скомпрометированным процессом контейнера собственной конфигурации.

6.2 Команды рабочего процесса Compose

“`bash

Start all services in detached mode

docker compose up -d

View logs for all services

docker compose logs -f

View logs for a specific service

docker compose logs -f web

List running Compose services

docker compose ps

Scale a specific service to multiple replicas

docker compose up -d –scale app=3

Stop services without removing containers

docker compose stop

Stop and remove containers, networks, and volumes

docker compose down –volumes

Rebuild images before starting (useful after code changes)

docker compose up -d –build

“`

6.3 Проверка работающего сервиса

“`bash

curl -I http://localhost:8080

“`

Ответ `200 OK` подтверждает корректную работу Nginx. Для сервисов, работающих на удалённом экземпляре VPS Хостинга, замените `localhost` на публичный IP-адрес вашего сервера и убедитесь, что соответствующий порт открыт в брандмауэре (`ufw allow 8080/tcp`).

Шаг 7: Основы сетевого взаимодействия Docker

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

Стандартные сетевые драйверы:

ДрайверСценарий использования
`bridge`По умолчанию для автономных контейнеров; изолированное сетевое пространство имён на хосте
`host`Контейнер использует сетевой стек хоста; максимальная производительность, нулевая изоляция
`none`Нет доступа к сети; полезно для пакетной обработки или рабочих нагрузок с повышенными требованиями к безопасности
`overlay`Многохостовое сетевое взаимодействие для кластеров Docker Swarm
`macvlan`Назначает MAC-адрес контейнеру; отображается как физическое устройство в сети

Создание и использование пользовательской мостовой сети:

“`bash

Create an isolated network

docker network create my-app-network

Run containers attached to the custom network

docker run -d –name db –network my-app-network postgres:16-alpine

docker run -d –name api –network my-app-network my-api-image

Containers on the same custom bridge network can resolve each other by name

Inside 'api', you can connect to 'db' using the hostname 'db'

“`

Пользовательские мостовые сети обеспечивают автоматическое разрешение DNS между контейнерами по имени контейнера. Стандартная сеть `bridge` этого не делает — это критически важное отличие, которое приводит к ошибкам подключения, когда разработчики предполагают, что контейнеры в стандартной сети могут обращаться друг к другу по имени.

Шаг 8: Постоянное хранение данных с томами Docker

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

“`bash

Create a named volume

docker volume create pgdata

Use the volume with a container

docker run -d

–name postgres-db

-e POSTGRES_PASSWORD=securepassword

-v pgdata:/var/lib/postgresql/data

postgres:16-alpine

List volumes

docker volume ls

Inspect a volume (shows mount point on host)

docker volume inspect pgdata

Remove unused volumes

docker volume prune

“`

Тома vs. монтирование привязкой:

ХарактеристикаИменованный томМонтирование привязкой
Управляется DockerДаНет
Требуется путь на хостеНетДа
Переносимость между хостамиДа (с драйверами томов)Нет
Лучше всего подходит дляДанных баз данных, состояния приложенияКода разработки, файлов конфигурации
Механизм резервного копирования`docker run –volumes-from`Стандартные инструменты файловой системы

Шаг 9: Обновление Docker

Официальный репозиторий Docker обрабатывает обновления через стандартный механизм `apt`:

“`bash

sudo apt update

sudo apt upgrade -y

“`

Для обновления только пакетов, связанных с Docker, без обновления всей системы:

“`bash

sudo apt install –only-upgrade docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

“`

Перед обновлением до новых мажорных версий ознакомьтесь с примечаниями к релизу Docker, особенно в части изменений драйвера хранилища, обработки версий cgroup или устаревших версий API, которые могут повлиять на существующие файлы `compose.yml`.

Docker vs. альтернативные подходы к контейнеризации

ХарактеристикаDocker EnginePodmanLXC/LXDcontainerd (автономный)
Архитектура демонаЦентрализованный демонБез демонаНа основе демонаНа основе демона
Поддержка rootlessДа (v20+)НативнаяОграниченнаяДа
Поддержка Docker ComposeНативнаяЧерез `podman-compose`НетНет
Соответствие OCIДаДаНет (формат LXC)Да
Интеграция с KubernetesЧерез шим CRI-dockerdНативный CRIНетНативный CRI
Поддержка Windows/macOSDocker DesktopОграниченнаяНетНет
Лучше всего подходит дляОбщей разработки и продакшенаОриентированных на безопасность, rootlessСистемных контейнеров, виртуальных машинУзлов Kubernetes

Для команд, запускающих контейнеризованные рабочие нагрузки в масштабе на bare metal, среда Выделенных серверов даёт полный контроль над параметрами ядра, планированием дискового ввода-вывода и конфигурацией сети — всё это напрямую влияет на плотность контейнеров и производительность.

Контрольный список усиления безопасности для продакшена

Перед запуском Docker в производственной среде устраните следующие проблемы:

Конфигурация демона (`/etc/docker/daemon.json`):

“`json

{

"log-driver": "json-file",

"log-opts": {

"max-size": "10m",

"max-file": "3"

},

"storage-driver": "overlay2",

"userns-remap": "default",

"live-restore": true,

"no-new-privileges": true

}

“`

  • `log-opts` с `max-size` и `max-file`: Без ротации логов JSON-файлы логов Docker заполнят ваш диск. Это одна из наиболее распространённых причин неожиданных сбоев серверов на контейнеризованных хостах.
  • `userns-remap: "default"`: Включает переназначение пространства имён пользователей, так что root контейнера (UID 0) сопоставляется с непривилегированным UID на хосте.
  • `live-restore: true`: Позволяет контейнерам продолжать работу при сбое или перезапуске демона Docker во время обновления — критически важно для обслуживания без простоев.
  • `no-new-privileges: true`: Предотвращает получение процессами контейнера дополнительных привилегий через бинарные файлы `setuid` или `setgid`.

Соображения по сети и брандмауэру:

Docker напрямую управляет `iptables` и по умолчанию обходит правила `ufw`. Контейнер с опубликованным портом (`-p 8080:80`) будет доступен из интернета, даже если установлена политика `ufw deny 8080`. Чтобы применить правила `ufw` поверх манипуляций Docker с `iptables`, добавьте `"iptables": false` в `daemon.json` и управляйте маршрутизацией вручную, или используйте `–network host` Docker с явными правилами `ufw`.

Для проектов, требующих терминирования HTTPS, сочетайте ваше контейнеризованное приложение с правильно настроенным обратным прокси (Nginx или Traefik) и действительным сертификатом. SSL-сертификаты являются обязательным условием для любого производственного веб-сервиса, работающего за контейнеризованным стеком.

Если ваша рабочая нагрузка включает инференс машинного обучения, обслуживание моделей или GPU-ускоренную обработку данных внутри контейнеров, NVIDIA Container Toolkit интегрируется напрямую с Docker Engine. GPU Хостинг обеспечивает необходимое аппаратное обеспечение для этих рабочих нагрузок.

Для команд, управляющих несколькими проектами с веб-интерфейсом управления контейнерами, VPS с cPanel предлагает среду управляемой панели управления, которая может дополнять развёртывания на основе Docker для более простых стеков приложений.

Ключевые технические выводы и матрица принятия решений

Когда использовать Docker на VPS, а когда на выделенном сервере:

  • Используйте VPS для сред разработки, тестирования и производственных рабочих нагрузок с низким и средним трафиком, где плотность контейнеров составляет 10–50 контейнеров.
  • Используйте выделенный сервер, когда плотность контейнеров превышает 50 экземпляров, когда требуется предсказуемая производительность ввода-вывода (без эффекта шумного соседа) или когда для вашей рабочей нагрузки необходима настройка параметров ядра (`sysctl`).

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

  • Настройте ротацию логов в `daemon.json` (`max-size`, `max-file`)
  • Включите `live-restore` для выживания при перезапуске демона без простоя контейнеров
  • Используйте именованные тома, а не монтирование привязкой, для данных сервисов с состоянием
  • Закрепляйте версии образов во всех файлах `compose.yml` — никогда не используйте `latest` в продакшене
  • Включите `userns-remap` или запускайте rootless Docker на многопользовательских хостах
  • Проверьте правила `iptables` после установки Docker, чтобы убедиться, что политика брандмауэра не обходится
  • Установите `restart: unless-stopped` для всех долго работающих сервисов
  • Запускайте `docker system prune` по расписанию cron для предотвращения исчерпания диска
  • Используйте пользовательские мостовые сети для всего межконтейнерного взаимодействия — никогда не полагайтесь на стандартный мост для обнаружения сервисов

Часто задаваемые вопросы

Использует ли Docker на Ubuntu `systemd` или `cgroupfs` в качестве драйвера cgroup по умолчанию?

Начиная с Docker Engine 20.10, драйвером cgroup по умолчанию в системах на основе `systemd` (включая все современные релизы Ubuntu LTS) является `systemd`. Это соответствует требованиям Kubernetes и позволяет избежать нестабильности, вызванной одновременной работой двух менеджеров cgroup. Проверить можно с помощью `docker info | grep -i cgroup`.

В чём разница между `docker compose down` и `docker compose stop`?

`docker compose stop` останавливает работающие контейнеры, но сохраняет их и связанные с ними сети. `docker compose down` останавливает контейнеры, а затем удаляет их вместе с сетями, созданными Compose. Добавление `–volumes` к `down` также удаляет именованные тома, определённые в файле Compose — используйте этот флаг с осторожностью в продакшене, так как он безвозвратно удаляет постоянные данные.

Почему Docker обходит правила брандмауэра `ufw` на Ubuntu?

Docker вставляет собственные правила `iptables` в цепочки `DOCKER` и `DOCKER-USER`, которые обрабатываются раньше правил цепочки `INPUT` `ufw`. Это означает, что порт, опубликованный с помощью `-p`, доступен из интернета независимо от политики `ufw`. Правильным решением является добавление правил непосредственно в цепочку `DOCKER-USER` или привязка опубликованных портов к конкретному интерфейсу (например, `-p 127.0.0.1:8080:80`), когда внешний доступ не требуется.

Как ограничить потребление CPU и памяти контейнером Docker?

Используйте флаги ограничения ресурсов во время выполнения: `docker run –memory="512m" –cpus="1.5" my-image`. В Compose задайте их в ключе `deploy.resources` (Compose V2) или в ключах верхнего уровня `mem_limit` и `cpus`. Без ограничений один вышедший из-под контроля контейнер может исчерпать ресурсы хоста и вывести из строя все остальные контейнеры на том же хосте.

Можно ли запустить Docker внутри контейнера Docker (Docker-in-Docker)?

Да, но это настоятельно не рекомендуется для производственного использования. Распространённый шаблон для CI-конвейеров — монтирование сокета Docker хоста (`-v /var/run/docker.sock:/var/run/docker.sock`) в CI-контейнер, что даёт контейнеру полный контроль над демоном Docker хоста — это существенный риск безопасности. Более безопасной альтернативой является использование флага `–allow security.insecure` BuildKit или специализированных инструментов, таких как Kaniko или Buildah, которые собирают OCI-образы без необходимости в демоне Docker.

15%

Сэкономьте 15% на всех хостинговых услугах

Проверьте свои навыки и получите скидку на любой тарифный план

Используйте код:

Skills
Начать