Будем делать всё руками, без Docker Desktop и прочей магии.
Что получим в итоге
После выполнения инструкции у нас будет сервер примерно такой конфигурации:
Debian 13
│
├── Docker Engine
│
├── Docker Compose
│
├── nginx
│
├── PostgreSQL
│
└── приложение
Все сервисы будут изолированы друг от друга и управляться через docker compose.
1. Подготовка Debian 13
Для начала обновляем систему:
apt update
apt full-upgrade -y
Устанавливаем необходимые пакеты:
apt install -y \
ca-certificates \
curl \
gnupg \
lsb-release
Проверяем версию операционной системы:
cat /etc/debian_version
cat /etc/os-release
Должно быть что-то вроде:
PRETTY_NAME="Debian GNU/Linux 13 (trixie)"
2. Установка Docker
Я предпочитаю устанавливать Docker из официального репозитория, а не из случайных скриптов из интернета.
Создаём каталог для ключей:
install -m 0755 -d /etc/apt/keyrings
Скачиваем ключ репозитория:
curl -fsSL https://download.docker.com/linux/debian/gpg \
-o /etc/apt/keyrings/docker.asc
Выставляем права:
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/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" \
> /etc/apt/sources.list.d/docker.list
Обновляем список пакетов:
apt update
Проверяем, откуда будет установлен Docker:
apt-cache policy docker-ce
Теперь устанавливаем:
apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
Проверяем:
docker --version
docker compose version
Если всё нормально, получим версии Docker Engine и Docker Compose.
3. Проверяем работу Docker
Запускаем тестовый контейнер:
docker run hello-world
Если Docker установлен правильно, увидим сообщение:
Hello from Docker!
Проверяем запущенные контейнеры:
docker ps
А вообще все контейнеры:
docker ps -a
4. Разрешаем Docker запускаться автоматически
Проверяем состояние:
systemctl status docker
Включаем автозапуск:
systemctl enable docker
И запускаем:
systemctl start docker
Можно сделать одной командой:
systemctl enable --now docker
5. Работа с Docker без root
По умолчанию Docker требует root-доступ.
Это неудобно, особенно если Docker используется разработчиком или администратором не для системных операций.
Добавим пользователя в группу docker.
Например:
usermod -aG docker username
После этого необходимо перелогиниться.
Проверяем:
groups
В списке должна появиться группа:
docker
Важный момент
Группа docker фактически предоставляет пользователю очень высокие привилегии на системе.
Поэтому не стоит добавлять в неё всех пользователей подряд.
6. Docker Compose
Современный Docker уже содержит Compose как плагин.
Проверяем:
docker compose version
Обратите внимание на команду:
docker compose
а не старый вариант:
docker-compose
Для новых установок я рекомендую использовать именно современный вариант.
7. Первый docker-compose.yml
Создадим каталог проекта:
mkdir -p /opt/test-app
cd /opt/test-app
Создадим файл docker-compose.yml
services:
nginx:
image: nginx:alpine
container_name: test-nginx
restart: unless-stopped
ports:
- "8080:80"
Запускаем:
docker compose up -d
Проверяем:
docker compose ps
Должны увидеть контейнер: test-nginx
Теперь открываем http://IP_SERVERA:8080 Если всё прошло правильно, мы увидим стандартную страничку nginx
8. Полезные команды Docker
Это тот минимум, который реально приходится использовать постоянно.
Посмотреть запущенные контейнеры:
docker ps
Посмотреть вообще все контейнеры:
docker ps -a
Посмотреть образы:
docker images
Посмотреть логи:
docker logs test-nginx
Следить за логами в реальном времени:
docker logs -f test-nginx
Зайти внутрь контейнера:
docker exec -it test-nginx sh
Перезапустить:
docker restart test-nginx
Остановить:
docker stop test-nginx
Удалить:
docker rm test-nginx
Удалить образ:
docker rmi nginx:alpine
9. Запускаем PostgreSQL
Теперь сделаем что-то более полезное. Изменим docker-compose.yml
services:
nginx:
image: nginx:alpine
container_name: test-nginx
restart: unless-stopped
ports:
- "8080:80"
postgres:
image: postgres:17
container_name: test-postgres
restart: unless-stopped
environment:
POSTGRES_DB: app
POSTGRES_USER: app
POSTGRES_PASSWORD: change_this_password
volumes:
- postgres_data:/var/lib/postgresql/data
volumes:
postgres_data:
Запускаем и проверяем:
docker compose up -d
docker compose ps
Теперь у нас два контейнера:
test-nginx
test-postgres
10. Почему обязательно нужен volume
Самая распространённая ошибка новичка:
«Я запустил PostgreSQL в Docker, значит данные теперь хранятся в контейнере».
Нет.
Контейнер — это не место, где следует хранить критичные данные.
Если контейнер удалить:
docker rm test-postgres
то данные могут исчезнуть вместе с ним.
Поэтому для PostgreSQL используется volume:
volumes:
- postgres_data:/var/lib/postgresql/data
Посмотреть volumes:
docker volume ls
Посмотреть информацию:
docker volume inspect test_postgres_data
Название volume может отличаться в зависимости от имени проекта.
11. Docker и firewall
Здесь есть важный нюанс.
Многие ставят ufw, запрещают входящие подключения и думают, что Docker автоматически будет соблюдать эти правила.
Не всё так просто.
Docker самостоятельно создаёт правила сетевой фильтрации для опубликованных портов.
Например:
ports:
- "8080:80"
может сделать сервис доступным снаружи.
Поэтому перед публикацией контейнеров наружу нужно понимать, какие порты реально открываются.
Проверяем:
ss -lntup
Если PostgreSQL не должен быть доступен из интернета, не нужно делать:
ports:
- "5432:5432"
Во многих случаях PostgreSQL вообще не требуется публиковать наружу.
Контейнеры внутри одной Docker-сети смогут обращаться к нему напрямую.
12. Как смотреть нагрузку
Docker предоставляет удобную команду:
docker stats
Получаем примерно:
CONTAINER CPU % MEM USAGE / LIMIT
test-nginx 0.01% 5MiB / 2GiB
test-postgres 0.15% 80MiB / 2GiB
13. Что не стоит делать в production
Есть несколько типичных ошибок.
Не использовать latest
Например:
image: postgres:latest
Лучше фиксировать версию:
image: postgres:17
Не запускать контейнеры от root без необходимости
Для готовых официальных образов это обычно уже продумано, но при создании собственных Dockerfile лучше явно разобраться с пользователем, правами и файловой системой.
14. Минимальный production-вариант
В итоге базовый Compose может выглядеть примерно так:
services:
app:
image: my-app:1.0
container_name: my-app
restart: unless-stopped
networks:
- backend
postgres:
image: postgres:17
container_name: my-postgres
restart: unless-stopped
environment:
POSTGRES_DB: app
POSTGRES_USER: app
POSTGRES_PASSWORD: change_me
volumes:
- postgres_data:/var/lib/postgresql/data
networks:
- backend
networks:
backend:
volumes:
postgres_data:
Заключение
Docker на Debian 13 устанавливается довольно просто. Самое интересное начинается дальше — когда на сервере появляется несколько сервисов.
Например:
Internet
│
▼
nginx
│
▼
application
│ │
▼ ▼
PostgreSQL Redis
│
▼
backup
Именно в таком виде Docker становится действительно полезным: каждый сервис живёт отдельно, конфигурация описывается кодом, сервер можно быстро восстановить, а перенос инфраструктуры на другую машину занимает гораздо меньше времени.
Для небольшого VPS или домашнего сервера Docker + Docker Compose уже позволяют собрать вполне серьёзную инфраструктуру.
А дальше можно добавить:
- reverse proxy;
- HTTPS;
- автоматические backup PostgreSQL;
- Prometheus + Grafana;
- Loki для логов;
- Watchtower или собственный процесс обновления;
- GitLab CI/CD;
- отдельную Docker-сеть для frontend/backend;
- мониторинг состояния контейнеров.
И тогда обычный Debian-сервер превращается уже в полноценную небольшую инфраструктурную платформу.
Если статья оказалась полезной — сохраните её. Когда Docker в очередной раз перестанет запускаться в два часа ночи, эта ссылка может пригодиться.
Комментарии к этой статье отключены.