Перезаписать содержимое тома содержимым контейнера

#docker #dockerfile #docker-volume #docker-container

#докер #докерфайл #докер-объем #докер-контейнер

Вопрос:

У меня есть том, содержащий данные, которые необходимо сохранить. При первом создании тома и его установке в контейнер моего узла все содержимое контейнера копируется в том, и все ведет себя так, как ожидалось. Проблема в том, что когда я изменяю несколько файлов в контейнере узла, я удаляю старый образ и контейнер и перестраиваю их с нуля. При запуске обновленного контейнера файлы контейнера не копируются в том. Это означает, что том все еще содержит старые файлы, и поэтому, когда том монтируется в контейнере, никаких обновленных функций нет, и мне приходится удалять и воссоздавать том с нуля, что я не могу сделать, так как данные тома должны сохраняться.

Вот мой док-файл

 FROM mcr.microsoft.com/dotnet/sdk:5.0 COPY CommandLineTool App/CommandLineTool/  COPY NeedBackupNodeServer App/NeedBackupNodeServer/ WORKDIR /App/NeedBackupNodeServer RUN curl -sL https://deb.nodesource.com/setup_14.x | bash -    amp;amp; apt update   amp;amp; apt install -y nodejs EXPOSE 5001 ENTRYPOINT ["node", "--trace-warnings", "index.js"]  

Вот мои команды и ожидаемый результат

 docker volume create nodeServer-and-commandLineTool-volume   docker build -t need-backup-image -f Dockerfile .   docker run -p 5001:5001 --name need-backup-container -v nodeServer-and-commandLineTool-volume:/App need-backup-image -a   

при запуске

 docker exec need-backup-container cat index.js  

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

Теперь, когда я обновляю некоторые файлы, мне нужно перестроить образ и контейнер, поэтому я запускаю

 docker rm need-backup-container   docker rmi need-backup-image   docker build -t need-backup-image -f Dockerfile .   docker run -p 5001:5001 --name need-backup-container -v nodeServer-and-commandLineTool-volume:/App need-backup-image -a  

Теперь я думал, что, когда бежал

 docker exec need-backup-container cat index.js  

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

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

1. Можете ли вы разместить свои данные и исходный код в разных каталогах? Затем вы можете подключить постоянный том /data , и он не будет перезаписывать код изображения /app . Обычно вам не следует хранить зависимости вашего приложения или библиотеки в томах именно по причинам жизненного цикла, которые вы описываете здесь (а также потому, что «копирование файлов в том» не работает для вещей, которые не являются специально томами с именами Docker).

2. @DavidMaze Поэтому я создаю том /данные, который содержит все данные, но затем /приложению также необходимо получить доступ к этим /данным, так как сервер должен иметь доступ к этим файлам. Однако проблема все еще остается, потому что при восстановлении образа и установке тома /app в контейнер измененные файлы все равно не будут обновлены, поскольку, похоже, проблема все еще остается, поскольку я не могу перезаписать файлы тома файлами контейнера

3. Правильно, /app нужно почитать /data . (Или это может быть подкаталог /app/data , и это нормально, просто в любом месте, которое отличается от каталога, в котором находится соответствующее приложение.) Вы не монтируете том /app , а только каталог данных.

4. @DavidMaze Ну, это сработало как заклинание. Не могли бы вы добавить это в качестве ответа, чтобы я мог принять его, а другие нашли бы ответ, если бы столкнулись с такой проблемой?

Ответ №1:

Если вашему приложению требуются постоянные данные, они должны храниться в каталоге, отличном от кода приложения. Это может быть в выделенном /data каталоге или в подкаталоге вашего приложения; важно то, что при подключении тома для хранения постоянных данных он не скрывает код вашего приложения.

Например, в узловом приложении вы можете ссылаться на a ./data для файлов данных:

 import { open } from 'fs/promises'; import { join } from 'path'; const dataDir = process.env.DATA_DIR || 'data'; const fh = await open(join(dataDir, 'file.txt'), 'rw');  

Затем в вашем файле Dockerfile вам нужно будет создать этот каталог. Если вы настроили пользователя, не являющегося пользователем root, этот каталог, но не ваш код, должен принадлежать пользователю.

 FROM node:lts  # Create the non-root user RUN adduser --system --no-create-home nonroot  # Install the Node application normally WORKDIR /app COPY package*.json . RUN npm ci COPY index.js .  # Create the data directory RUN mkdir data amp;amp; chown nonroot data  # Specify how to run the container USER nonroot CMD ["node", "index.js"]  

Затем, когда вы запустите контейнер, смонтируйте том только в каталоге данных, а не по всему /app дереву.

 docker run   -p 5001:5001   --name need-backup-container   -v nodeServer-and-commandLineTool-volume:/app/data   need-backup-image # ^^^^^^^^^  

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

 docker run   -p 5002:5001   --name same-image-with-bind-mount   -u $(id -u)   -v "$PWD/app-data:/app/data"   need-backup-image