К основному содержимому

Docker на VPS: установка и запуск контейнеров

VDS / VPS · 15.03.2025 · 4 мин чтения
Иллюстрация к статье «Docker на VPS: установка и запуск контейнеров»

Docker упаковывает приложение вместе с зависимостями в изолированный контейнер, который запускается одинаково на любой машине с установленным движком. На VPS это избавляет от конфликтов версий PHP или Node.js между разными проектами на одном сервере.

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

curl -fsSL https://get.docker.com | sh
systemctl enable --now docker

# Добавляем пользователя в группу docker (без sudo)
usermod -aG docker $USER
newgrp docker

Официальный скрипт сам определяет дистрибутив и подключает нужный репозиторий — для production предпочтительнее явная установка по инструкции docs.docker.com под конкретную версию Ubuntu или Debian, чтобы зафиксировать пакет, а не получать последнюю версию скриптом при каждом новом сервере.

Установка Docker Compose v2

apt install docker-compose-plugin -y
docker compose version
💡 Docker Compose v2 встроен как плагин (docker compose), устаревший v1 — отдельный бинарник (docker-compose). Используйте v2.

Первый контейнер

# Запуск Nginx в контейнере
docker run -d \
  --name mynginx \
  -p 80:80 \
  -v /var/www/html:/usr/share/nginx/html:ro \
  nginx:alpine

# Проверка
docker ps
curl http://localhost

Основные команды Docker

КомандаОписание
docker ps -aВсе контейнеры
docker imagesСписок образов
docker logs -f nameЛоги контейнера (live)
docker exec -it name bashВойти в контейнер
docker statsИспользование ресурсов
docker system pruneОчистка неиспользуемых данных
⚠️ Не запускайте контейнеры от root (--user 0) в production. Создавайте отдельного пользователя внутри образа.

Разбор типичных ошибок

Ошибка docker: permission denied while trying to connect to the Docker daemon socket появляется, когда пользователь не входит в группу docker либо изменение группы ещё не подхватилось в текущей сессии. Команда newgrp docker или повторный вход по SSH решает проблему без перезагрузки сервера.

docker: Error response from daemon: driver failed programming external connectivity on endpoint mynginx: Bind for 0.0.0.0:80 failed: port is already allocated

Эта ошибка значит, что порт 80 на хосте уже занят — либо другим контейнером, либо системным Nginx или Apache вне Docker. Проверяется командой ss -tulpn | grep :80 до запуска контейнера, а не после отладки непонятного отказа.

Контейнер завершается сразу после запуска (статус Exited (0) или с ненулевым кодом) — обычно значит, что основной процесс внутри контейнера отработал и вышел, а Docker не держит контейнер живым сам по себе. Причина смотрится в логах: docker logs mynginx покажет, что именно пошло не так на старте — от отсутствующего конфига до ошибки в entrypoint-скрипте.

Docker и файрвол: важная деталь

Docker прописывает собственные правила в iptables напрямую, в обход UFW. Опубликованный порт контейнера (-p 8080:8080) может остаться доступным снаружи, даже если в UFW стоит ufw deny 8080 — правила Docker в цепочке DOCKER-USER применяются раньше, чем успевает сработать политика UFW. Если нужен контроль доступа к портам контейнеров через файрвол, правила добавляются именно в цепочку DOCKER-USER, а не через обычный ufw, — иначе создаётся ложное чувство защищённости, разобранное в статье про настройку UFW на VDS.

Сравнение Docker и обычной установки приложения

ПараметрDocker-контейнерУстановка напрямую на хост
Изоляция зависимостейПолная, свои версии библиотекОбщая с системой, конфликты версий возможны
Перенос на другой серверОбраз переносится как естьНужно повторять установку и настройку
Потребление ресурсовНебольшой оверхед на движокМинимальный, без прослойки
Отладка на низком уровнеСложнее, нужен вход в контейнерПрямой доступ к процессам и файлам

Когда Docker не подходит

  • Единственное приложение на всём VDS и без планов масштабирования — оверхед на изучение Docker может не окупиться против прямой установки пакета из репозитория.
  • Приложению нужен прямой доступ к устройствам или ядру хоста (специфичные драйверы, низкоуровневая работа с сетью) — контейнеризация такого требует привилегированного режима, что снижает саму пользу изоляции.
  • Команда не готова контролировать файрвол на уровне цепочки DOCKER-USER — иначе публикация портов контейнеров может незаметно открыть больше, чем предполагалось в UFW.
  • Нужна максимальная производительность дисковых операций без прослойки — оверлейная файловая система Docker добавляет накладные расходы по сравнению с прямой записью на хостовую ФС.

Проверка результата

  1. Проверьте, что демон запускается автоматически: systemctl is-enabled docker должно вернуть enabled.
  2. Убедитесь, что непривилегированный пользователь может выполнять команды docker без sudo: docker ps из-под обычного пользователя не должен требовать пароль или падать с ошибкой доступа.
  3. Проверьте реальную доступность опубликованного порта снаружи, а не только через curl http://localhost на самом сервере.
  4. Сверьте правила файрвола для портов контейнеров: iptables -L DOCKER-USER -n покажет, что реально фильтруется на уровне Docker, отдельно от вывода ufw status.
Статья помогла?
← Назад в базу знаний Задать вопрос поддержке