#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