Docker и Docker Compose
Docker запускает приложения в изолированных контейнерах — без ручной установки зависимостей и конфликтов версий на хосте. В этой статье — установка Docker Engine и плагина Docker Compose на mHost VPS, запуск первого контейнера и разбор docker-compose.yml на примере из двух сервисов.
Docker — это контейнеры, а не виртуализация
Docker контейнеризирует приложения на уровне ОС: все контейнеры на сервере используют одно и то же ядро Linux хост-системы и изолированы друг от друга штатными механизмами ядра (namespaces, cgroups) — без гипервизора и без гостевых операционных систем внутри. Именно поэтому контейнеры лёгкие и быстро стартуют: это не «маленькая виртуальная машина», а обычный процесс, изолированный на том же ядре.
Что понадобится
- VPS mHost на Ubuntu 22.04/24.04, Debian 11/12 или AlmaLinux/Rocky Linux 8/9.
- Доступ по SSH под
rootили пользователем с правамиsudo. - Публичный IP сервера — понадобится, чтобы проверить контейнер из браузера.
Шаг 1. Установите Docker Engine и плагин Docker Compose
Готового рецепта для Docker в VMmanager 6 нет (в отличие, например, от LEMP или Django — полный список в статье «Готовые рецепты VMmanager 6») — ставим вручную, любым из способов ниже.
Ставить будем docker-ce — официальную сборку Docker, а не docker.io из репозитория дистрибутива (там обычно более старая версия). Плагин Compose (docker-compose-plugin) ставится тем же пакетным менеджером и добавляет команду docker compose (два слова, без дефиса) — современную замену старому отдельному бинарнику docker-compose (через дефис), который больше не развивается.
Официальный репозиторий: Ubuntu и Debian
Если раньше на сервере уже стоял Docker из репозитория дистрибутива, сначала уберите старые пакеты:
sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc podman-docker containerd runc | cut -f1)Подключите официальный репозиторий Docker и поставьте пакеты:
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
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
sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-pluginОфициальный репозиторий: AlmaLinux и Rocky Linux
Обе системы RHEL-совместимы, поэтому подходит официальный репозиторий Docker для RHEL:
sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo https://download.docker.com/linux/rhel/docker-ce.repo
sudo dnf install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin
sudo systemctl enable --now dockerПри установке dnf спросит подтверждение GPG-ключа репозитория — сверьте показанный отпечаток с указанным на официальной странице docs.docker.com/engine/install/rhel/ и только потом подтверждайте.
Быстрый способ: скрипт get.docker.com
Для теста или разработки Docker можно поставить одной командой — универсальным скриптом, который сам определяет дистрибутив:
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.shШаг 2. Проверьте установку
sudo systemctl status docker
sudo docker run hello-worldЕсли всё в порядке, docker run hello-world сообщит, что клиент Docker успешно связался с демоном, скачал тестовый образ и запустил его.
Запуск без sudo (опционально)
По умолчанию управлять Docker может только root (или пользователь через sudo) — демон работает от root, а сокет /var/run/docker.sock доступен только ему и группе docker. Чтобы выполнять команды docker от обычного пользователя без sudo:
sudo groupadd docker
sudo usermod -aG docker $USER
newgrp docker
docker run hello-world(если группа docker уже существует — а после установки docker-ce через apt/dnf так обычно и есть — groupadd просто сообщит, что группа уже есть, это не ошибка)
Дальше по статье команды docker/docker compose для единообразия даны с sudo — если вы настроили доступ без пароля, как выше, sudo можно опустить.
Шаг 3. Запустите первый контейнер
Поднимите Nginx в фоне с проброшенным портом 80:
sudo docker run -d --name web --restart unless-stopped -p 80:80 nginx:alpine-d— запустить в фоне (detached).--name web— имя контейнера, чтобы не запоминать случайный ID.--restart unless-stopped— перезапускать контейнер автоматически, в том числе после перезагрузки сервера, пока вы явно не остановите его сами.-p 80:80— пробросить порт 80 хоста на порт 80 внутри контейнера.
Проверьте, что контейнер запущен, и откройте IP сервера в браузере:
sudo docker ps
curl -I http://localhostКогда контейнер больше не нужен для примеров ниже, остановите и удалите его — иначе он займёт порт 80, который понадобится в следующем шаге:
sudo docker rm -f webШаг 4. docker-compose.yml на практике
Compose описывает сразу несколько контейнеров одним файлом — вместо того чтобы вручную набирать docker run с десятком флагов для каждого сервиса.
Создайте каталог проекта и файл со статической страницей:
mkdir -p ~/myapp/html && cd ~/myapp
echo "<h1>Hello from Docker Compose</h1>" > html/index.htmlСоздайте файл docker-compose.yml:
nano docker-compose.ymlservices:
web:
image: nginx:alpine
container_name: web
restart: unless-stopped
ports:
- "80:80"
volumes:
- ./html:/usr/share/nginx/html:ro
depends_on:
- db
db:
image: postgres:16
container_name: db
restart: unless-stopped
environment:
POSTGRES_DB: appdb
POSTGRES_USER: appuser
POSTGRES_PASSWORD: change_me
volumes:
- db_data:/var/lib/postgresql/data
volumes:
db_data:Что тут происходит:
services— список контейнеров проекта:web(Nginx) иdb(PostgreSQL).image— какой образ использовать;restart— политика перезапуска, как и вdocker run.ports— проброс портов хост:контейнер, как флаг-p.volumes— уwebэто bind-монтирование каталога./htmlс хоста внутрь контейнера, только для чтения (:ro); уdb— именованный volumedb_data, где PostgreSQL хранит данные отдельно от жизненного цикла контейнера.environment— переменные окружения внутри контейнера.depends_on— Compose запуститdbраньше, чемweb.
Запустите проект:
sudo docker compose up -d
sudo docker compose psПосмотреть логи и остановить проект:
sudo docker compose logs -f
sudo docker compose downЧастые команды
Docker
docker pull <образ>— скачать образ без запуска.docker images— список скачанных образов.docker build -t <имя> .— собрать образ из Dockerfile в текущем каталоге.docker ps— список запущенных контейнеров.docker ps -a— список всех контейнеров, включая остановленные.docker logs -f <контейнер>— логи контейнера в реальном времени.docker exec -it <контейнер> sh— открыть shell внутри работающего контейнера (на образах Debian/Ubuntu вместоshобычно доступенbash).docker stop <контейнер>/docker start <контейнер>/docker restart <контейнер>— остановить / запустить / перезапустить.docker rm <контейнер>— удалить остановленный контейнер (-f— принудительно, даже если он запущен).docker rmi <образ>— удалить образ.docker system prune— удалить неиспользуемые контейнеры, образы и сети, освободить место на диске.
Docker Compose
docker compose up -d— создать и запустить все сервисы проекта в фоне.docker compose ps— статус сервисов текущего проекта.docker compose logs -f— логи всех сервисов проекта в реальном времени.docker compose stop/docker compose restart— остановить / перезапустить сервисы без удаления контейнеров.docker compose down— остановить и удалить контейнеры и сеть проекта (volume’ы остаются).docker compose exec <сервис> sh— shell внутри контейнера конкретного сервиса.docker compose pull— обновить образы сервисов до актуальных версий.
Что дальше
Если вам не принципиален именно Docker и нужен просто готовый веб-стек (LAMP/LEMP) или конкретное приложение (Zabbix, Tomcat и другие) — возможно, для него уже есть готовый рецепт в VMmanager 6, который поставит всё в один клик: см. статью «Готовые рецепты VMmanager 6». Если контейнеры смотрят наружу — не забудьте про firewall: «Настройка firewall: ufw».