Совет по умолчанию в 2026 году - «просто заDockerь это». Обычно он верный, но иногда это ошибка. Контейнеры дают воспроизводимость и изоляцию, однако на небольшом VPS они ещё и едят память, добавляют лишнюю подвижную деталь и делают одноприложенческий сервер сложнее, чем нужно. Честный вопрос не «Docker или нет» - а «что нужно именно вашей установке?».
Что Docker реально даёт
- Воспроизводимость. Образ - это и есть ваше окружение. Никакого дрейфа «у меня работает» между локальной машиной, CI и продом.
- Изоляция. Падение или зависимость одного приложения не рушит хост и его соседей.
- Запуск одной командой.
docker compose upподнимает весь ваш стек - приложение, БД, прокси - из файла, который можно версионировать. - Чистые обновления и откаты. Меняете тег образа, а если что-то не так - возвращаете обратно. Уже одно это стоит многого.
Что это вам стоит
- Память. Контейнеры добавляют накладные расходы поверх RSS процесса (базовый образ + рантайм + слой контейнера), а лимит памяти Docker считает весь контейнер, а не только ваше приложение.[1] На машине с 1–2 ГБ, когда приложение + Postgres + Nginx живут каждый в своём контейнере, вы незаметно дойдёте до свопа - а своп на VPS это жестоко. Накладные расходы зависят от рантайма и базового образа; измерьте память в простое на каждый контейнер через
docker stats, прежде чем планировать бюджет. - Размер образа. Полный образ
node:24тащит весь тулчейн - сотни мегабайт ещё до вашего приложения; небрежный Dockerfile отправляет в прод ваши dev-зависимости. Многоступенчатые сборки - это решение, а не украшение. - Ещё один слой для отладки. Сеть, тома и права - реальная поверхность для траблшутинга. Для одного Node-приложения это накладные расходы, которые могут быть не нужны.
- Больше CPU за ту же работу. Рантайм контейнеров добавляет тонкий слой; для веб-приложений это обычно незаметно, но на крошечной машине каждый бит на счету.
Рамка для решения
| Ваша ситуация | Что брать |
|---|---|
| Одно приложение, один сервер, без команды | Сырой VPS, pm2/systemd |
| Приложение + база данных + надо расти | Docker Compose |
| Несколько приложений на одной машине | Docker Compose (с namespaces) |
| Нужны чистые откаты всего стека | Docker Compose |
| У вас машина на 1 ГБ | Docker, но тощий |
| Жёсткий лимит по диску | Сырой VPS |
Реальная граница - сколько независимо версионируемых сервисов вы запускаете и насколько цените откат. Одно долгоживущее Node-приложение с одним Postgres позади: это можно вести через systemd и обычную установку - меньше слоёв, меньше RAM. Как только вам нужно менять версии нескольких сервисов вместе или отдавать настройку кому-то другому - выигрывают контейнеры.
Экономный средний путь (что я бы реально запускал)
Если уж докеризовать - делайте это без типичного налога на накладные расходы.
Собирайте маленьким. Многоступенчатый Dockerfile, который тащит в прод только рантайм:
FROM node:24-slim AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build
FROM node:24-slim AS runtime
WORKDIR /app
ENV NODE_ENV=production
COPY --from=build /app/.next/standalone ./
COPY --from=build /app/.next/static ./.next/static
COPY --from=build /app/public ./public
EXPOSE 3000
CMD ["node", "server.js"]
Если приложение не использует Next.js standalone, копирование в runtime отличается - подгоните строки COPY под ваш вывод сборки.[2] Важна сама форма стадии FROM … AS runtime - никаких dev-зависимостей, никакого дерева исходников, никакого git-репозитория.
node:24-slim (а не полный node:24) резко уменьшает базу. Ещё меньшие варианты (Alpine, distroless) меняют удобство отладки на размер - выбирайте, насколько вам хочется копаться внутри работающего контейнера.
Задайте лимиты ресурсов. Одна из самых полезных вещей, чтобы держать контейнеры в узде на маленькой машине:
# docker-compose.yml
services:
app:
build: .
restart: unless-stopped
ports:
- "127.0.0.1:3000:3000"
environment:
- NODE_ENV=production
deploy:
resources:
limits:
memory: 384m
cpus: "0.50"
Привязка порта приложения к 127.0.0.1 вместо 0.0.0.0 означает, что можно поставить Nginx спереди (или другой контейнер), не выставляя приложение напрямую в интернет. Блок deploy.resources.limits не даёт одному контейнеру уморить хост - особенно важно, если вы добавляете в стек базу данных.
Добавьте базу данных в тот же файл. Типичный путь роста:
db:
image: postgres:18
restart: unless-stopped
environment:
- POSTGRES_DB=myapp
- POSTGRES_USER=myapp
- POSTGRES_PASSWORD=change-me
volumes:
- dbdata:/var/lib/postgresql/data
deploy:
resources:
limits:
memory: 256m
volumes:
dbdata:
Зафиксируйте поддерживаемый мажор Postgres - 18 это текущий стабильный релиз[3] (19 с 15 октября 2026 в стадии Release Candidate 1, GA запланирован на 19 ноября 2026).[4] Проверьте потребление памяти образа, прежде чем ставить лимит слишком низко: недокормленный Postgres получает OOM-kill при записи.[1]
Запускайте.
docker compose up -d --build
docker compose logs -f
docker compose down
Когда возвращаться к сырому VPS
Если у вас одно приложение, хранилище «строки в файле» или лёгкая база, нет нужды в много-контейнерной оркестрации, а вы хотите меньше памяти и подвижных деталей - пропускайте Docker. Используйте PM2 или systemd. Вы получаете:
- Меньше RAM на процесс.
- Более быстрое и простое отлаживание (нет слоя томов/прав, о который спотыкаешься).
- Прямой доступ к
node, вашему пакетному менеджеру и файловой системе. - Меньше вещей, которые придётся объяснять следующему человеку, унаследовавшему сервер.
Мы публикуем цифры простоя/перезагрузок и памяти для этих двух установок только после замера на чистом платном VPS - см. как мы тестируем. До этого считайте любые цифры выше структурой, а не результатами.
Итог
Docker - не значение по умолчанию, а инструмент для конкретной задачи. Используйте его, когда у вас несколько независимо версионируемых сервисов, нужны обратимые деплои или вы хотите передать стек кому-то другому без документации на 20 страниц. Пропускайте, когда у вас одно приложение, одна машина и сильное предпочтение меньшего числа слоёв. Если всё же используете - собирайте маленьким и задавайте лимиты: именно оттуда берутся большинство страшилок про «накладные расходы контейнеров», и это предотвратимо.
Источники
- Docker - Resource constraints (лимиты памяти и поведение OOM). https://docs.docker.com/engine/containers/resource_constraints/ - проверено 2026-09-27
- Next.js -
output: 'standalone'(справочникnext.config.js). https://nextjs.org/docs/app/api-reference/config/next-config-js/output - проверено 2026-09-27 - PostgreSQL - Versioning policy (текущие поддерживаемые мажоры). https://www.postgresql.org/support/versioning/ - проверено 2026-09-27
- PostgreSQL - PostgreSQL 19 RC 1 Released! (2026-10-15; RC 2 - 2026-11-12, GA план 2026-11-19). https://www.postgresql.org/about/news/postgresql-19-rc-1-released-3409/ - проверено 2026-11-07