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 со статической страницей:
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:
{
"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 в примере. А чтобы данные пережили не только пересоздание контейнера, но и ошибку на сервере, настройте резервные копии — как это сделать, разобрали в статье «Снапшоты и бэкапы».
