【问题标题】:Overwrite volume contents with container's contents用容器的内容覆盖卷内容
【发布时间】:2022-01-08 20:18:01
【问题描述】:

我有一个卷,其中包含需要保持不变的数据。第一次创建卷并将其挂载到我的节点容器时,所有容器内容都会复制到卷中,并且一切都按预期运行。问题是,当我更改节点容器中的一些文件时,我删除了旧图像和容器,并从头开始重建它们。运行更新的容器时,容器的文件不会被复制到卷中。这意味着该卷仍然包含旧文件,因此当该卷安装在容器中时,不存在更新的功能,我必须从头开始删除并重新创建该卷,因为卷的数据我不能这样做需要持久化。

这是我的 dockerfile

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 - \ 
    && apt update \
    && 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

我会看到更新后的文件发生变化,但不,我只看到第一次挂载卷时首次创建的旧文件。 所以我的问题是,有没有办法在创建容器时实现覆盖卷的文件?

【问题讨论】:

  • 你能把你的数据和你的源代码放在不同的目录吗?然后您可以在/data 上挂载一个持久卷,它不会覆盖/app 中的图像代码。由于您在此处描述的生命周期原因,您通常不应该将您的应用程序或库依赖项保留在卷中(也因为“将文件复制到卷中”不适用于不是专门为 Docker 命名的卷)。
  • @DavidMaze 所以我创建了一个包含所有数据的卷 /data,但是 /app 也需要访问这个 /data,因为服务器需要访问这些文件。但问题仍然存在,因为在重建映像并将 /app 卷安装到容器时,更改的文件仍然不会更新,因为问题似乎仍然存在,我无法用容器的卷文件覆盖文件
  • 正确,/app 需要从/data 读取。 (或者它可以是/app/data 的子目录,这很好,只要与拥有应用程序的目录不同的任何地方。)您不会在/app 上安装卷,只有数据目录。
  • @DavidMaze 好吧,这就像一个魅力。你介意添加这个作为答案,这样我就可以接受它,如果他们遇到这样的问题,其他人会找到答案吗?

标签: docker dockerfile docker-volume docker-container


【解决方案1】:

如果您的应用程序需要持久数据,则应将其存储在与应用程序代码不同的目录中。这可以在专用的/data 目录中或在您的应用程序的子目录中;重要的是,当你挂载一个卷来保存持久数据时,它不会隐藏你的应用程序代码。

例如,在 Node 应用程序中,您可以为数据文件引用 ./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 && 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

【讨论】:

    猜你喜欢
    • 2017-02-18
    • 2018-03-30
    • 2022-09-29
    • 1970-01-01
    • 2019-04-26
    • 1970-01-01
    • 2012-05-30
    • 2014-04-27
    • 1970-01-01
    相关资源
    最近更新 更多