Инструкции4 мин чтения

Как установить Docker на VPS с Ubuntu

Ставим Docker из официального репозитория, запускаем первый проект на Compose и настраиваем то, о чём обычно вспоминают слишком поздно: опубликованные порты в обход ufw и логи, съедающие диск.

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

Перед началом. Нужен сервер на KVM с доступом по SSH. Если вы только что его получили, сначала пройдите базовую настройку безопасности. Docker внутри контейнерной виртуализации (OpenVZ, LXC) часто работает с ограничениями, на KVM таких проблем нет.

Сколько ресурсов нужно

Сам Docker почти ничего не потребляет — память и процессор расходуют ваши контейнеры. Ориентиры такие:

  • 1 vCPU и 2 ГБ памяти — бот, небольшой сайт или пара лёгких сервисов.
  • 2–4 vCPU и 4–8 ГБ — приложение с базой данных, Redis и обратным прокси в отдельных контейнерах.
  • Место на диске закладывайте с запасом: образы, тома с данными и логи быстро занимают несколько гигабайт. Быстрый NVMe-диск заметно ускоряет сборку образов и запуск контейнеров.

Установка из официального репозитория

Пакет docker.io из стандартных репозиториев Ubuntu часто отстаёт по версии, поэтому ставьте Docker из репозитория самого Docker. Сначала добавьте ключ и источник пакетов:

Терминал
sudo apt update
sudo apt install -y ca-certificates curl
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
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

Затем установите сам Docker и плагин Compose:

Терминал
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Проверьте, что всё работает:

Терминал
sudo docker run --rm hello-world
docker compose version

Если контейнер напечатал приветствие, Docker установлен и служба запущена. Для Debian команды те же, только в адресах репозитория вместо ubuntu укажите debian.

Docker без sudo

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

Терминал
sudo usermod -aG docker $USER

Важно. Членство в группе docker равносильно правам root: такой пользователь может запустить контейнер с доступом ко всей файловой системе сервера. Добавляйте в группу только тех, кому вы и так доверили бы root.

Первый проект на Docker Compose

Compose описывает все контейнеры проекта в одном файле. Создайте каталог проекта и файл compose.yaml — для примера поднимем nginx со статической страницей:

yaml
services:
  web:
    image: nginx:stable
    restart: unless-stopped
    ports:
      - "127.0.0.1:8080:80"
    volumes:
      - ./site:/usr/share/nginx/html:ro

Положите в каталог site файл index.html и запустите проект:

Терминал
docker compose up -d
docker compose ps
curl http://127.0.0.1:8080

Политика restart: unless-stopped поднимет контейнер после сбоя и после перезагрузки сервера. Обновить образы и перезапустить проект можно двумя командами: docker compose pull и docker compose up -d.

Docker и файрвол: частая ловушка

Docker сам прописывает правила iptables для опубликованных портов, и они срабатывают раньше правил ufw. Если написать в compose.yaml просто "8080:80", порт 8080 окажется открыт всему интернету — даже если в ufw он закрыт.

Правило простое:

  • если сервис должен быть доступен снаружи только через nginx или другой обратный прокси, публикуйте порт на локальном адресе: "127.0.0.1:8080:80", как в примере выше;
  • базы данных, Redis и внутренние API вообще не публикуйте — контейнеры одного проекта видят друг друга по имени сервиса во внутренней сети Compose;
  • снаружи оставляйте открытыми только 80 и 443 у прокси и порт SSH.

Проверить, какие порты реально слушает сервер, можно командой sudo ss -tlnp.

Логи и место на диске

По умолчанию Docker пишет логи контейнеров в JSON-файлы без ограничения размера, и болтливый сервис за несколько недель может занять весь диск. Включите ротацию в файле /etc/docker/daemon.json:

json
{
  "log-driver": "local",
  "log-opts": { "max-size": "20m", "max-file": "5" }
}

Перезапустите Docker командой sudo systemctl restart docker. Настройка действует для новых контейнеров, поэтому существующие пересоздайте: docker compose up -d --force-recreate.

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

Терминал
docker system df
docker image prune -a

Что с данными

Всё, что контейнер пишет внутрь себя, пропадает при его пересоздании. Данные баз и загрузки пользователей держите в томах (volumes) или в каталогах на диске сервера, как ./site в примере. А чтобы данные пережили не только пересоздание контейнера, но и ошибку на сервере, настройте резервные копии — как это сделать, разобрали в статье «Снапшоты и бэкапы».

VPS под контейнеры

KVM на AMD EPYC 7713 с NVMe SSD — Docker работает без ограничений, а быстрый диск ускоряет сборку образов.