Изменения в файловой системе внутри контейнера не отражаются на хосте в томе докера - PullRequest
0 голосов
/ 28 апреля 2019

Я работаю на сервере Express, написанном на TypeScript.Поток проекта заключается в том, что у меня есть скрипт сборки npm, который берет файлы проекта в папке src и компилирует их в папку dist.Обе эти папки живут в корневом каталоге.Проект работает, но при попытке переместить все в Docker, хотя я монтирую том и встроенные файлы (каталог dist) находится в контейнере, изменения не отражаются на хосте.(Я использую Windows + VirtualBox для Docker)

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

Структура каталогов проекта:

├── Backend
│   ├── src/
│   │   ├── controllers/
│   │   ├── models/
│   │   ├── routes/
│   │   ├── services/
│   │   ├── index.ts
│   │   └── server.ts
│   ├── dist/ (Created upon compilation)
│   │   ├── controllers/
│   │   ├── data/ (Created upon starting the server)
│   │   ├── models/
│   │   ├── routes/
│   │   ├── services/
│   │   ├── index.js
│   │   └── server.js
│   ├── Dockerfile
│   ├── package.json
│   ├── tsconfig.json
│   ├── tslint.json
│   └── .env
├── Frontend/ (This part is an independent application)
├── docker-compose.yml
└── README.md

Когда сервер запускается, он создаеткаталог в %proj_root%/Backend/dist с именем data, который используется для ввода данных приложению через текстовые файлы.Компиляция работает хорошо, как видно из команд ls, которые я поместил в Dockerfile, но изменения, сделанные внутри контейнера (создание каталога dist), не отражаются на хосте.На хосте каталог dist пуст, что приводит к сбою сервера из-за отсутствия файла server.js.

Вот мой docker-compose.yml:

version: "3"
services:
  backend:
    build:
      context: ./Backend/
    volumes:
      - ./Backend/dist:/app/dist
      - /app/node_modules
      - ./Backend:/app
  frontend:
    build:
      context: ./Frontend
    ports:
      - "3001:8080"
    volumes:
      - /app/node_modules
      - ./Frontend:/app

Вот файл Dockerfileдля службы Backend:

FROM node:8
WORKDIR /app
COPY ./package.json .
RUN npm install
COPY . . # Copying everything to enable standalone usage
RUN ls # Logging before tsc build
RUN npm run build
RUN ls /app/dist # Logging after tsc build. All the built files are visible.
CMD ["npm", "run", "start"]

После запуска docker-compose up папка dist должна быть создана в контейнере (/app/dist) и отображаться на хосте как %proj_root%/Backend/dist

Я понимаюЯ мог бы создать скрипт, который компилирует TS, а затем запускает docker-compose, но для меня это выглядит хакерским подходом.Есть ли лучшее решение?

1 Ответ

3 голосов
/ 28 апреля 2019

Настройка docker-compose.yml, которую вы показываете, делает две независимые вещи. Во-первых, он создает образ Docker, используя Dockerfile, который вы даете ему изолированно. Во-вторых, он берет это изображение, монтирует тома и применяет другие параметры, а также запускает контейнер на основе этих параметров. Последовательность сборки образа Docker игнорирует все эти другие настройки; ничто из того, что вы делаете в Dockerfile, не может изменить файлы в хост-системе.

Когда вы запускаете контейнер, любой контент в настройках volumes:, который вы передаете полностью , заменяет то, что получилось из этого изображения. Это всегда односторонняя «вставка в контейнер»: содержимое каталога Backend вашего хоста заменяет /app в контейнере; содержимое анонимного тома заменяет его node_modules, а содержимое каталога list хоста заменяет /app/dist.

Существует одно исключение особого случая. При запуске контейнера, если монтирование тома пусто, содержимое образа копируется на том. Это происходит только в том случае, если в дереве томов нет абсолютно ничего. Если в каталоге хоста dist уже есть контент или анонимный том node_modules, он заменяет все, что было в образе, даже если оно изменилось в образе (или изменилось в томе, Docker не может сказать).

В качестве одноразового решения, если вы

rm -rf dist

затем при следующем запуске контейнера Docker заметит, что каталог dist пуст и заполнит его из образа.

Я бы рекомендовал просто удалить эти volumes: настройки. Если вы активно разрабатываете программное обеспечение, делайте это на хосте: Node очень легко установить с типичными менеджерами пакетов ОС, ваша IDE не будет смущена тем, что ваш интерпретатор Node скрыт внутри контейнера, и вы не нажмете такого рода проблемы. Когда вы приступаете к развертыванию, вы можете просто использовать образ Docker как есть, без отдельного распространения кода, который также находится внутри образа.

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