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

Ставим Docker Engine из официального репозитория, запускаем первый контейнер nginx, привязываем порт к localhost и разбираем, почему Docker обходит ufw.

Команда EGN 9 мин чтения
Docker на VPS: установка и первый контейнер в Ubuntu 24.04
Содержание 17
  1. Коротко
  2. Что такое Docker и зачем он на VPS
  3. Шаг 1. Устанавливаем Docker Engine
  4. Шаг 2. Проверяем установку
  5. Шаг 3. Запускаем первый контейнер
  6. Шаг 4. Выводим сайт в интернет через reverse proxy
  7. Примеры: типичные команды
  8. Обход ufw: что нужно знать
  9. Частые ошибки
  10. Пример: два контейнера на одном VPS
  11. Пример: место на диске
  12. Таблица: симптом, причина и решение
  13. Вопросы и ответы
  14. Нужен ли Docker, если сервис можно поставить напрямую?
  15. Можно ли использовать Docker на небольшом VPS?
  16. Как удалить Docker полностью?
  17. Итог

Коротко

Docker запускает приложения в изолированных контейнерах. На VPS это удобно: каждый сервис живёт отдельно, его легко обновить или удалить, а сервер остаётся чистым. Установите Docker Engine из официального репозитория download.docker.com, проверьте его командой sudo docker run hello-world и запустите первый контейнер, например nginx. Порт публикуйте так: -p 127.0.0.1:8080:80. Тогда сайт доступен только с самого сервера, а наружу его выведет reverse proxy.

Главная ловушка Docker на сервере — он работает с iptables напрямую и может открыть порт мимо правил ufw. Это не ошибка, а свойство Docker, и с ним нужно считаться.

Что такое Docker и зачем он на VPS

Контейнер — это процесс с собственным набором файлов, библиотек и сетевых правил. Образ — шаблон, из которого контейнер создаётся. Например, образ nginx:stable содержит веб-сервер в готовом виде, и вам не нужно ставить его в систему.

Польза на VPS состоит из трёх вещей. Во-первых, приложения не конфликтуют: одна версия PHP не мешает другой. Во-вторых, обновление сводится к замене образа. В-третьих, удаление сервиса не оставляет мусора в системе. Цена за это — немного сложности и необходимость понимать сети Docker.

Если вы хотите поднять несколько сервисов сразу, например сайт, базу и бота, посмотрите статью про Docker Compose. Здесь разбираем первый контейнер.

Шаг 1. Устанавливаем Docker Engine

Официальная инструкция Docker для Ubuntu использует отдельный репозиторий. Установка из стандартного репозитория Ubuntu тоже работает, но версии там могут отставать. Сначала подготовьте ключ и источник:

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

Затем добавьте источник в формате deb822. Команда ниже взята из официальной инструкции Docker для Ubuntu (проверено в ноябре 2026: поддерживаются 22.04, 24.04 и 26.04). Кодовое имя выпуска и архитектура подставляются автоматически:

Терминал
sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

sudo apt update

Если у вас Debian, адрес и ключ другие (download.docker.com/linux/debian), смотрите отдельную страницу инструкции для Debian. Теперь установите пакеты:

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

Пакет docker-compose-plugin даёт команду docker compose, которая понадобится позже. Служба запускается сама. Проверить состояние можно так:

Терминал
sudo systemctl status docker

Шаг 2. Проверяем установку

Тестовый образ hello-world скачивается, запускается и выводит сообщение. Это самый короткий способ убедиться, что Docker работает:

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

В выводе должна быть строка Hello from Docker! и пояснение, что установка работает правильно. Если её нет, смотрите ошибку: чаще всего это нехватка места на диске или отсутствие доступа к download.docker.com.

Установка Docker Engine
Установка Docker Engine

Шаг 3. Запускаем первый контейнер

Запустим nginx в фоне и привяжем его порт 80 внутри контейнера к порту 8080 на сервере:

Терминал
sudo docker run -d --name web -p 127.0.0.1:8080:80 nginx:stable

Разберём параметры. -d запускает контейнер в фоне. --name web задаёт имя, по которому его удобно найти и остановить. -p 127.0.0.1:8080:80 публикует порт 80 контейнера на адрес 127.0.0.1 сервера, порт 8080. Именно адрес 127.0.0.1 ограничивает доступ: снаружи сервера этот порт не виден.

Проверьте, что контейнер работает, и ответ приходит:

Терминал
sudo docker ps --format 'table {{.Names}}\t{{.Ports}}'
curl -I http://127.0.0.1:8080

Команда docker ps покажет имя и порты. curl должен вернуть заголовок HTTP/1.1 200 OK.

Первый контейнер и проверка порта
Первый контейнер и проверка порта
Не публикуйте порт без адреса

Запись -p 8080:80 без 127.0.0.1 открывает порт на всех интерфейсах. Такой порт доступен из интернета, даже если в ufw его нет. Для сервисов, которые должны работать только для сайта, всегда указывайте 127.0.0.1.

Шаг 4. Выводим сайт в интернет через reverse proxy

Контейнер на 127.0.0.1:8080 не виден снаружи, и это правильно. Публичный вход делает reverse proxy, например nginx на хосте, который проксирует запросы по домену на контейнер. Так вы получаете один публичный вход с HTTPS, а контейнеров может быть несколько. Настройку reverse proxy и сертификата разбираем в статьях про сайт на VPS с nginx и Let’s Encrypt. Ключевой момент здесь простой: публикуйте контейнеры на localhost, а наружу выводите один сервис.

Примеры: типичные команды

Терминал
sudo docker images
sudo docker logs web
sudo docker stop web
sudo docker rm web
sudo docker run -d --name web -p 127.0.0.1:8080:80 nginx:stable

Первая команда показывает образы на диске. Вторая выводит журнал контейнера, полезно при ошибках. Третья и четвёртая останавливают и удаляют контейнер. Последняя создаёт его заново.

Обновление nginx до свежей версии выглядит так: docker pull nginx:stable, затем остановка, удаление и новый запуск контейнера. Данные, которые нужно сохранить, должны лежать в томах, а не внутри контейнера, иначе при удалении они пропадут.

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

Терминал
sudo docker run -d --name web --restart unless-stopped -p 127.0.0.1:8080:80 nginx:stable

Политика unless-stopped перезапускает контейнер после сбоя и после старта Docker, кроме случая, когда вы остановили его сами командой docker stop.

Обход ufw: что нужно знать

Docker создаёт собственные правила iptables для публикации портов. Пакеты для опубликованных портов направляются через таблицу nat и обходят цепочки INPUT, которыми пользуется ufw, поэтому правила ufw на них не действуют. В документации Docker прямо сказано, что Docker и ufw несовместимы в этом месте и что вручную менять правила Docker не стоит. Практический вывод: порт, опубликованный без 127.0.0.1, будет доступен из интернета, даже если вы его не разрешали в ufw.

Из этого следуют три практических правила:

  • публикуйте порты только на 127.0.0.1, если сервис не должен быть публичным;
  • не полагайтесь на ufw как на единственную защиту для портов Docker;
  • после запуска нового контейнера проверяйте доступ снаружи, например с другого устройства;
  • на VPS EGN добавьте внешнюю защиту: во вкладке «Фаервол» в карточке услуги включите режим «Свои правила» и оставьте только нужные порты. Такой фильтр работает до сервера, и порт, который Docker открыл мимо ufw, до контейнера не дойдёт.

Подробнее про базовую защиту читайте в статье Базовая защита VPS: ufw, fail2ban и обновления.

Частые ошибки

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

Порт занят. Если 8080 уже используется, Docker сообщит об ошибке. Посмотрите, кто слушает порт, командой sudo ss -tlnp | grep 8080, и выберите другой.

Данные пропали после удаления контейнера. Данные внутри контейнера не переживают docker rm. Используйте именованные тома: -v web-data:/usr/share/nginx/html.

Не работает сайт после обновления образа. Проверьте журнал sudo docker logs web и конфиг, который вы монтируете. Новая версия образа может изменить пути.

Пример: два контейнера на одном VPS

Чаще всего на сервере работает не один контейнер. Например, сайт и административная панель, которые должны жить рядом, но не конфликтовать. Каждый получает собственное имя и собственный порт на localhost:

Терминал
sudo docker run -d --name site -p 127.0.0.1:8080:80 nginx:stable
sudo docker run -d --name admin -p 127.0.0.1:8081:80 nginx:stable
sudo docker ps --format 'table {{.Names}}\t{{.Ports}}'

Имена site и admin нужны, чтобы потом останавливать контейнеры по понятному названию. Порты 8080 и 8081 разные, поэтому конфликта нет. Снаружи оба недоступны, а nginx на хосте проксирует домены на нужный порт. Так вы получаете два сервиса за одним публичным входом.

Пример: место на диске

Docker хранит образы, слои и тома в /var/lib/docker, и на небольшом VPS этот каталог растёт незаметно. Посмотреть, сколько места занимают образы, контейнеры и тома, можно командой:

Терминал
sudo docker system df

Неиспользуемые образы удаляются командой sudo docker image prune. Она спросит подтверждение и не тронет образы, которые нужны запущенным контейнерам. Удалять тома без проверки не стоит, потому что в них могут лежать данные базы или файлы сайта. Перед очисткой всегда смотрите список через sudo docker volume ls.

Таблица: симптом, причина и решение

Симптом Причина Решение
permission denied while trying to connect to the Docker daemon Команда без sudo, пользователь не в группе docker Используйте sudo или добавьте пользователя в группу осознанно
port is already allocated Порт занят другой программой или контейнером Найдите процесс через ss -tlnp и выберите другой порт
Контейнер сразу завершается Ошибка в приложении или не хватает переменных Смотрите sudo docker logs имя
Порт открыт из интернета, хотя ufw его не пускает Публикация без 127.0.0.1 Пересоздайте контейнер с -p 127.0.0.1:...
docker: command not found после установки Пакет не установился до конца Повторите apt install, проверьте ошибки

Вопросы и ответы

Нужен ли Docker, если сервис можно поставить напрямую?

Не обязательно. Прямая установка проще для одного сервиса. Docker выигрывает, когда сервисов несколько или версии зависимостей конфликтуют.

Можно ли использовать Docker на небольшом VPS?

Да, но учитывайте, что сам Docker и образы занимают место на диске и память. Следите за диском командой df -h /.

Как удалить Docker полностью?

Остановите и удалите контейнеры и образы, затем удалите пакеты через apt remove и очистите каталог /var/lib/docker. Перед этим сохраните данные из томов.

Итог

Установите Docker Engine из официального репозитория, проверьте hello-world, запустите nginx и публикуйте порты только на 127.0.0.1. Так вы получаете изоляцию сервисов без лишних публичных портов. Помните про обход ufw и регулярно проверяйте, что открыто наружу. Дальше полезно разобраться с мониторингом ресурсов VPS, потому что контейнеры расходуют память и диск.

Сервер под VPS за пару минут — egnetwork.ru

Читать далее

Вся рубрика →