Перевод статьи «Say Goodbye to Docker Volumes».
Вы когда-нибудь пытались использовать тома Docker для горячей замены (hot-reloading) в своем веб-приложении? Если вы получили такой же ужасный опыт, как и я, вам понравится новейшая функция, которую только что выпустил Docker: docker-compose watch!
В этой статье я расскажу, как обновить существующий проект, чтобы получить настройку среды разработки в Docker, которая точно понравится вашей команде.
TL;DR: Ознакомьтесь с этим файлом docker-compose и официальной документацией.
От редакции Techrocks: если вы еще не знакомы с Docker, познакомиться можно здесь — «Docker: практическое руководство для начинающих».
Приступим!
Введение
Docker только что выпустил Docker Compose Watch с Docker Compose версии 2.22. С помощью этой новой функции вы можете использовать docker-compose watch
вместо docker-compose up и автоматичес
ки синхронизировать локальный исходный код с кодом в контейнере Docker без необходимости использовать тома!
Давайте посмотрим, как это работает в реальном проекте. Об этом проекте я писал ранее.
В этом проекте у меня есть монорепозиторий с фронтендом, бэкендом и некоторыми дополнительными библиотеками для пользовательского интерфейса и базы данных.
├── apps │ ├── api │ └── web └── packages ├── database ├── eslint-config-custom ├── tsconfig └── ui
Оба приложения (api и web) уже докеризованы, а Docker-файлы находятся в корне проекта (1, 2).
Файл docker-compose.yml будет выглядеть следующим образом:
services: web: build: dockerfile: web.Dockerfile ports: - "3000:3000" depends_on: - api api: build: dockerfile: api.Dockerfile ports: - "3001:3000"from within the Docker network
Файл неплох, но, как вы знаете, работать с ним во время разработки очень хлопотно. Вам придется пересобирать образы Docker при каждом изменении кода, даже если ваши приложения, вероятно, поддерживают hot-reloading из коробки (а если нет, то с помощью чего-то вроде Nodemon).
Чтобы улучшить ситуацию, Docker Compose Watch вводит новый атрибут — watch
. Атрибут watch содержит список так называемых правил. Каждое правило содержит путь, за которым оно следит, и действие, которое будет выполнено, как только файл на этом пути изменится.
Синхронизация
Если вы хотите, чтобы между хостом и контейнером синхронизировалась папка, вы должны добавить следующий код:
services: web: # shortened for clarity build: dockerfile: web.Dockerfile develop: watch: - action: sync path: ./apps/web target: /app/apps/web
При изменении файла на хосте по пути ./apps/web/ он будет скопирован в ваш контейнер по адресу /app/apps/web. Дополнительный app
в целевом пути необходим, потому что это наша рабочая директория WORKDIR
, определенная в Dockerfile. Это главное, что вы, вероятно, будете использовать, если у вас есть приложения с возможностью hot-reloading.
Пересборка — rebuild
Если у вас есть приложения, которые нужно компилировать, или зависимости, которые нужно переустанавливать, вам поможет такое действие (action), как пересборка (rebuild). Вместо того чтобы просто копировать файлы между хостом и контейнером, оно перестроит и перезапустит контейнер. Это очень полезно для ваших npm-зависимостей! Давайте добавим это действие:
services: web: # shortened for clarity build: dockerfile: web.Dockerfile develop: watch: - action: sync path: ./apps/web target: /app/apps/web - action: rebuild path: ./package.json target: /app/package.json
При каждом изменении нашего package.json мы будем перестраивать весь наш Dockerfile для установки новых зависимостей.
Sync+Restart
Помимо синхронизации и пересборки есть еще и нечто среднее, называемое sync+restart
. Это действие сначала синхронизирует каталоги, а затем сразу же перезапускает контейнер без пересборки.
Большинство фреймворков обычно имеют конфигурационные файлы (например, next.config.js), которые не могут быть загружены в горячем режиме (просто синхронизировать недостаточно), но и не требуют медленной пересборки.
Ваш compose-file изменится следующим образом:
services: web: # shortened for clarity build: dockerfile: web.Dockerfile develop: watch: - action: sync path: ./apps/web target: /app/apps/web - action: rebuild path: ./package.json target: /app/package.json - action: sync+restart path: ./apps/web/next.config.js target: /app/apps/web/next.config.js
Оговорки
Но не все так радужно, есть и несколько предостережений.
Самая большая проблема с новым атрибутом watch заключается в том, что пути все еще очень простые. В документации говорится, что шаблоны Glob пока не поддерживаются, что может привести к огромному количеству правил.
Вот несколько примеров того, что работает, а что нет:
apps/web
Будет соответствовать всем файлам в ./apps/web (например, ./apps/web/README.md, а также ./apps/web/src/index.tsx)
build/**/!(*.spec|*.bundle|*.min).js
Глобы, к сожалению, (пока?) не поддерживаются.
~/Downloads
Все пути относительны к корню проекта!
Следующие шаги
Если вы все еще недовольны своей настройкой Docker, есть еще много способов ее улучшить!
Сотрудничество — важная часть разработки программного обеспечения, и работа в одиночку может нанести серьезный ущерб вашей команде. Медленные сборки Docker и сложные настройки не способствуют сотрудничеству! Чтобы противостоять этому, вы можете использовать расширения Docker, такие как Livecycle, для мгновенного обмена локальными приложениями docker-compose с членами вашей команды.
Поскольку вы уже используете Docker и docker-compose, все, что вам нужно сделать, — это установить расширение Docker Desktop Extension и нажать на переключатель share. После этого вы сможете поделиться уникальным URL-адресом с командой, чтобы получить отзывы!
Следите за тем, чтобы ваш Dockerfile соответствовал лучшим практикам, особенно в отношении многоступенчатых сборок и кэширования. Хотя это может усложнить написание начального Dockerfile, это сделает ваши Docker-приложения гораздо более приятными в использовании во время разработки.
Создание базового файла .dockerignore и разделение установки зависимостей и сборки кода поможет вам в этом!