8 800 500-99-26 Для звонков по России
Docker-контейнер: как создавать образы и развёртывать приложения
База знаний
16 мин

Docker-контейнер: как создавать образы и развёртывать приложения

DigitalRazor
DigitalRazor
Подписаться в Telegram
Содержание 11 разделов
Что такое Docker и зачем он нужен Ключевые понятия: образ, контейнер, Dockerfile, реестр Как создать Docker-образ: пошагово Запуск и управление контейнерами Docker Compose: запуск многоконтейнерных приложений Оптимизация образов Docker и GPU: контейнеры для ИИ-нагрузок Деплой Docker-приложений на сервер Частые ошибки при работе с Docker Частые вопросы (FAQ) Заключение
Подберём решение под ваш проект

Расскажите о задаче — предложим оптимальную конфигурацию и реализацию.

Обсудить проект
или свяжитесь с нами
Telegram Telegram WhatsApp WhatsApp ВКонтакте ВКонтакте MAX MAX

Есть проект? Напишите нам

Обсудим задачу и подберём оборудование

Обсудить проект

Docker помогает упаковать приложение вместе с библиотеками, настройками среды и системными зависимостями, а затем запустить ту же сборку на другом компьютере или сервере. Вместо ручной установки Python, PostgreSQL, CUDA и десятка пакетов сервер получает заранее подготовленный образ.

В этом гайде пройдём всю цепочку: напишем Dockerfile, соберём Docker-образ, запустим Docker-контейнер, подключим постоянное хранилище, объединим несколько сервисов через Docker Compose и развернём приложение на сервере. Отдельно разберём GPU в Docker: NVIDIA Container Toolkit, CUDA-образы и несколько изолированных ИИ-окружений на одном GPU-сервере.

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

Представим Python-приложение, которому нужны определённая версия интерпретатора, библиотеки из requirements.txt, системные пакеты и PostgreSQL. На компьютере разработчика всё работает. На сервере установлена другая версия Python, одной библиотеки нет, а другая обновилась и сломала совместимость.

Docker переносит окружение вместе с приложением. Разработчик описывает его в Dockerfile, собирает образ и запускает из него один или несколько контейнеров. Такой подход упрощает перенос между рабочей машиной, тестовым стендом и продакшеном.

  • Одинаковая среда разработки, тестирования и продакшена;
  • Быстрый запуск приложения на новом сервере;
  • Изоляция разных версий библиотек и системных пакетов;
  • Микросервисная архитектура и CI/CD;
  • Локальный запуск баз данных и вспомогательных сервисов;
  • ИИ-разработка с разными версиями CUDA, PyTorch или TensorFlow.

Изоляция окружений не означает, что каждый контейнер получает собственную полноценную операционную систему. Linux-контейнеры используют ядро среды, в которой работает Docker Engine. При нативной установке в Linux это обычно ядро хоста, а Docker Desktop в Windows и macOS запускает Linux-контейнеры внутри служебной виртуальной машины.

Docker и виртуальная машина: в чём разница

Виртуализация и контейнеризация решают похожую задачу — отделяют приложения друг от друга, — но делают это на разных уровнях.

Docker vs Виртуальная машина
Параметр Docker-контейнер Виртуальная машина
ОС Использует ядро среды Docker Engine Имеет отдельную гостевую ОС
Запуск Обычно быстрый Требуется загрузка гостевой ОС
Накладные расходы Относительно небольшие Выше из-за виртуального оборудования и ОС
Типичный сценарий Приложения, сервисы, CI/CD Отдельные ОС, жёсткая изоляция, legacy-системы

Виртуальная машина остаётся полезной, когда нужна отдельная ОС или более жёсткая граница между средами. Docker удобнее, когда требуется быстро переносить и масштабировать приложения. Эти подходы не исключают друг друга: Docker часто работает внутри виртуальной машины в облаке или на VDS.

Ключевые понятия: образ, контейнер, Dockerfile, реестр

У Docker несколько сущностей, которые начинающие пользователи часто смешивают.

  1. Dockerfile — текстовый файл с инструкциями сборки.
  2. Docker-образ — готовый шаблон файловой системы и параметров запуска.
  3. Docker-контейнер — запущенный экземпляр образа.
  4. Registry — серверное хранилище образов, например Docker Hub.

Вся цепочка выглядит так: исходный код и Dockerfile передаются команде docker build, после чего появляется Docker-образ. Его можно сохранить в registry через docker push, получить на сервере через docker pull и затем запустить как контейнер.

Чем образ отличается от контейнера

Образ сам по себе не является работающим приложением. Это неизменяемый шаблон, из которого Docker создаёт экземпляры. Если есть образ myapp:1.0, из него можно запустить несколько независимых контейнеров с разными именами, портами и переменными окружения.

Во время работы контейнер получает собственный записываемый слой. Критичные постоянные данные лучше не хранить только там. При удалении контейнера этот слой исчезнет, поэтому базы данных, пользовательские файлы и другие постоянные данные выносят в volumes или внешнее хранилище.

Docker Hub и другие реестры образов

Registry нужен, чтобы хранить образы вне локального компьютера. После сборки docker build -t myapp:1.0 . можно создать тег для репозитория командой docker tag myapp:1.0 username/myapp:1.0, а затем отправить образ через docker push username/myapp:1.0. На сервере тот же Docker-образ получают командой docker pull username/myapp:1.0.

Docker Hub подходит для публичных проектов и частных репозиториев. В корпоративной инфраструктуре часто используют приватный реестр образов. Версии лучше фиксировать тегами вроде app:1.0, app:1.1 или app:2026-09-01. Тег latest не гарантирует, что на сервере находится именно та версия, которую ожидает команда.

Репозиторий на DockerHub

Как Docker связывает client, daemon и registry

Когда выполняется docker run nginx, команда docker выступает клиентом и обращается к Docker daemon. Daemon управляет локальными образами, контейнерами, сетями и томами. Если образа nginx на машине нет, daemon скачивает его из registry, после чего создаёт контейнер.

Docker daemon обладает широкими правами на хосте. Поэтому доступ к Docker API и сокету /var/run/docker.sock нельзя без необходимости передавать приложениям или неизвестным контейнерам.

Как создать Docker-образ: пошагово

Для практического примера возьмём небольшое Python-приложение. В каталоге проекта будут app.py, requirements.txt, Dockerfile, .dockerignore и compose.yaml. Предположим, приложение слушает порт 8000 и запускается через Gunicorn.

Структура Dockerfile (FROM, COPY, RUN, CMD/ENTRYPOINT)

Простой Dockerfile можно разобрать по основным инструкциям:

Инструкция Пример Что делает
FROM python:3.13-slim Задаёт базовый образ
WORKDIR /app Выбирает рабочий каталог внутри образа
COPY requirements.txt . Копирует файл зависимостей
RUN pip install --no-cache-dir -r requirements.txt Устанавливает зависимости во время сборки
COPY . . Копирует исходный код проекта
CMD gunicorn --bind 0.0.0.0:8000 app:app Задаёт команду запуска по умолчанию
FROM python:3.13-slim

WORKDIR /app

COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt

COPY . .

EXPOSE 8000

CMD ["gunicorn", "--bind", "0.0.0.0:8000", "app:app"]

Инструкция EXPOSE 8000 документирует порт приложения, но сама по себе не открывает его на хосте. Для публикации порта нужен параметр -p в docker run или раздел ports в Compose.

RUN выполняется во время сборки образа, а CMD — при запуске контейнера. ENTRYPOINT тоже задаёт исполняемую команду, но обычно используется, когда образ должен вести себя как отдельная программа и дополнительные аргументы передаются к фиксированной точке входа. Для небольшого сервиса достаточно CMD.

Команда docker build и кэширование слоёв

Сборка запускается командой docker build -t myapp:1.0 . Точка в конце обозначает build context — набор файлов, доступных сборщику. Современный Docker использует BuildKit и старается повторно применять уже готовые слои из build cache.

Порядок инструкций влияет на скорость повторной сборки. Если сначала выполнить COPY . ., а затем устанавливать зависимости, изменение одного файла исходного кода может сбросить кэш и заставить Docker заново выполнять установку пакетов. Поэтому удобнее сначала копировать requirements.txt, затем выполнять RUN pip install ..., а исходники добавлять позже.

Кэширование Docker

После сборки список образов можно проверить командой docker image ls. Для тестового запуска подойдёт docker run --rm -d --name myapp -p 8000:8000 myapp:1.0.

Тегирование образов и версионирование

Тег можно присвоить сразу при сборке через docker build -t myapp:1.0 . или позднее командой docker tag myapp:1.0 username/myapp:1.0. Для новой версии меняется тег, например на myapp:1.1, после чего образ отправляется в registry.

На рабочем сервере лучше явно указывать конкретный тег. Тогда понятно, какая версия сейчас запущена, а при ошибке можно вернуть предыдущую. Использовать один latest как единственный способ версионирования неудобно: он скрывает, какая именно сборка реально работает.

.dockerignore и контекст сборки

Команда docker build . передаёт сборщику содержимое текущего каталога как build context. Туда не нужно включать всё подряд. В .dockerignore обычно исключают .git, локальное виртуальное окружение .venv, __pycache__, временные файлы, журналы, тестовые артефакты и секреты вроде .env.

Это ускоряет сборку и снижает риск случайно добавить в образ ненужные или чувствительные файлы. Особенно опасно копировать приватные ключи и токены: секрет, попавший в слой Docker-образа, нельзя считать безопасно удалённым простым rm в следующей инструкции.

Запуск и управление контейнерами

После сборки Docker-образ можно использовать многократно. Повторный docker build нужен только тогда, когда меняется сам образ, а не при каждом запуске контейнера.

Для разработки и тестирования контейнерных ИИ-приложений необязательно сразу брать сервер на четыре–шесть GPU. Если достаточно одной-двух GPU, можно использовать компактную систему для локального инференса, RAG и экспериментов.

RACKSTATION AI RS24-32-256
Для каких задач Компактный GPU-сервер до 2 видеокарт для начальных задач в AI и графике. Оптимален для инференса, визуализации, VFX и рендеринга в студиях и лабораториях, где важна гибкость.
Подробнее
Видеокарты
2 x NVIDIA RTX 5080 16GB
Объем видеопамяти 32 ГБ
Процессоры
Threadripper PRO 7965WX
Количество ядер 24
RAM 256GB DDR5
Форм-фактор 4.5U
RACKSTATION AI RS32-64-256
Для каких задач Компактный GPU-сервер до 2 видеокарт для начальных задач в AI и графике. Оптимален для инференса, визуализации, VFX и рендеринга в студиях и лабораториях, где важна гибкость.
Подробнее
Видеокарты
2 x NVIDIA RTX 5090 32GB
Объем видеопамяти 64 ГБ
Процессоры
Threadripper PRO 7975WX
Количество ядер 32
RAM 256GB DDR5
Форм-фактор 4.5U
RACKSTATION AI RS32-48-512
Для каких задач Компактный GPU-сервер до 2 видеокарт для начальных задач в AI и графике. Оптимален для инференса, визуализации, VFX и рендеринга в студиях и лабораториях, где важна гибкость.
Подробнее
Видеокарты
NVIDIA RTX 6000 Ada 48GB
Объем видеопамяти 48 ГБ
Процессоры
Threadripper PRO 7975WX
Количество ядер 32
RAM 512GB DDR5
Форм-фактор 4.5U

docker run: основные флаги

Базовый запуск выглядит как docker run myapp:1.0. На сервере часто нужны дополнительные параметры. Например, -d запускает процесс в фоне, --name myapp задаёт имя, -p 8000:8000 публикует порт, -e APP_ENV=production передаёт переменную окружения, а --restart unless-stopped задаёт автоматический перезапуск.

Без указания IP Docker публикует порт на всех интерфейсах хоста. Если сервис нужен только локально, безопаснее использовать -p 127.0.0.1:8000:8000.

Для временного теста удобно использовать --rm: после остановки контейнер автоматически удалится. Когда флагов становится слишком много, а вместе с приложением запускаются база данных, Redis или фоновые воркеры, лучше перейти на Docker Compose.

Логи, остановка, удаление контейнеров

Работающие контейнеры показывает docker ps, а вместе с остановленными — docker ps -a. Логи доступны через docker logs myapp, а режим наблюдения за новыми строками — через docker logs -f myapp. Остановить экземпляр можно командой docker stop myapp, запустить снова — docker start myapp, удалить остановленный — docker rm myapp.

Для диагностики внутри уже работающего контейнера используют docker exec -it myapp sh. Но ручное изменение файлов через docker exec не должно превращаться в способ обновления приложения: новый контейнер всё равно будет создан из исходного образа и не унаследует такие исправления.

Volumes и сети Docker

Контейнеры лучше считать заменяемыми, а постоянные данные хранить отдельно. Именованный том можно создать командой docker volume create app-data и подключить при запуске через --mount type=volume,src=app-data,dst=/data. Удаление контейнера не удаляет такой том автоматически.

Docker Volume

Для связи сервисов используется сеть Docker. Команда docker network create app-net создаёт пользовательскую сеть, а подключённые к ней контейнеры могут обращаться друг к другу по именам. В Compose такая сеть обычно создаётся автоматически, поэтому веб-приложение может обращаться к базе по имени сервиса, например db, без публикации базы в интернет.

Docker Compose: запуск многоконтейнерных приложений

Один docker run удобен. Пять длинных команд для веб-приложения, базы данных, Redis и фонового воркера — уже нет. Docker Compose описывает весь набор сервисов в YAML-файле и позволяет управлять им как единым проектом.

В старых гайдах часто встречается команда docker-compose. Современный вариант — docker compose. Старое написание с дефисом относится к standalone Compose и сохраняется в legacy-сценариях, поэтому при чтении старых инструкций важно не смешивать два варианта CLI.

Структура docker-compose.yml

Название docker-compose.yml по-прежнему поддерживается, но для нового проекта лучше использовать compose.yaml. Верхнеуровневый параметр version: в современном Compose не требуется.

Элемент Пример Назначение
services web, db Описывает контейнеры приложения
image / build username/myapp:1.0 или build: . Выбирает готовый образ или локальную сборку
ports 8000:8000 Публикует порт сервиса
environment DATABASE_HOST=db Передаёт переменные окружения
volumes postgres-data:/var/lib/postgresql/data Сохраняет постоянные данные
healthcheck pg_isready ... Проверяет готовность сервиса
services:
  web:
    build: .
    ports:
      - "127.0.0.1:8000:8000"
    environment:
      DATABASE_HOST: db
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    depends_on:
      db:
        condition: service_healthy
    restart: unless-stopped

  db:
    image: postgres:17
    environment:
      POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
    volumes:
      - postgres-data:/var/lib/postgresql/data
    healthcheck:
      test: ["CMD-SHELL", "pg_isready -U postgres"]
      interval: 10s
      timeout: 5s
      retries: 5
    restart: unless-stopped

volumes:
  postgres-data:

Значение POSTGRES_PASSWORD можно положить в локальный файл .env, но этот файл нельзя добавлять в репозиторий. Названия переменных приложения нужно адаптировать под его конфигурацию.

Запускается проект командой docker compose up -d. Состояние показывает docker compose ps, логи — docker compose logs -f, а остановка и удаление контейнеров проекта выполняются через docker compose down.

Типичный сценарий: веб-приложение и база данных

Для связки веб-приложения и PostgreSQL достаточно двух сервисов в compose.yaml. Сервис web использует образ приложения, публикует порт 8000 и получает параметры подключения через переменные окружения. Сервис db использует официальный образ PostgreSQL, хранит данные в named volume и имеет healthcheck.

Веб-приложение обращается к базе по имени db внутри внутренней сети Compose. Порт PostgreSQL наружу можно вообще не публиковать. Если требуется дождаться готовности БД, а не только запуска её процесса, в depends_on используют условие service_healthy, а у базы задают healthcheck через pg_isready.

Пароль удобно передавать через переменную окружения, например ${POSTGRES_PASSWORD}, но реальный production-секрет нельзя хранить в Git. Для локальной разработки допустим .env, если файл исключён из репозитория и .dockerignore.

Оптимизация образов

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

Multi-stage build

Multi-stage build разбивает сборку на несколько стадий. Каждая начинается со своего FROM, а в финальный образ переносятся только необходимые артефакты. Например, первая стадия на Python может собрать wheel-пакеты, а вторая — установить уже готовые пакеты и добавить приложение, не сохраняя лишние build-инструменты.

В Go и C++ эффект ещё заметнее: компилятор, заголовочные файлы и исходники остаются в builder-стадии, а production-образ получает только готовый бинарник и необходимые библиотеки среды выполнения.

Уменьшение размера образа

Универсального «самого маленького» базового образа нет. Alpine иногда полезен, но его нельзя автоматически считать лучшим выбором для Python, научных библиотек или программ, которые ожидают glibc.

  • Использовать подходящий минимальный runtime-образ;
  • Исключать ненужные файлы через .dockerignore;
  • Не оставлять компиляторы и build-инструменты в production-стадии;
  • Применять multi-stage build;
  • Не копировать локальные виртуальные окружения;
  • Удалять временные файлы в том же слое, где они появились;
  • Не включать секреты и локальные данные;
  • Располагать редко меняющиеся слои раньше часто меняющихся.

Сначала стоит смотреть на состав образа, воспроизводимость сборки и время обновления, а уже потом на минимальное число мегабайт.

Docker и GPU: контейнеры для ИИ-нагрузок

Docker особенно полезен в ИИ-разработке. Один проект требует PyTorch и одну CUDA-среду, второй — другую версию библиотек, третий запускает TensorRT или vLLM. Устанавливать всё глобально на одном Linux-сервере неудобно, а контейнеризация позволяет разделить пользовательские окружения.

Важная граница проходит по драйверу: NVIDIA-драйвер работает на хосте. Контейнер получает пользовательские CUDA-библиотеки, фреймворк и зависимости, но не приносит с собой независимый драйвер ядра для видеокарты.

Если Docker используется для локального инференса, обучения или нескольких ИИ-окружений, сервер стоит подбирать не только по числу GPU, но и по объёму VRAM, памяти и характеру нагрузки.

Выберите GPU-сервер под свои задачи

Готовые конфигурации для инференса, машинного обучения и вычислений

Переход в каталог

NVIDIA Container Toolkit: зачем нужен и как установить

Для корректного доступа Docker к NVIDIA GPU используется NVIDIA Container Toolkit. Сначала на хосте должен нормально работать драйвер — это проверяют командой nvidia-smi. Затем устанавливают Toolkit, настраивают Docker через sudo nvidia-ctk runtime configure --runtime=docker и перезапускают Docker daemon командой sudo systemctl restart docker.

nvidia-smi

Для новых установок ставят nvidia-container-toolkit и настраивают Docker через nvidia-ctk. Отдельно устанавливать nvidia-docker2 или nvidia-container-runtime обычно не требуется: необходимая функциональность входит в Toolkit.

Запуск контейнера с GPU: docker run --gpus all

После настройки можно выполнить тестовый запуск контейнера с GPU. Общая форма команды выглядит как docker run --rm --gpus all nvidia/cuda:<подходящий-тег> nvidia-smi. Если всё работает, внутри контейнера появится информация о доступных ускорителях.

Не обязательно выдавать приложению все карты. Например, параметр --gpus '"device=1,2"' позволяет предоставить контейнеру конкретные GPU. На сервере с четырьмя ускорителями инференс-сервис можно закрепить за GPU 0–1, а экспериментальное окружение — за GPU 2–3.

Готовые CUDA-образы для обучения и инференса

В официальном репозитории nvidia/cuda публикуются разные CUDA-образы. Выбирать их лучше по назначению, а не только по номеру версии.

Тип Содержимое Когда выбирать
base Минимальный набор CUDA runtime Самое компактное базовое окружение
runtime CUDA runtime и дополнительные библиотеки Инференс и запуск готовых приложений
devel Runtime плюс инструменты разработки и заголовки Компиляция CUDA-кода и сборка расширений

CUDA-образ нужно выбирать с учётом совместимости с драйвером хоста. Для продакшен-среды полезно фиксировать полный тег вместо неопределённой версии, чтобы обновление образа не изменило CUDA-окружение неожиданно.

Изоляция окружений на одном GPU-сервере: разные версии CUDA и фреймворков без конфликтов

На одном GPU-сервере можно держать разные окружения: контейнер A — PyTorch и CUDA-среда A, контейнер B — другая версия PyTorch и CUDA-среда B, контейнер C — vLLM для инференса. Обновление библиотек в одном окружении не должно ломать остальные.

Но Docker не превращает один ускоритель в несколько автоматически изолированных физических GPU. Если два контейнера используют одну карту, они делят вычислительные ресурсы и VRAM. На совместимых дата-центровых ускорителях для аппаратного разделения можно применять MIG, но это функция конкретной GPU и инфраструктуры.

Если контейнеры постоянно обслуживают модели, полезно отдельно оценить серверную платформу. Общие сценарии разобраны в материале DigitalRazor «Для чего нужен GPU-сервер».

Для компактного локального инференса, RAG, разработки и тестирования можно использовать RackStation AI с одной-двумя GPU. Для нескольких параллельных R&D-окружений и более тяжёлых ИИ-нагрузок подойдёт масштабируемый DevBox AI на нескольких ускорителях.

DEVBOX AI DV64-64-512
Для каких задач Для локального обучения LLM, генеративных моделей и R&D
Подробнее
Видеокарты
4 x NVIDIA RTX 5080 16GB
Объем видеопамяти 64 ГБ
Процессоры
Threadripper PRO 7985WX
Количество ядер 64
RAM 512GB DDR5
Форм-фактор 6.5U
DEVBOX AI DV64-128-512
Для каких задач Для локального обучения LLM, генеративных моделей и R&D
Подробнее
Видеокарты
4 x NVIDIA RTX 5090 32GB
Объем видеопамяти 128 ГБ
Процессоры
Threadripper PRO 7985WX
Количество ядер 64
RAM 512GB DDR5
Форм-фактор 6.5U
DEVBOX AI DV96-576-1024
Для каких задач Для локального обучения LLM, генеративных моделей и R&D
Подробнее
Видеокарты
6 x NVIDIA RTX PRO 6000 96GB
Объем видеопамяти 576 ГБ
Процессоры
Threadripper PRO 7995WX
Количество ядер 96
RAM 1024GB DDR5
Форм-фактор 6.5U

Деплой Docker-приложений на сервер

Локальный запуск — только половина задачи. Следующий этап — доставить проверенную версию на сервер и обновлять её без ручной установки зависимостей.

Если сам сервер ещё не подготовлен, SSH, базовую безопасность, домен, HTTPS и Nginx отдельно разбираем в гайде «Как развернуть VDS/VPS-сервер».

Для постоянного контейнеризованного инференса сервер должен выдерживать не только саму модель, но и параллельные сервисы, базы данных, RAG и фоновые задачи.

Нужна помощь с выбором сервера?

Специалисты помогут подобрать оборудование под нагрузку, бюджет и задачи

Написать

Подготовка сервера

  • Linux-сервер и SSH-доступ;
  • Docker Engine;
  • Compose plugin, если используется Compose;
  • Доступ к registry;
  • Место под образы и volumes;
  • Открытые только необходимые порты.

Публично выставлять Docker daemon в интернет без правильно настроенной защиты не нужно. Для GPU-сервера дополнительно устанавливаются NVIDIA-драйвер и NVIDIA Container Toolkit.

От локального образа до registry и сервера

Рабочая последовательность состоит из нескольких коротких команд. Локально выполняется docker build -t myapp:1.2 ., затем docker tag myapp:1.2 username/myapp:1.2 и docker push username/myapp:1.2. На сервере нужную версию получают через docker pull username/myapp:1.2.

Сервер получает версию образа, на которую в момент загрузки указывает тег 1.2. Если нужна строгая воспроизводимость развёртывания, образ можно закрепить по digest sha256. Серверу не нужно отдельно ставить Python-пакеты или вручную воспроизводить окружение. Та же схема хорошо ложится на CI/CD: Git → тесты → docker build → registry → сервер.

Развёртывание через Docker Compose

На сервере в compose.yaml указывают образ нужной версии, например username/myapp:1.2, публикуют необходимые порты и задают restart policy. Затем выполняют docker compose pull и docker compose up -d. Состояние проверяют через docker compose ps, а логи — через docker compose logs -f.

Для одного сервера этого достаточно во многих проектах. Когда приложение нужно распределять по кластеру машин, автоматически масштабировать и управлять десятками сервисов, начинается полноценная оркестрация контейнеров — например, через Kubernetes. Compose не заменяет кластерный оркестратор.

Когда на одном сервере одновременно работают инференс, RAG, API и несколько экспериментальных окружений, важны уже не только Docker и Compose, но и количество GPU, VRAM, оперативная память и возможность расширения системы.

Обновление приложения и откат версии

Готовый Docker-образ не редактируют на сервере вручную. Для новой версии собирается новый образ, например username/myapp:1.3, и отправляется в registry. Затем в compose.yaml меняется тег с 1.2 на 1.3, после чего выполняются docker compose pull и docker compose up -d.

Build cache позволяет не пересобирать неизменившиеся слои. Если проблема обнаружилась уже после релиза, для отката достаточно вернуть в Compose предыдущий тег образа и снова запустить обновление проекта. Такой подход надёжнее попытки «починить» контейнер вручную через docker exec.

Healthcheck и автоматический перезапуск

Restart policy и healthcheck решают разные задачи. Параметр restart: unless-stopped определяет, нужно ли перезапустить завершившийся процесс. Healthcheck проверяет, способен ли сервис реально выполнять работу.

Процесс может оставаться запущенным, но база ещё не принимать подключения, а веб-сервис — зависнуть. Поэтому состояние running не равно healthy. Ни healthcheck, ни restart policy при этом не обеспечивают полноценную высокую доступность сами по себе: для отказоустойчивости нужны резервирование, балансировщик и инфраструктура уровнем выше одного контейнера.

Важно

Статус unhealthy сам по себе не заставляет обычный Docker Engine перезапустить контейнер. Restart policy срабатывает при остановке процесса. Для автоматической реакции на healthcheck нужен дополнительный механизм или оркестратор.

Частые ошибки при работе с Docker

Docker позволяет быстро получить рабочий результат, поэтому часть проблем проявляется уже после переноса приложения на сервер.

  • Данные базы хранятся только во внутреннем слое контейнера;
  • Все версии помечены единственным тегом latest;
  • Секреты попадают в Dockerfile или Git;
  • Build context содержит гигабайты ненужных файлов;
  • Ранний COPY . . постоянно сбрасывает build cache;
  • Production-образ содержит компилятор и build-инструменты;
  • Наружу опубликованы лишние порты;
  • Нет healthcheck и restart policy;
  • Контейнер получает лишние привилегии;
  • Сторонний образ используется без проверки происхождения.

Если сервер собирается под несколько контейнеров и разные рабочие нагрузки, конфигурацию лучше сразу рассчитывать с запасом по GPU, VRAM, оперативной памяти и накопителям.

Выберите решение для работы

Найдите готовый компьютер под вашу профессию

Подобрать ПК

Безопасность контейнеров

Контейнеризация улучшает изоляцию приложений, но контейнер нельзя считать непроницаемой песочницей. Особенно опасно без необходимости использовать --privileged: такой режим выдаёт контейнеру существенно больше возможностей на хосте.

Не следует подключать неизвестному приложению /var/run/docker.sock, хранить пароль через инструкцию ENV DATABASE_PASSWORD=... в Dockerfile или копировать приватные ключи в образ. Приложение по возможности запускают не от root, bind mounts дают только туда, где они нужны, а запись отключают, если достаточно чтения.

Для сторонних CUDA-образов действуют те же правила. Наличие CUDA в названии не делает образ безопасным: нужно проверять registry, издателя, содержимое, права и то, какие каталоги и устройства контейнер получает от хоста.

Частые вопросы (FAQ)

1. Чем Docker-образ отличается от контейнера?
Docker-образ — неизменяемый шаблон с приложением и зависимостями. Контейнер — запущенный экземпляр этого образа со своим состоянием выполнения и записываемым слоем.
2. Можно ли запускать несколько контейнеров с GPU одновременно на одном сервере?
Да. Контейнеры могут использовать разные GPU или делить одну карту. Во втором случае они конкурируют за вычислительные ресурсы и VRAM, поэтому Docker сам по себе не гарантирует производительность каждого процесса.
3. Нужен ли ещё nvidia-docker или его полностью заменил NVIDIA Container Toolkit?
Для современных установок используется NVIDIA Container Toolkit. Старые пакеты nvidia-docker2 и отдельный nvidia-container-runtime относятся к прежней схеме и не нужны в новом типовом развёртывании.
4. Как обновить образ приложения без пересборки всего проекта?
Docker использует build cache и повторно применяет неизменившиеся слои. После изменения инструкции или её входных файлов этот слой и последующие строятся заново. Готовый старый образ при этом не редактируется.
5. Безопасно ли запускать в Docker-контейнерах чужие CUDA-образы?
Только после проверки источника и содержимого. Контейнер не даёт абсолютной защиты. Неизвестному образу нельзя без необходимости выдавать --privileged, Docker socket, секреты и запись в важные каталоги хоста.

Заключение

Рабочая схема Docker довольно проста: Dockerfile описывает окружение, docker build создаёт версионированный образ, registry хранит его, а Docker или Compose запускает тот же пакет на сервере. Volumes отделяют постоянные данные от заменяемых контейнеров, сети связывают сервисы, а healthcheck и restart policy помогают контролировать их состояние.

Для GPU в Docker к этой цепочке добавляются совместимый NVIDIA-драйвер на хосте и NVIDIA Container Toolkit. После настройки разные CUDA-образы и версии фреймворков можно держать в отдельных окружениях, не превращая сервер в набор конфликтующих системных зависимостей.

Если приложение выросло от экспериментального контейнера до постоянного инференса, RAG или нескольких ИИ-сервисов, оборудование стоит подбирать под число GPU, объём VRAM и характер нагрузки. Подробнее о локальных моделях читайте в материале DigitalRazor «Какие модели ИИ можно развернуть на своём ПК или сервере».

Мы поможем подобрать GPU-сервер под количество контейнеров, размер модели и требуемый объём видеопамяти — без лишнего запаса по компонентам.

Scale
Для каких задач Сервер промышленного уровня на 8 GPU с кластерной архитектурой. Предназначен для дата-центров и AI-ферм, где требуется масштабируемость и полная загрузка ресурсов под обучение LLM и R&D.
Подробнее
Видеокарты
RTX PRO 6000 / RTX 5090
Объем видеопамяти до 768 ГБ
Процессоры
AMD Epyc, Intel Xeon
Количество ядер до 320
RAM до 3072 ГБ DDR5
Форм-фактор 6U
HPC 8000
Для каких задач Серия серверов для кластеризации на 8 GPU. Предназначены для дата-центров и AI-ферм, где требуется повышенная плотность для обучение LLM и R&D.
Подробнее
Видеокарты
L40s / RTX PRO / H200 NVL
Объем видеопамяти до 1128 ГБ
Процессоры
AMD EPYC, Intel Xeon
Количество ядер до 256
RAM до 2048 ГБ DDR5
Форм-фактор 4U
HGX H200
Для каких задач HGX объединяет 8 видеокарт NVIDIA H200, достигая экстремальной плотности производительности. Благодаря внутренней связности NVSwitch мгновенно интегрируется в масштабные вычислительные кластеры.
Подробнее
Видеокарты
NVIDIA H200 SXM
Объем видеопамяти до 1128 ГБ
Процессоры
AMD EPYC, Intel Xeon
Количество ядер до 256
RAM до 2048 ГБ DDR5
Форм-фактор 5U
Подберём решение под ваш проект

Расскажите о задаче — предложим оптимальную конфигурацию и реализацию.

Обсудить проект
или свяжитесь с нами
Telegram Telegram WhatsApp WhatsApp ВКонтакте ВКонтакте MAX MAX
291

Так же будет интересно почитать

Сайт использует cookies
Узнать подробнее