gpt4 book ai didi

docker - Docker COPY命令未挂载目录

转载 作者:行者123 更新时间:2023-12-02 18:48:03 25 4
gpt4 key购买 nike

Host OS: Linux
Container OS: Linux

我正在尝试学习如何使用docker。我使用docker-compose,并且成功构建了镜像并运行了容器。

现在,如果我想在容器内挂载某个目录,文档说明我应该在Dockerfile中使用COPY命令。
COPY /path/to/my/addons/ /path/to/directory/inside/container

可悲的是,当我编写此容器时,COPY命令将被忽略,并且/ path / to / my / addons中的内容无法放入容器中。

我也尝试过用ADD命令,但是同样的问题。

最佳答案

绝对路径

首先,您不能对COPY使用绝对路径。所有路径都必须为inside the context of the build,这意味着相对于Dockerfile。如果主机上的文件夹结构是这样的

my-docker-directory
-- Dockerfile
-- docker-compose.yml
-- addons

那么您就可以使用 COPY addons /path/to/directory/inside/container了。对于所有后续解释,我假设您有一个相对于 addonsDockerfile文件夹。

挂载目录
COPY并不只是在运行时将文件夹挂载到容器。它根本没有真正挂载目录。而是将 addons复制到图像内的 /path/to/directory/inside/container。重要的是要了解,此过程是单向发生的(主机>镜像),并且仅在生成镜像时发生。
COPY旨在为构建时所需的镜像添加依赖项,例如将源代码编译为二进制文件。这就是为什么您不能使用绝对路径的原因。通常将 Dockerfile和源代码/配置文件放在顶层区域。

镜像的生成过程仅在第一次运行时发生,除非您使用 docker-compose up --build对其进行强制。但这似乎并不是您想要的。要在运行时从主机挂载目录,请在 volume文件中使用 docker-compose:
version: '3'
services:
test:
build: .
volumes:
- ./addons/:/path/to/directory/inside/container

何时使用 COPY和何时使用卷?

重要的是要意识到 COPYADD会在构建时将内容复制到镜像中,其中 volumes从主机在runtume处将它们装入(在镜像中不包含它们)。因此,通常会将用户需要的常规内容复制到镜像中,例如默认配置文件。

卷必须包含来自主机的文件,例如定制的配置文件。或将持久性事物作为数据库的数据目录。没有卷,这些容器可以工作,但不能持久。因此,当容器重新启动时,所有内容都会丢失。

请注意,一个并不排除另一个。可以使用 COPY镜像中某个应用程序的默认配置是很好的,用户可以在其中用卷覆盖它以修改它们。特别是在开发过程中,这可以使事情变得更容易,因为您不必为单个更改的配置文件重建整个镜像*

*最佳做法是针对集成缓存机制优化Dockerfile。如果 Dockerfile写得很好,那么重建较小的配置更改通常不会花费太长时间。但这是这个范围之外的另一个话题。

举例更详细的解释
COPY中的 Dockerfile的基本设置

作为简单的示例,我们从Nginx Web服务器图像创建一个 Dockerfile并在其中复制html
FROM nginx:alpine
COPY my-html /usr/share/nginx/html

让我们创建包含演示内容的文件夹
mkdir my-html
echo "Dockerfile content" > my-html/index.html

并添加一个简约的 docker-compose.yml
version: '3'
services:
test:
build: .

如果我们是使用 docker-compose up -d第一次运行它,则该图像已构建并提供了我们的测试页:
root@server2:~/docker-so-example# docker-compose up -d
Creating network "docker-so-example_default" with the default driver
Creating docker-so-example_test_1 ... done

root@server2:~/docker-so-example# curl $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-so-example_test_1)
Dockerfile content

让我们来操作我们的测试文件:
echo "NEW Modified content" > my-html/index.html

如果再次使用 curl请求服务器,则会得到旧的响应:
root@server2:~/docker-so-example# curl $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-so-example_test_1)
Dockerfile content

要应用我们的内容,需要重新构建:
docker-compose down && docker-compose up -d --build

现在我们可以看到我们的更改:
root@server2:~/docker-so-example# curl $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-so-example_test_1)
NEW Modified content

使用 docker-compose中的卷

为了显示差异,我们通过修改 docker-compose.yml文件来使用卷,如下所示:
version: '3'
services:
test:
build: .
volumes:
- ./my-html:/usr/share/nginx/html

现在,使用 docker-compose down && docker-compose up -d重新启动容器,然后重试:
root@server2:~/docker-so-example# echo "Again changed content" > my-html/index.html
root@server2:~/docker-so-example# curl $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-so-example_test_1)
NEW Modified content
root@server2:~/docker-so-example# echo "Some content" > my-html/index.html
root@server2:~/docker-so-example# curl $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-so-example_test_1)
Some content

请注意,我们没有重建图像,我们的修改立即生效。使用卷时,文件不包含在镜像中。

关于docker - Docker COPY命令未挂载目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/55197971/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com