⟵ Все статьи
Читать на:

Установка Docker на VPS: пошаговое руководство для веб-приложений

Установка Docker на VPS: пошаговое руководство для веб-приложений

Docker избавляет от классической проблемы «на моей машине работало»: приложение вместе со всеми зависимостями упаковывается в контейнер и одинаково запускается где угодно. Для веб-проектов это ещё и простой деплой — обновление сводится к пересборке образа и перезапуску контейнера.

Запустить Docker можно только там, где есть доступ к ядру системы, то есть на VPS или выделенном сервере: на обычном виртуальном хостинге он невозможен в принципе. Ниже — весь путь от аренды сервера до работающего приложения за HTTPS.

Шаг 1. Взять сервер

В панели NodexGo нажмите «Создать сервер» и пройдите четыре шага: локация (рядом с каждой показан ваш реальный пинг до неё), тариф, образ системы и имя сервера. Дальше выбираете период оплаты — 1, 3, 6 или 12 месяцев — и подтверждаете заказ.

Для Docker берите Ubuntu 24.04: все команды ниже написаны под неё. По ресурсам ориентируйтесь так: пара небольших контейнеров живёт на 2 ГБ памяти, связка «приложение + база + прокси» комфортно себя чувствует на 4 ГБ. Сама сборка образов требовательна к диску, поэтому NVMe здесь ощутимо экономит время.

Примерно через минуту сервер готов: IP-адрес и пароль root придут в панель и на почту.

Ubuntu 24.04, NVMe и root-доступ — всё, что нужно Docker.

Создать сервер

Шаг 2. Первое подключение

Подключаемся по SSH, подставив выданный IP-адрес:

ssh root@IP-адрес-сервера

Если SSH не отвечает или вы закрыли себе доступ файрволом, в карточке сервера в панели есть web-консоль VNC — она работает в обход сети и всегда пускает в систему.

Обновляем пакеты:

apt update && apt upgrade -y

Шаг 3. Установить Docker Engine

Ставить Docker из стандартного репозитория Ubuntu не стоит — там почти всегда старая версия. Подключаем официальный репозиторий Docker. Сначала зависимости и ключ:

apt install -y ca-certificates curl gnupg
install -m 0755 -d /etc/apt/keyrings
curl -fsSL https://download.docker.com/linux/ubuntu/gpg | gpg --dearmor -o /etc/apt/keyrings/docker.gpg
chmod a+r /etc/apt/keyrings/docker.gpg

Добавляем сам репозиторий:

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

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

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

Проверяем, что всё поднялось:

docker run --rm hello-world
docker compose version

Если вывелось приветствие Docker и версия Compose — движок работает. Автозапуск после перезагрузки сервера включается так:

systemctl enable --now docker

Шаг 4. Работать не под root

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

adduser deploy
usermod -aG sudo,docker deploy

После этого переподключитесь по SSH уже под ним. Учтите: членство в группе docker фактически равно правам root — добавляйте туда только тех, кому доверяете.

Шаг 5. Первое приложение через Compose

Compose описывает весь стек в одном файле, поэтому приложение поднимается одной командой. Создаём каталог проекта:

mkdir -p /opt/app && cd /opt/app
nano docker-compose.yml

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

services:
  app:
    image: node:22-alpine
    working_dir: /srv
    volumes:
      - ./src:/srv
    command: node index.js
    environment:
      DATABASE_URL: postgres://app:${DB_PASSWORD}@db:5432/app
    depends_on:
      - db
    restart: always

  db:
    image: postgres:16-alpine
    environment:
      POSTGRES_USER: app
      POSTGRES_PASSWORD: ${DB_PASSWORD}
      POSTGRES_DB: app
    volumes:
      - dbdata:/var/lib/postgresql/data
    restart: always

volumes:
  dbdata:

Пароль кладём в файл .env рядом с docker-compose.yml — в репозиторий он не попадает:

echo "DB_PASSWORD=придумайте-длинный-пароль" > .env
chmod 600 .env

Запускаем стек в фоне и смотрим, что получилось:

docker compose up -d
docker compose ps
docker compose logs -f app

Шаг 6. HTTPS и обратный прокси

Открывать контейнеры напрямую в интернет не нужно. Перед ними ставят обратный прокси, который принимает запросы на 80 и 443 портах, сам получает сертификат Let's Encrypt и передаёт трафик внутрь. Проще всего это делает Caddy — сертификат он выпускает и продлевает автоматически.

Добавьте в docker-compose.yml ещё один сервис:

  proxy:
    image: caddy:2-alpine
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./Caddyfile:/etc/caddy/Caddyfile
      - caddydata:/data
    restart: always

И создайте рядом файл Caddyfile — две строки, где example.com замените своим доменом, уже направленным A-записью на IP сервера:

example.com {
    reverse_proxy app:3000
}

После перезапуска стека сайт откроется по HTTPS без единой ручной настройки сертификата:

docker compose up -d

Шаг 7. Файрвол

Оставляем снаружи только то, что действительно нужно: SSH и веб. Порты самих контейнеров наружу не публикуем — они общаются между собой во внутренней сети Compose.

ufw allow OpenSSH
ufw allow 80/tcp
ufw allow 443/tcp
ufw enable

Важно знать особенность: Docker работает с iptables напрямую и умеет обходить правила ufw, если вы публикуете порт строкой вида 5432:5432. Поэтому базы и внутренние сервисы никогда не публикуйте наружу — обращайтесь к ним по имени сервиса внутри Compose.

Обновление приложения и обслуживание

Обновить образы и перезапустить стек:

docker compose pull
docker compose up -d

Docker со временем занимает много места старыми образами и слоями сборки. Раз в месяц полезно прибирать за собой:

docker system df
docker system prune -a

Не забывайте про резервные копии: том с базой данных нужно выгружать отдельно, сам контейнер бэкапом не является.

docker compose exec -T db pg_dump -U app app > /root/backup-$(date +%F).sql

Если не хватает ресурсов

Признак того, что сервер мал: контейнеры начинают падать с кодом 137 — это значит, что процесс убил механизм нехватки памяти. Проверить текущую нагрузку можно так:

docker stats --no-stream
free -h

В такой ситуации в карточке сервера в панели есть кнопка «Увеличить мощности»: тариф меняется на старший, диск и IP-адрес сохраняются, контейнеры продолжают работать — переустанавливать ничего не нужно.

Коротко

Арендовать VPS с Ubuntu 24.04, поставить Docker из официального репозитория, описать приложение в docker-compose.yml, закрыть его обратным прокси с автоматическим HTTPS и оставить открытыми только 22, 80 и 443 порты. Дальше любое обновление — это две команды, а переезд на другой сервер сводится к копированию каталога проекта.

Тарифы от 2 до 32 ГБ памяти — начните с малого, перейти на старший можно в один клик.

Посмотреть тарифы

Мы используем файлы cookie: необходимые — для входа в аккаунт и языка интерфейса, аналитические — чтобы понимать, какими страницами пользуются. Сторонних рекламных систем у нас нет. Подробнее