логотип PurpleSchool
логотип PurpleSchool

Использование Docker для контейнеризации приложений на Vue

Автор

Анна Кузнецова

Введение

Контейнеризация стала основой современной разработки благодаря своей гибкости, согласованности и простоте масштабирования приложений. Docker — самый популярный инструмент для создания, доставки и запуска контейнеров, который позволяет легко паковать приложения с их зависимостями для запуска в любом окружении. Если вы разрабатываете фронтенд-приложения на Vue, Docker способен упростить вашу жизнь и сделать процессы сборки и деплоя стабильными и предсказуемыми.

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

Что такое контейнеризация и зачем она Vue-разработчику

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

Для Vue‑разработчика преимущества такие:

  • Гарантированная стабильность среды: неважно, что установлено у вас, командных коллег или на сервере — приложение всегда ведет себя одинаково.
  • Лёгкий обмен проектом: любой, получив проект и Dockerfile, поднимает приложение одной командой.
  • Автоматизация CI/CD: сборка и доставка приложения на сервер автоматизируется, ошибки из-за различий версий Node и NPM пропадают.
  • Безопасность: процессы в контейнере изолированы, это уменьшает риски для основной системы.

Чистое приложение на Vue — с чего начать

Подготовка минимума для контейнеризации

Вот с этим сталкивается каждый: вы написали проект на Vue (например, на Vue CLI или Vite), теперь надо собрать его и запустить где угодно.

Первое, что вам понадобится:

  • Код проекта (желательно вычищенный от временных файлов)
  • package.json и package-lock.json (или yarn.lock)
  • Cкомпилированная версия приложения (dist/ или build/ – в зависимости от шаблона)

Кодовая база, структура обычно такая: my-vue-app/ └── src/ └── public/ └── package.json └── package-lock.json

Сборка Vue проекта для продакшн

Обычный workflow такой: сначала собираем Vue‑приложение в статические файлы, а затем обслуживаем их лёгким веб‑сервером (чаще всего Nginx). Это значит, что ваш Docker‑контейнер может быть очень легким — никакой NodeJS на продакшене уже не нужен!

Для сборки проекта выполните в терминале:

npm install
npm run build

Появится папка dist (или build при использовании других шаблонов). Именно её мы завернём в контейнер.

Теперь подготавливаем Dockerfile. Давайте разберём несколько подходов — для разработки и продакшена.

Dockerfile для разработки и продакшена — простые и многоступенчатые сборки

Dockerfile для локальной разработки

Когда вы разрабатываете, хочется, чтобы изменения в коде сразу отражались в браузере. Здесь можно использовать "горячую перезагрузку" (hot reload) из Vue CLI или Vite.

Вот базовый Dockerfile для разработки на Vue CLI:

# Используем официальный Node образ
FROM node:18

# Устанавливаем рабочую директорию внутри контейнера
WORKDIR /app

# Копируем package.json и lock-файл
COPY package*.json ./

# Устанавливаем зависимости
RUN npm install

# Копируем всё остальное приложение внутрь контейнера
COPY . .

# Открываем порт (по умолчанию 8080)
EXPOSE 8080

# Запускаем режим разработки
CMD ["npm", "run", "serve"]

Комментарии:

  • WORKDIR /app — все команды ниже будут выполняться из этой папки.
  • COPY package*.json ./ — сперва копируются только метаданные зависимостей; это нужно для кэширования слоёв (при изменениях в коде не нужен повторный npm install).
  • Контейнер всегда будет слушать порт 8080, который мы пробрасываем наружу с помощью опции -p.

Можно собрать с помощью команды:

docker build -t vue-dev .

и запустить:

docker run --rm -it -p 8080:8080 -v ${PWD}:/app vue-dev

Вот так подключается ваш проект как volume — при изменении кода результат сразу обновляется.

Dockerfile для продакшена c multi-stage build

Для продакшена принято не тянуть весь NodeJS в образ — он нужен только для сборки, но не для самого приложения. Вместо этого используется "multi-stage build". Смотрите, я покажу, как это реализовано:

# Первый этап: сборка приложения
FROM node:18 AS build-stage

WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build     # Получаем статические файлы в /app/dist

# Второй этап: минимальный Nginx для обслуживания статических файлов
FROM nginx:1.25-alpine as production-stage

# Удаляем дефолтную страницу Nginx (чтобы не мешала)
RUN rm -rf /usr/share/nginx/html/*

# Копируем собранные статические файлы из предыдущей стадии
COPY --from=build-stage /app/dist /usr/share/nginx/html

# Открываем 80 порт на сервере для доступа к приложению
EXPOSE 80

# Без изменений – дефолтный запуск nginx

Комментарии:

  • В первой секции на базе NodeJS только компилируется проект.
  • Вторая секция — это супер-легкий Nginx: только сервер для отдачи уже собранного контента, никаких зависимостей Vue или Node не остается внутри контейнера.
  • Использование COPY --from=... дает вам небольшой, максимально безопасный контейнер.

Пример build и run для продакшена

Собираем образ:

docker build -t vue-app-prod .

Запускаем контейнер:

docker run --rm -p 80:80 vue-app-prod

Теперь ваше приложение доступно на http://localhost/ — Nginx сам отдаёт файлы из dist.

Конфигурирование приложения и Docker

Окружение, переменные, сети

В крупных проектах часто надо прокидывать переменные окружения, настраивать сети и специальные параметры.

Работа с .env

Vue поддерживает переменные окружения через файл .env. Например:

VUE_APP_API_URL=https://api.example.com

В Dockerfile или docker-compose можно прокидывать переменные с помощью:

ENV VUE_APP_API_URL=https://api.example.com

и передавать их в build-команду:

docker build --build-arg VUE_APP_API_URL=https://api.example.com .

Внутри package.json для корректной работы переменных рекомендуют использовать префикс VUE_APP_.

Docker Compose для локальной разработки

Если у вас не только Vue, но и бэкенд/БД, удобнее настроить файл docker-compose.yaml. Вот пример такого файла для разработки:

version: "3.8"
services:
  frontend:
    build:
      context: .
      dockerfile: Dockerfile
    ports:
      - "8080:8080"
    volumes:
      - .:/app
    environment:
      - NODE_ENV=development

Так можно запускать, останавливать все контейнеры сразу:

docker-compose up

Настройка Nginx для SPA маршрутизации (history mode)

Vue часто используют в режиме history, где все роуты выглядят как "красивые" адреса (например, /profile, а не /#/profile). Но это требует от Nginx отдавать всегда один и тот же index.html при любом запросе (кроме API и статических).

Конфигурация для этого внутри контейнера (заменить стандартный nginx.conf):

server {
  listen 80;
  server_name localhost;

  location / {
    root /usr/share/nginx/html;
    try_files $uri $uri/ /index.html;
    index index.html;
  }
}

Добавьте этот файл в проект под именем, например, nginx.conf и подключите в Dockerfile:

COPY nginx.conf /etc/nginx/conf.d/default.conf

Теперь все нестандартные роуты SPA будут корректно работать.

Лучшие практики: безопасность, размер и кеширование

Минимизируйте размеры образа

  • Используйте образы Node и Nginx с тэгом alpine — меньше лишних утилит.
  • Не копируйте в образ ничего лишнего: папки типа .git, временные файлы, node_modules (если не нужны на этапе билда).
  • Multi-stage сборка особенно критична — иначе ваши исходники и секреты попадут внутрь финального контейнера.

Учитывайте кеширование сборки

Чтобы Docker не выполнял caroстоящие шага (npm install) повторно при мелких изменениях в коде, помещайте COPY package*.json ./ как можно раньше в Dockerfile, только после этого устанавливайте зависимости, затем копируйте весь проект.

Целевые оптимизации для CI/CD

В CI/CD пайплайнах советуют явно задавать тэги (не "latest"), чтобы всегда точно знать, какой образ деплоится. А также настраивать удаление временных образов.

Более сложные варианты: монтирование volume, кастомные Nginx

Если надо использовать кастомные плагины для Nginx, подключить сертификаты TLS или шардировать кэш, достаточно расширить стандартную конфигурацию Nginx и добавить нужные файлы с помощью COPY.

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

docker run -v ${PWD}:/app ...

Для деплоя полезно использовать CI/CD, которые автоматически строят контейнер, тестируют его и отправляют на сервер.

Заключение

Использование Docker для контейнеризации приложений на Vue — мощный инструмент, который упрощает процессы разработки и развертывания. Создавая чёткий, лаконичный Dockerfile, можно добиться повторяемости среды, минимизировать ошибки на продакшене и ускорить проектирование сервисов. Важно знать разницу между подходами для разработки и для продакшена, применять multi-stage сборку, настраивать корректные volume и окружение, а для фронтенд SPA — правильно конфигурировать web-сервер.

Контейнеризация повышает удобство командной работы, облегчает миграцию между платформами, способствует безопасности и удобству обновления ваших проектов на Vue.

Частозадаваемые технические вопросы по теме статьи и ответы на них

Вопрос 1: Как использовать Docker, если мой Vue-проект использует Vite вместо Vue CLI?
Ответ: Для Vite используйте практически такой же Dockerfile, но убедитесь, что порт по умолчанию — 5173 (или ваш). В CMD поменяйте на ["npm", "run", "dev", "--", "--host", "0.0.0.0"] чтобы сервер был доступен на всех интерфейсах внутри контейнера.

Вопрос 2: Почему не работают горячая перезагрузка и монтирование volume?
Ответ: Часто причина — у пользователя контейнера нет прав на изменение файлов. Запустите контейнер с тем же UID, что у пользователя на хосте, либо настройте права вручную. Добавьте в Dockerfile строку RUN chown -R node:node /app и запускайте от node: USER node.

Вопрос 3: Как проксировать API-запросы с Vue к бэкенду в Docker через nginx?
Ответ: Можно добавить в nginx.conf секцию:

location /api/ {
  proxy_pass http://backend:5000/api/;
}

И убедитесь, что сервис backend в docker-compose доступен по имени backend.

Вопрос 4: Как уменьшить размер образа — он слишком большой даже с Alpine?
Ответ: Проверьте, не копируются ли временные файлы (node_modules, .git, .env, файлы тестов). Используйте .dockerignore, чтобы исключить всё лишнее из билда. Не оставляйте исходники в финальном стадии multi-stage.

Вопрос 5: Как реализовать автоматическую сборку и деплой Docker Vue-приложения?
Ответ: Настройте CI (например, GitHub Actions или GitLab CI): добавьте шаги для сборки образа из Dockerfile и публикации в Docker Registry. Организуйте деплой на сервер с помощью команд docker pull и docker run. Для секрета registry используйте secrets/переменные в CI/CD.

Стрелочка влевоОрганизация и управление индексной страницей в проектах VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСтрелочка вправо

Все гайды по Vue

Руководство по валидации форм во Vue.jsИнтеграция Tiptap для создания редакторов на VueРабота с таблицами во Vue через TanStackИнструкция по установке и компонентам Vue sliderУправление пакетами Vue js с помощью npmУправление пакетами и node modules в Vue проектахКак использовать meta для улучшения SEO на VueПолный гайд по компоненту messages во Vuejs5 правил использования Inertia с Vue и LaravelРабота с модулями и пакетами в VueИнструкция по работе с grid на VueGithub для Vue проектов - подробная инструкция по хранению и совместной работеНастройка ESLint для Vue проектов и поддержка качества кодаОбработка ошибок и отладка в Vue.jsИспользование Vue Devtools для отладки и мониторинга приложенийРабота с конфигурационными файлами и скриптами VueСоздание и настройка проектов Vue с помощью Vue CLI3 способа интеграции Chart.js с Vue для создания графиковРабота с Canvas во VueИнструкция по реализации календаря во VueРабота с Ant Design Vue для создания UI на Vue
Обзор и использование утилит Vue для удобной разработкиРабота с обновлениями компонента и жизненным циклом updateРазрешение конфликтов и ошибок с помощью Vue resolveИспользование query-параметров и их обработка в маршрутах VueЗагрузка и управление состоянием загрузки в VueИспользование библиотек Vue для расширения функционалаРабота с JSON данными в приложениях VueКак работать с экземплярами компонента Instance во VueПолучение данных и API-запросы во Vue.jsЭкспорт и импорт данных и компонентов в VueОбработка событий и их передача между компонентами VuejsГайд по defineEmits на Vue 3Понимание core функционала Vue и его применениеПонимание и применение Composition API в Vue 3Понимание и работа с компилятором VueКогда и как использовать $emit и call во VueВзаимодействие с внешними API через Axios в Vue
Веб приложения на Vue архитектура и лучшие практикиИспользование Vite для быстрого старта и сборки проектов на Vue 3Работа с URL и ссылками в приложениях на VueРабота с пользовательскими интерфейсами и UI библиотеками во VueОрганизация и структура исходных файлов в проектах VueИспользование Quasar Framework для разработки на Vue с готовыми UI-компонентамиОбзор популярных шаблонов и стартовых проектов на VueИнтеграция Vue с PHP для создания динамичных веб-приложенийКак организовать страницы и маршруты в проекте на VueNuxt JS и Vue 3 для SSR приложенийСоздание серверных приложений на Vue с помощью Nuxt jsИспользование Vue Native для разработки мобильных приложенийОрганизация и управление индексной страницей в проектах VueИспользование Docker для контейнеризации приложений на VueИнтеграция Vue.js с Django для создания полноценных веб-приложенийСоздание и работа с дистрибутивом build dist Vue приложенийРабота со стилями и CSS в Vue js для красивых интерфейсовСоздание и структурирование Vue.js приложенияКак исправить ошибку cannot find module vueНастройка и сборка проектов Vue с использованием современных инструментовИнтеграция Vue с Bitrix для корпоративных решенийРазработка административных панелей на Vue js
5 библиотек для создания tree view во VueИнтеграция Tailwind CSS с Vue для современных интерфейсовИнтеграция Vue с серверной частью и HTTPS настройкамиКак обрабатывать async операции с Promise во VueИнтеграция Node.js и Vue.js для разработки приложенийРуководство по интеграции Vue js в NET проектыПримеры использования JSX во VueГайд по импорту и регистрации компонентов на VueМногоязычные приложения на Vue с i18nИнтеграция FLIR данных с Vue5 примеров использования filter во Vue для упрощения разработки3 примера реализации drag-and-drop во Vue
Управление переменными и реактивными свойствами во VueИспользование v for и slot в VueПрименение v-bind для динамической привязки атрибутов в VueУправление пользователями и их данными в Vue приложенияхСоздание и использование UI Kit для Vue приложенийТипизация и использование TypeScript в VuejsИспользование шаблонов в Vue js для построения интерфейсовИспользование Swiper для создания слайдеров в VueРабота со стилями и стилизацией в VueСтруктура и особенности Single File Components SFC в VueРабота со SCSS в проектах на Vue для стилизацииРабота со скроллингом и прокруткой в Vue приложенияхПрименение script setup синтаксиса в Vue 3 для упрощения компонентовИспользование scoped стилей для изоляции CSS в компонентах Vue3 способа улучшить навигацию Vue с push()Обработка запросов и асинхронных операций в VueПонимание и использование provide inject для передачи данных между компонентамиПередача и использование props в Vue 3 для взаимодействия компонентовПередача данных между компонентами с помощью props в Vue jsУправление property и функциями во Vue.jsРабота со свойствами компонентов VueУправление параметрами и динамическими данными во VueРабота с lifecycle-хуком onMounted во VueОсновы работы с объектами в VueПонимание жизненного цикла компонента Vue js на примере mountedИспользование модальных окон modal в Vue приложенияхИспользование методов в компонентах Vue для обработки логикиИспользование метода map в Vue для обработки массивовИспользование хуков жизненного цикла Vue для управления состоянием компонентаРабота с ключами key в списках и компонентах VueОбработка пользовательского ввода в Vue.jsРабота с изображениями и их оптимизация в VueИспользование хуков жизненного цикла в VueОрганизация сеток и гридов для верстки интерфейсов на VueСоздание и управление формами в VueОрганизация файлов и структура проекта Vue.jsКомпоненты Vue создание передача данных события и emitРабота с динамическими компонентами и данными в Vue3 способа манипулирования DOM на VueРуководство по div во VueИспользование директив в Vue и их расширенные возможностиОсновы и применение директив в VueИспользование директив и их особенности на Vue с помощью defineИспользование компонентов datepicker в Vue для выбора датОрганизация циклов и итераций во VueКак работает компиляция Vue CoreСоздание и использование компонентов в Vue JSОбработка кликов и пользовательских событий в VueИспользование классов в Vue для организации кода и компонентовИспользование директивы checked для управления состоянием чекбоксов в VueГайд на checkbox компонент во VueОтображение данных в виде графиков с помощью Vue ChartСоздание и настройка кнопок в VueСоздание и настройка кнопок в Vue приложенияхРабота с lifecycle-хуками beforeCreate и beforeMount во VueИспользование массивов и методов их обработки в VueИспользование массивов и их обработка в Vue
Использование Vuetify для создания современных интерфейсов на VueИспользование transition во VueТестирование компонентов и приложений на VueРабота с teleport для управления DOM во VueПять шагов по настройке SSR в VuejsИспользование Shadcn UI компонентов с Vue для продвинутых интерфейсовИспользование router-link для навигации в Vue RouterКак использовать require в Vue для динамического импорта модулейРабота с динамическим рендерингом и виртуальным DOM на Vue.jsИспользование ref для управления ссылками и реактивностью в Vue 3Использование Vue Pro и его преимущества для профессиональной разработкиРуководство по nextTick для работы с DOMСоздание и использование компонентов с помощью Vue js и CУправление состоянием и реактивностью через inject и provideДинамическое обновление компонентов и данных на VueГлубокое изучение документации Vue и как эффективно её использоватьИспользование Crystal с Vue для разработкиИспользование вычисляемых свойств для динамического отображения данных на Vue jsОптимизация производительности и предупреждения в Vue
Открыть базу знаний