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命令,但是同样的问题。
答案 0 :(得分:4)
首先,您不能为COPY
使用绝对路径。所有路径都必须为inside the context of the build,这意味着相对于Dockerfile
。如果主机上的文件夹结构是这样
my-docker-directory
-- Dockerfile
-- docker-compose.yml
-- addons
然后您就可以使用COPY addons /path/to/directory/inside/container
。对于所有后续解释,我假设您相对于addons
有一个Dockerfile
文件夹。
COPY
并不只是在运行时将文件夹安装到容器。它实际上根本没有 mount 目录。而是将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
以及何时使用卷?重要的是要意识到COPY
和ADD
会在构建时将内容复制到映像中,其中volumes
在运行时将它们从主机上挂载(而不将其包含在图片中)。因此,通常会将用户需要的常规内容复制到映像中,例如默认配置文件。
卷必须包含来自主机的文件,例如自定义配置文件。或将持久性事物作为数据库的数据目录。没有卷,这些容器就可以工作,但不是持久的。因此,当容器重新启动时,所有内容都会丢失。
请注意,一个并不排除另一个。最好为映像中的某些应用程序设置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
请注意,我们没有重新构建图像,我们的修改立即生效。使用卷,文件不包含在图像中。
答案 1 :(得分:0)
将您的插件文件夹移至Dockerfile所在的位置,然后运行
mkdir -p /path/to/directory/inside/container
COPY ./addons/* /path/to/directory/inside/container
答案 2 :(得分:0)
COPY命令在构建时将内容复制到映像。安装卷是另一回事。要进行安装,您需要使用
docker run -v <volume_name>:<volume_name> ...
您到底要实现什么?您是否要查看主机中容器内的文件夹?