use*_*021 1 docker docker-compose
Host OS: Linux
Container OS: Linux
Run Code Online (Sandbox Code Playgroud)
我正在尝试学习如何使用 docker。我使用 docker-compose 并且成功构建了图像并运行了容器。
现在,如果我想在容器内挂载某个目录,文档表明我应该在 Dockerfile 内使用 COPY 命令。
COPY /path/to/my/addons/ /path/to/directory/inside/container
Run Code Online (Sandbox Code Playgroud)
遗憾的是,当我编写此容器时,COPY 命令被忽略,并且 /path/to/my/addons 中的内容无法进入容器。
我也尝试过使用ADD命令,但同样的问题。
首先,不能使用绝对路径COPY。所有路径必须位于构建的上下文中,这意味着相对于Dockerfile. 如果你的主机上的文件夹结构是这样的
my-docker-directory
-- Dockerfile
-- docker-compose.yml
-- addons
Run Code Online (Sandbox Code Playgroud)
然后你就可以使用COPY addons /path/to/directory/inside/container. 对于所有后续解释,我假设您有一个addons相对于Dockerfile.
COPY不只是在运行时将文件夹安装到容器。它根本没有真正挂载目录。相反,addons被复制到图像/path/to/directory/inside/container内部。重要的是要理解,这个过程是单向发生的(主机>镜像)并且仅在构建镜像时发生。
COPY旨在将构建时所需的依赖项添加到映像中,例如编译为二进制文件的源代码。这就是为什么你不能使用绝对路径的原因。ADockerfile通常与源代码/配置文件一起放置在顶层区域。
图像的构建过程仅在第一次运行时发生,除非您使用docker-compose up --build. 但这似乎并不是你想要的。要在运行时从主机挂载目录,请volume在docker-compose文件中使用 a:
version: '3'
services:
test:
build: .
volumes:
- ./addons/:/path/to/directory/inside/container
Run Code Online (Sandbox Code Playgroud)
COPY以及何时使用?认识到这一点很重要,COPY并将在构建时ADD将这些内容复制到映像中,并在volumes运行时从主机挂载它们(不将它们包含在映像中)。因此,您通常会将用户需要的一般内容(例如默认配置文件)复制到映像中。
卷需要包含来自主机的文件,例如自定义配置文件。或者作为数据库的数据目录的持久事物。如果没有卷,这些容器可以工作,但不会持久。因此,当容器重新启动时,所有内容都会丢失。
请注意,其中之一并不排除另一个。COPY镜像中某些应用程序的默认配置很好,用户可以使用卷覆盖它来修改它们。特别是在开发过程中,这可以使事情变得更容易,因为您不必为单个更改的配置文件重建整个映像*
* 尽管针对集成缓存机制优化 Dockerfile 是一个很好的做法。如果 aDockerfile写得好,重建小的配置更改通常不会花费太长时间。但这是这个范围之外的另一个话题。
COPY 设置Dockerfile举个简单的例子,我们从 nginx 网络服务器镜像创建一个Dockerfile并将 html 复制到其中
FROM nginx:alpine
COPY my-html /usr/share/nginx/html
Run Code Online (Sandbox Code Playgroud)
让我们创建包含演示内容的文件夹
mkdir my-html
echo "Dockerfile content" > my-html/index.html
Run Code Online (Sandbox Code Playgroud)
并添加一个简约的docker-compose.yml
version: '3'
services:
test:
build: .
Run Code Online (Sandbox Code Playgroud)
如果我们第一次使用 运行它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
Run Code Online (Sandbox Code Playgroud)
让我们操作我们的测试文件:
echo "NEW Modified content" > my-html/index.html
Run Code Online (Sandbox Code Playgroud)
如果我们再次请求服务器curl,我们会得到旧的响应:
root@server2:~/docker-so-example# curl $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-so-example_test_1)
Dockerfile content
Run Code Online (Sandbox Code Playgroud)
要应用我们的内容,需要重建:
docker-compose down && docker-compose up -d --build
Run Code Online (Sandbox Code Playgroud)
现在我们可以看到我们的更改:
root@server2:~/docker-so-example# curl $(docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' docker-so-example_test_1)
NEW Modified content
Run Code Online (Sandbox Code Playgroud)
docker-compose为了显示差异,我们通过修改文件来使用卷,docker-compose.yml如下所示:
version: '3'
services:
test:
build: .
volumes:
- ./my-html:/usr/share/nginx/html
Run Code Online (Sandbox Code Playgroud)
现在使用以下命令重新启动容器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
Run Code Online (Sandbox Code Playgroud)
请注意,我们没有重新构建图像,并且我们的修改会立即应用。使用卷时,文件不会包含在映像中。
| 归档时间: |
|
| 查看次数: |
1413 次 |
| 最近记录: |