将内容从主机 OS 复制到 Docker 图像而不重建图像
Copy contents from host OS into Docker image without rebuilding image
我正在构建一个新映像,并将主机 OS 文件夹 D:\Programs\scrapy 中的内容复制到其中,如下所示:docker build . -t scrapy
Dockerfile
FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
RUN mkdir root
RUN cd root
WORKDIR /root
RUN mkdir scrapy
COPY scrapy to /root/scrapy
现在,当我将新内容添加到主机 OS 文件夹“D:\Programs\scrapy”时,我还想将其添加到图像文件夹“root/scrapy”,但我不知道我想建立一个全新的形象(需要相当长的时间)。
那么如何保留现有图像并覆盖图像文件夹“root/scrapy”的内容。
另外:我不想每次 运行 容器时都复制新内容(所以不是在 运行 时),我只想拥有一个单独的命令,用于将更多文件添加到现有图像,然后 运行 另一个基于该图像的新容器。
我在这里查看:How to update source code without rebuilding image(但不确定 OP 是否尝试与我做同样的事情)
更新 1
正在检查 and docker --volume format for Windows
我尝试了以下命令,均导致错误:
docker: Error response from daemon: invalid volume specification: ''. See 'docker run --help'.
其中 <pathiused>
例如 D:/Programs/scrapy:/root/scrapy
docker run -v //D/Programs/scrapy:/root/scrapy scrapy
docker run -v scrapy:/root/scrapy scrapy
docker run -it -v //D/Programs/scrapy:/root/scrapy scrapy
docker run -it -v scrapy:/root/scrapy scrapy
根据@Makariy 的反馈使用 cp
命令进行更新
docker images -a
给出:
REPOSITORY TAG IMAGE ID CREATED SIZE
scrapy latest e35e03c8cbbd 29 hours ago 5.71GB
<none> <none> 2089ad178feb 29 hours ago 5.71GB
<none> <none> 6162a0bec2fc 29 hours ago 5.7GB
<none> <none> 116a0c593544 29 hours ago 5.7GB
mcr.microsoft.com/windows/servercore ltsc2019 d1724c2d9a84 5 weeks ago 5.7GB
I 运行 docker run -it scrapy
然后 docker container ls
给出:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1fcda458a14c scrapy "c:\windows\system32…" About a minute ago Up About a minute thirsty_bassi
如果我 运行 docker cp D:\Programs\scrapy scrapy:/root/scrapy
我得到:
Error: No such container:path: scrapy:\root
所以在一个单独的 PowerShell 实例中,我然后 运行 docker cp D:\Programs\scrapy thirsty_bassi:/root/scrapy
在 PowerShell 中没有显示任何输出,所以我认为它应该做一些事情。
但是在我的容器实例中,当我转到 /root/scrapy 文件夹时,我只能看到构建图像时已经添加的文件,而不是我想要添加的新文件。
另外,我想我是在这里向容器中添加文件,但是没有办法将它添加到图像中吗?不重建整个图像?
更新 2
我的文件夹结构:
D:\Programs
Dockerfile
\image_addons
Dockerfile
\scrapy
PS D:\Programs>docker build . -t scrapybase
成功构建95676d084e28
成功标记 scrapybase:latest
PS D:\Programs\image_addons> docker build -t scrapy .
Step 2/2 : COPY scrapy to /root/scrapy
COPY failed: file not found in build context or excluded by .dockerignore: stat to: file does not exist
Dockerfile A
FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
WORKDIR /root/scrapy
Dockerfile B
FROM scrapybase
COPY scrapy to /root/scrapy
对于您的场景:
docker run -v D:/test:/root/test your-image
此
中提供了很多有价值的详细信息
如果你想要它又快又脏,请回答
docker run -it -v c:/programs/test:/root/test ubuntu:latest cat /root/test/myTestFile.txt
快速更新一个文件:
如果您不必构建代码(我不知道您使用的是什么语言),您可以使用初始代码构建一些基本图像,并且当您只想更改一个文件时(我再次假设您不这样做)不需要为此再次编译你的项目,否则如果你这样做是不可能的,因为 compiled programming language):
FROM previous-version-image:latest
COPY myfile dest/to/file
那么因为你的 CMD
和 ENTRYPOINT
是从前面的阶段保存下来的,所以不需要声明它们。 (如果您不记得使用 docker history <docker-image-name>
查看虚拟 docker 图像文件到此阶段)。
注意不要重复使用这个方法,否则你会得到一个非常大的图像,有很多无用的图层。仅将其用于快速测试和调试。
说明
通常人们使用它在 docker 容器上进行前端开发,但基本思想仍然存在,您创建基本工作图像并安装依赖项并设置目录布局,最后一个 Dockerfile 命令是开发服务器启动命令。
示例:
Docker 文件:
# pull the base image
FROM node:slim
# set the working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
# copy dependencies files
COPY package.json ./
COPY package-lock.json ./
# install app dependencies
RUN npm install
# add app
COPY . ./
# start development server
CMD ["npm", "start"]
启动命令:
docker run -it --rm \
-v ${PWD}:/app \ <mount current working directory in host to container in path /app>
-v /app/node_modules \ <or other dependency directory if exists>
-p 80:3000 \ <ports if needs exposing>
ps-container:dev
我不确定该用例是否 100% 适合您,因为它需要一直使用 bind-mount 安装代码,并且在需要导出时必须导出为另一方面,它允许您快速更改图像和源代码目录,而无需在每次添加新内容时等待构建图像,并最终构建包含所有所需内容的最终图像。
问题提供代码的更多相关示例:
如您所见,主机上有一个包含一些文本的文件
使用 bind-mount 访问文件的命令:
docker run -it -v c:/programs/test:/root/test ubuntu:latest cat /root/test/myTestFile.txt
希望您能从我在这里提供的内容中找到适合您的内容。
感谢 this tutorial and this example 提供示例和信息。
编辑:
假设您的原始 Dockerfile 如下所示:
FROM python:latest
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD python /app/app.py
这将在我们将添加图层并更改 python 文件的基础上构建您的初始图像。
我们将使用的下一个 Dockerfile(我们称之为 Dockerfile.fix 文件)将复制我们想要更改的文件,而不是图像中已有的文件
FROM previous-image-name
COPY app.py .
现在,在使用这个 Dockerfile 构建之后,最终图像 Dockerfile 看起来(有点)像这样:
FROM python:latest
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD python /app/app.py
FROM previous-image-name
COPY app.py .
每次我们想要更改文件时,我们都会使用第二个 Dockerfile
您也可以使用 docker cp,将文件从您的主机手动复制到 运行 容器
docker cp ./path/to/file containername:/another/path
如果 Docker 图像不重建(至少是部分重建),则无法更改它。但是你不必重建全部,你可以重建复制你的scrapy
内容的图层。
您可以优化构建以拥有两个图像:
- 第一张图片是您不想每次都重建的静态图片。我们称它为
scrapy-base
.
- 第二张也是最后一张图片基于第一张图片
scrapy-base
,仅用于复制您的动态 scrapy
内容
scrapy-base
的Docker文件:
FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
RUN mkdir root
RUN cd root
WORKDIR /root
RUN mkdir scrapy
并将其构建为:
docker build -t scrapy-base .
这条命令只需要运行一次。如果您只更改本地 scrapy
文件夹的内容,则不必构建此映像。 (如您所见,构建根本没有使用它)
scrapy
的 Docker 文件:
FROM scrapy-base
COPY scrapy /root/scrapy
使用构建命令:
docker build -t scrapy .
这第二个构建命令将重新使用之前的静态图像并且只复制内容而无需重建整个图像。即使有很多文件,它也应该很快。您不需要 运行ning 容器。
我正在构建一个新映像,并将主机 OS 文件夹 D:\Programs\scrapy 中的内容复制到其中,如下所示:docker build . -t scrapy
Dockerfile
FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
RUN mkdir root
RUN cd root
WORKDIR /root
RUN mkdir scrapy
COPY scrapy to /root/scrapy
现在,当我将新内容添加到主机 OS 文件夹“D:\Programs\scrapy”时,我还想将其添加到图像文件夹“root/scrapy”,但我不知道我想建立一个全新的形象(需要相当长的时间)。
那么如何保留现有图像并覆盖图像文件夹“root/scrapy”的内容。
另外:我不想每次 运行 容器时都复制新内容(所以不是在 运行 时),我只想拥有一个单独的命令,用于将更多文件添加到现有图像,然后 运行 另一个基于该图像的新容器。
我在这里查看:How to update source code without rebuilding image(但不确定 OP 是否尝试与我做同样的事情)
更新 1
正在检查
我尝试了以下命令,均导致错误:
docker: Error response from daemon: invalid volume specification: ''. See 'docker run --help'.
其中 <pathiused>
例如 D:/Programs/scrapy:/root/scrapy
docker run -v //D/Programs/scrapy:/root/scrapy scrapy
docker run -v scrapy:/root/scrapy scrapy
docker run -it -v //D/Programs/scrapy:/root/scrapy scrapy
docker run -it -v scrapy:/root/scrapy scrapy
根据@Makariy 的反馈使用 cp
命令进行更新
docker images -a
给出:
REPOSITORY TAG IMAGE ID CREATED SIZE
scrapy latest e35e03c8cbbd 29 hours ago 5.71GB
<none> <none> 2089ad178feb 29 hours ago 5.71GB
<none> <none> 6162a0bec2fc 29 hours ago 5.7GB
<none> <none> 116a0c593544 29 hours ago 5.7GB
mcr.microsoft.com/windows/servercore ltsc2019 d1724c2d9a84 5 weeks ago 5.7GB
I 运行 docker run -it scrapy
然后 docker container ls
给出:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
1fcda458a14c scrapy "c:\windows\system32…" About a minute ago Up About a minute thirsty_bassi
如果我 运行 docker cp D:\Programs\scrapy scrapy:/root/scrapy
我得到:
Error: No such container:path: scrapy:\root
所以在一个单独的 PowerShell 实例中,我然后 运行 docker cp D:\Programs\scrapy thirsty_bassi:/root/scrapy
在 PowerShell 中没有显示任何输出,所以我认为它应该做一些事情。
但是在我的容器实例中,当我转到 /root/scrapy 文件夹时,我只能看到构建图像时已经添加的文件,而不是我想要添加的新文件。
另外,我想我是在这里向容器中添加文件,但是没有办法将它添加到图像中吗?不重建整个图像?
更新 2
我的文件夹结构:
D:\Programs
Dockerfile
\image_addons
Dockerfile
\scrapy
PS D:\Programs>docker build . -t scrapybase
成功构建95676d084e28
成功标记 scrapybase:latest
PS D:\Programs\image_addons> docker build -t scrapy .
Step 2/2 : COPY scrapy to /root/scrapy COPY failed: file not found in build context or excluded by .dockerignore: stat to: file does not exist
Dockerfile A
FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
WORKDIR /root/scrapy
Dockerfile B
FROM scrapybase
COPY scrapy to /root/scrapy
对于您的场景:
docker run -v D:/test:/root/test your-image
此
如果你想要它又快又脏,请回答
docker run -it -v c:/programs/test:/root/test ubuntu:latest cat /root/test/myTestFile.txt
快速更新一个文件: 如果您不必构建代码(我不知道您使用的是什么语言),您可以使用初始代码构建一些基本图像,并且当您只想更改一个文件时(我再次假设您不这样做)不需要为此再次编译你的项目,否则如果你这样做是不可能的,因为 compiled programming language):
FROM previous-version-image:latest
COPY myfile dest/to/file
那么因为你的 CMD
和 ENTRYPOINT
是从前面的阶段保存下来的,所以不需要声明它们。 (如果您不记得使用 docker history <docker-image-name>
查看虚拟 docker 图像文件到此阶段)。
注意不要重复使用这个方法,否则你会得到一个非常大的图像,有很多无用的图层。仅将其用于快速测试和调试。
说明
通常人们使用它在 docker 容器上进行前端开发,但基本思想仍然存在,您创建基本工作图像并安装依赖项并设置目录布局,最后一个 Dockerfile 命令是开发服务器启动命令。
示例:
Docker 文件:
# pull the base image
FROM node:slim
# set the working directory
WORKDIR /app
# add `/app/node_modules/.bin` to $PATH
ENV PATH /app/node_modules/.bin:$PATH
# copy dependencies files
COPY package.json ./
COPY package-lock.json ./
# install app dependencies
RUN npm install
# add app
COPY . ./
# start development server
CMD ["npm", "start"]
启动命令:
docker run -it --rm \
-v ${PWD}:/app \ <mount current working directory in host to container in path /app>
-v /app/node_modules \ <or other dependency directory if exists>
-p 80:3000 \ <ports if needs exposing>
ps-container:dev
我不确定该用例是否 100% 适合您,因为它需要一直使用 bind-mount 安装代码,并且在需要导出时必须导出为另一方面,它允许您快速更改图像和源代码目录,而无需在每次添加新内容时等待构建图像,并最终构建包含所有所需内容的最终图像。
问题提供代码的更多相关示例:
如您所见,主机上有一个包含一些文本的文件
docker run -it -v c:/programs/test:/root/test ubuntu:latest cat /root/test/myTestFile.txt
希望您能从我在这里提供的内容中找到适合您的内容。
感谢 this tutorial and this example 提供示例和信息。
编辑:
假设您的原始 Dockerfile 如下所示:
FROM python:latest
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD python /app/app.py
这将在我们将添加图层并更改 python 文件的基础上构建您的初始图像。 我们将使用的下一个 Dockerfile(我们称之为 Dockerfile.fix 文件)将复制我们想要更改的文件,而不是图像中已有的文件
FROM previous-image-name
COPY app.py .
现在,在使用这个 Dockerfile 构建之后,最终图像 Dockerfile 看起来(有点)像这样:
FROM python:latest
WORKDIR /app
COPY . .
RUN pip install -r requirements.txt
CMD python /app/app.py
FROM previous-image-name
COPY app.py .
每次我们想要更改文件时,我们都会使用第二个 Dockerfile
您也可以使用 docker cp,将文件从您的主机手动复制到 运行 容器
docker cp ./path/to/file containername:/another/path
如果 Docker 图像不重建(至少是部分重建),则无法更改它。但是你不必重建全部,你可以重建复制你的scrapy
内容的图层。
您可以优化构建以拥有两个图像:
- 第一张图片是您不想每次都重建的静态图片。我们称它为
scrapy-base
. - 第二张也是最后一张图片基于第一张图片
scrapy-base
,仅用于复制您的动态scrapy
内容
scrapy-base
的Docker文件:
FROM mcr.microsoft.com/windows/servercore:ltsc2019
SHELL ["powershell", "-Command", "$ErrorActionPreference = 'Stop'; $ProgressPreference = 'SilentlyContinue';"]
RUN mkdir root
RUN cd root
WORKDIR /root
RUN mkdir scrapy
并将其构建为:
docker build -t scrapy-base .
这条命令只需要运行一次。如果您只更改本地 scrapy
文件夹的内容,则不必构建此映像。 (如您所见,构建根本没有使用它)
scrapy
的 Docker 文件:
FROM scrapy-base
COPY scrapy /root/scrapy
使用构建命令:
docker build -t scrapy .
这第二个构建命令将重新使用之前的静态图像并且只复制内容而无需重建整个图像。即使有很多文件,它也应该很快。您不需要 运行ning 容器。