ServerAID
Найти гайд, команду, тег… ⌘ K
Серверный стек

Установка Docker на Ubuntu 24.04: официальный репозиторий, проверка, настройка

Ставим Docker Engine из официального репозитория Docker, а не из архива Ubuntu — там пакет отстаёт на месяцы и не содержит compose-плагина. Разбираем полную последовательность: ключ, репозиторий, установка, запуск без sudo, ограничение размера логов и главную ловушку Ubuntu — Docker публикует порты в обход UFW.

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

Выбираем источник пакета

В архиве Ubuntu есть пакет docker.io. Он ставится одной командой и этим подкупает, но у него два минуса: версия замораживается на момент релиза дистрибутива и обновляется только с бэкпортами безопасности, а плагин docker compose в него не входит — придётся отдельно искать docker-compose-v2.

Официальный репозиторий Docker даёт свежий Docker Engine, плагины buildx и compose в комплекте и обновляется обычным apt upgrade вместе с остальной системой.

docker.io из Ubuntu Официальный репозиторий
Свежесть версии отстаёт, часто на год текущий релиз
docker compose отдельным пакетом в комплекте (docker-compose-plugin)
docker buildx нет в комплекте
Обновления только security-бэкпорты полноценные
Подходит для прода с оговорками да

Дальше — установка из официального репозитория. Все команды проверены на Ubuntu 24.04 LTS; для 22.04 они идентичны, кодовое имя релиза подставляется автоматически.

Убираем конфликтующие пакеты

Если на машине уже пробовали ставить Docker или он приехал зависимостью, старые пакеты будут конфликтовать с docker-ce. Снимаем их заранее:

for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do
  sudo apt-get remove -y $pkg
done

Команда безопасна: apt-get remove для отсутствующего пакета просто ничего не делает. Образы и контейнеры при этом не удаляются — они лежат в /var/lib/docker и переживут переустановку движка.

Подключаем репозиторий Docker

Сначала — зависимости для работы с HTTPS-репозиторием и ключами:

sudo apt-get update
sudo apt-get install -y ca-certificates curl

Кладём GPG-ключ Docker в /etc/apt/keyrings. Это современный способ: ключ привязывается к конкретному репозиторию, а не добавляется в глобальное доверенное хранилище apt-key, которое объявлено устаревшим.

sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

Добавляем сам репозиторий. Кодовое имя релиза (noble для 24.04, jammy для 22.04) подставляется из /etc/os-release, поэтому команду не нужно править под версию:

echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] \
  https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

Если apt-get update ругается на NO_PUBKEY или неизвестный релиз — проверьте, что подставилось в файл:

cat /etc/apt/sources.list.d/docker.list

Частая причина ошибки — производная от Ubuntu система (Linux Mint, Pop!_OS), где VERSION_CODENAME возвращает собственное имя релиза, которого в репозитории Docker нет. Там нужно подставить кодовое имя базовой Ubuntu вручную. Подробнее про механику apt-репозиториев — в разборе apt update и upgrade.

Ставим Docker Engine

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

Что именно приехало:

  • docker-ce — сам демон (Docker Engine);
  • docker-ce-cli — клиент, команда docker;
  • containerd.io — низкоуровневый рантайм контейнеров;
  • docker-buildx-plugin — расширенная сборка образов, docker buildx;
  • docker-compose-plugindocker compose как подкоманда.

Установка сама создаёт и включает systemd-юниты docker.service и containerd.service, так что после перезагрузки Docker поднимется автоматически. Проверить это можно явно:

systemctl is-enabled docker
systemctl is-active docker

Обе команды должны ответить enabled и active. Если нет — включаем сами, механика разобрана в статье про systemd-юниты и systemctl enable:

sudo systemctl enable --now docker

Проверяем установку

docker --version
docker compose version
sudo docker run --rm hello-world

Флаг --rm удаляет контейнер сразу после завершения — тестовый мусор не копится. Если в выводе появилось «Hello from Docker!», значит демон работает, образ скачался с Docker Hub и контейнер запустился.

Более развёрнутая картина — docker info: там видно версию, хранилище (Storage Driver: overlay2), количество образов и контейнеров, cgroup-драйвер.

Запускаем docker без sudo

По умолчанию сокет /var/run/docker.sock принадлежит группе docker, поэтому обычный пользователь получает permission denied. Добавляем себя в группу:

sudo usermod -aG docker $USER

Изменение членства в группах применяется при новом входе в систему. Проще всего перелогиниться по SSH; либо обновить сессию на месте:

newgrp docker
docker run --rm hello-world

Важно понимать, что это ровно эквивалентно выдаче прав root. Любой член группы docker может смонтировать корень хоста в контейнер и получить полный доступ к системе:

# наглядная демонстрация, а не рецепт к применению
docker run --rm -v /:/host alpine cat /host/etc/shadow

Поэтому на многопользовательском сервере в группу docker добавляют только тех, кому и так доверен root. Про разграничение прав — в статьях о sudo и правах доступа chmod.

Ограничиваем логи, иначе диск кончится

Это главная причина «внезапно кончилось место» на серверах с Docker. По умолчанию драйвер логов json-file пишет весь stdout контейнера в файл без ограничения размера. Болтливое приложение за несколько месяцев спокойно съедает десятки гигабайт.

Правится один раз в /etc/docker/daemon.json:

{
  "log-driver": "json-file",
  "log-opts": {
    "max-size": "10m",
    "max-file": "3"
  },
  "live-restore": true
}
sudo systemctl restart docker

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

live-restore отдельно полезен на проде: контейнеры продолжают работать при перезапуске самого демона, то есть apt upgrade docker-ce не роняет ваши сервисы.

Проверить, сколько занимает Docker прямо сейчас:

docker system df
sudo du -sh /var/lib/docker

Почистить неиспользуемое:

docker system prune -a --volumes

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

Docker публикует порты в обход UFW

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

docker run -d -p 8080:80 nginx

И порт 8080 оказывается открыт всему интернету, хотя UFW его не разрешал. Причина в том, что Docker пишет свои правила в цепочку DOCKER таблицы nat напрямую через iptables, и они срабатывают раньше правил UFW. UFW при этом честно показывает Status: active и ничего не подозревает.

Проверить, что порт реально виден снаружи:

sudo ss -tulpn | grep 8080

Если в выводе 0.0.0.0:8080 — порт слушается на всех интерфейсах.

Самое надёжное решение — не публиковать порт наружу вообще. Привязываем публикацию к localhost:

docker run -d -p 127.0.0.1:8080:80 nginx

Снаружи порт недоступен, а наружу сервис отдаёт nginx как reverse proxy — с TLS, заголовками и логами. Это и есть штатная схема для веб-приложений в контейнерах.

В docker-compose.yml то же самое пишется так:

services:
  app:
    image: nginx
    ports:
      - "127.0.0.1:8080:80"

Про сам compose-файл и его структуру — в статье про Docker Compose на Ubuntu.

Переносим данные Docker на другой диск

Образы, тома и слои живут в /var/lib/docker. Если корневой раздел небольшой, а под данные есть отдельный диск, каталог переносится через data-root.

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

sudo systemctl stop docker docker.socket
sudo rsync -aHAX /var/lib/docker/ /mnt/data/docker/

Флаги -aHAX сохраняют жёсткие ссылки, ACL и расширенные атрибуты — для слоёв образов это критично, обычное cp -r здесь ломает overlay2. Подробнее про ключи — в разборе rsync.

Прописываем новый путь в /etc/docker/daemon.json:

{
  "data-root": "/mnt/data/docker"
}
sudo systemctl start docker
docker info | grep "Docker Root Dir"

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

Быстрая установка скриптом и почему не на прод

Docker предлагает convenience-скрипт:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

Он определяет дистрибутив и делает всё то же самое за один заход. Удобно для одноразовой виртуалки или стенда в CI, но на боевом сервере лучше пройти шаги вручную: скрипт может неожиданно поменять поведение между запусками, тянет --channel stable без вашего контроля и хуже сочетается с системами управления конфигурацией. Для скачивания скрипта, кстати, подойдёт и wget.

Удаляем Docker полностью

sudo apt-get purge -y docker-ce docker-ce-cli containerd.io \
  docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
sudo rm -rf /var/lib/docker /var/lib/containerd
sudo rm /etc/apt/sources.list.d/docker.list /etc/apt/keyrings/docker.asc

purge снимает пакеты вместе с конфигами, но каталоги с образами и томами не трогает — их удаляем явно вторым шагом. Проверьте, что там нет нужных томов: docker volume ls до удаления.

Частые вопросы

Какую версию Ubuntu поддерживает официальный репозиторий Docker?

Docker поддерживает актуальные LTS-релизы и текущий промежуточный. Для 24.04 (noble) и 22.04 (jammy) пакеты собираются штатно, и приведённые выше команды работают без изменений — кодовое имя подставляется из /etc/os-release.

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

Чем docker compose отличается от docker-compose?

docker-compose с дефисом — старая версия на Python, которая ставилась отдельным пакетом и сейчас не развивается. docker compose без дефиса — плагин на Go, входящий в docker-compose-plugin, это текущая поддерживаемая реализация.

Синтаксис docker-compose.yml совместим, менять файлы при переходе не нужно. Ключ version: в начале файла современный compose игнорирует и предупреждает о нём — его можно просто удалить.

Нужно ли ставить containerd отдельно?

Нет. Пакет containerd.io устанавливается вместе с docker-ce из того же репозитория и настраивается автоматически. Отдельно containerd ставят только в сценариях без Docker — например, под Kubernetes.

Конфликт возникает, если в системе остался containerd из архива Ubuntu, — его снимает команда очистки из раздела про конфликтующие пакеты.

Почему контейнер не запускается после установки на Ubuntu 24.04?

Проверьте вывод sudo journalctl -u docker -n 50 — там видна конкретная причина. Типичные варианты: не хватает места на /var, конфликт с оставшимся containerd из архива Ubuntu, либо контейнер требует привилегий, которые ограничены политикой AppArmor.

В Ubuntu 24.04 ужесточены ограничения на непривилегированные user namespaces (kernel.apparmor_restrict_unprivileged_userns=1), что задевает часть rootless-сценариев и отдельные образы. Обычный Docker Engine, запущенный от root, это ограничение не затрагивает.

Как обновлять Docker дальше?

Обычным обновлением системы — репозиторий уже подключён:

sudo apt update && sudo apt upgrade

С live-restore: true в daemon.json перезапуск демона при обновлении не останавливает работающие контейнеры. Без этой настройки контейнеры на несколько секунд встанут.

Что запомнить

  • Официальный репозиторий Docker вместо docker.io из архива Ubuntu: свежая версия плюс compose и buildx в комплекте.
  • Ключ кладём в /etc/apt/keyrings и ссылаемся на него через signed-byapt-key устарел.
  • Членство в группе docker равносильно root: выдаём только тем, кому доверен root.
  • Ограничение max-size/max-file в daemon.json ставим сразу — иначе логи контейнеров однажды займут весь диск.
  • Docker публикует порты в обход UFW. Привязывайте публикацию к 127.0.0.1 и выпускайте сервис наружу через nginx.

Похожие материалы

Серверный стек

Установка Nextcloud на Ubuntu Server: nginx, PostgreSQL и HTTPS

Поднимаем своё облако на Ubuntu Server 24.04: nginx с PHP-FPM, база в PostgreSQL, сертификат Let's Encrypt и права на каталог данных. Разбираем полный конфиг nginx под Nextcloud, обязательный cron для фоновых задач и настройки, без которых установка ругается на предупреждения безопасности.

Редакция
Серверный стек

Установка PostgreSQL на Ubuntu 24.04: кластер, роли, pg_hba.conf и доступ по сети

Ставим PostgreSQL из архива Ubuntu или из репозитория PGDG, создаём базу и пользователя, разбираемся с методами аутентификации в pg_hba.conf и аккуратно открываем доступ по сети. Плюс бэкап через pg_dump и типовые ошибки подключения.

Редакция
Серверный стек

Установка nginx на Ubuntu 24.04: пакет, виртуальные хосты, HTTPS и PHP

Ставим nginx на Ubuntu, разбираемся в структуре каталогов sites-available/sites-enabled, поднимаем первый виртуальный хост и включаем HTTPS. Отдельно — когда стоит взять свежую версию из репозитория nginx.org вместо архива Ubuntu и как подключить PHP-FPM.

Редакция
Серверный стек на Ubuntu: nginx, БД, Docker
Серверный стек

Серверный стек на Ubuntu: nginx, БД, Docker

Этот раздел про инфраструктуру, на которой живёт типичное веб-приложение: фронт-прокси, база данных, контейнеры, кэш. Здесь карта стека и порядок, в котором его обычно поднимают на Ubuntu Server.

Михаил Орлов