Docker - 无法在卷内的容器之间共享数据 (docker-compose 3)
Docker - Can't share data between containers within a volume (docker-compose 3)
我现在有一些用于 Web 应用程序的容器(nginx、gunicorn、postgres 和 node,用于从源代码和 React 服务器端渲染构建静态文件)。在节点容器的 Dockerfile 中,我有两个步骤:构建和 运行 (Dockerfile.node)。它最终在容器内有两个目录:bundle_client
- 对于 nginx 是静态的,bundle_server
- 它在节点容器本身中用于启动快速服务器。
然后我需要与 nginx 容器共享一个内置的静态文件夹 (bundle_client
)。根据我 docker-compose.yml
中的 docker-compose 参考,我有以下服务(参见完整 docker-compose.yml):
node:
volumes:
- vnode:/usr/src
nginx:
volumes:
- vnode:/var/www/tg/static
depends_on:
- node
和卷:
volumes:
vnode:
运行 docker-compose build
完成且没有错误。 运行 docker-compose up
运行一切正常,我可以打开 localhost:80
并且 nginx、gunicorn 和 node express SSR 都运行良好,我可以看到一个网页,但都是静态的文件 return 404 未找到错误。
如果我用 docker volume ls
检查卷,我可以看到两个新创建的卷,名为 tg_vnode
(我们在这里考虑)和 tg_vdata
(参见完整的 docker-compose.yml)
如果我进入带有 docker run -ti -v /tmp:/tmp tg_node /bin/bash
的 nginx 容器,我看不到我的 www/tg/static
文件夹,它应该从节点卷映射我的静态文件。我还尝试用 nginx 容器 Dockerfile.nginx
创建一个空的 /var/www/tg/static
文件夹,但它仍然是空的。
如果我在 nginx.volumes
部分的 docker-compose.yml
中将主机中的 bundle_client
文件夹映射为 - ./client/bundle_client:/var/www/tg/static
它工作正常,我可以看到所有静态在浏览器中使用 nginx 提供的文件。
我做错了什么以及如何使我的容器与 nginx 容器共享构建的静态内容?
PS: 我阅读了所有文档、所有 github 问题和 Whosebug 问答,据我所知,它必须有效,但没有信息什么时候没有。
更新: docker volume inspect vnode
的结果:
[
{
"CreatedAt": "2018-05-18T12:24:38Z",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "tg",
"com.docker.compose.version": "1.21.1",
"com.docker.compose.volume": "vnode"
},
"Mountpoint": "/var/lib/docker/volumes/tg_vnode/_data",
"Name": "tg_vnode",
"Options": null,
"Scope": "local"
}
]
文件:
Dockerfile.node,
docker-compose.yml
Nginx docker文件:Dockerfile.nginx
UPD: 我创建了一个简化的 repo 来重现一个问题:repo
(在 npm install
上有一些警告,没关系,它安装和构建正常)。最终,当我们打开 localhost:80
时,我们在 Chrome 开发工具中看到一个空白页面和静态文件(vendor.js
和 app.js
)的 404 条消息,但应该有一条消息 React app: static loaded
由反应脚本生成。
逐步解释发生的事情
Dockerfile.node
...
COPY ./client /usr/src
...
docker-compose.yml
services:
...
node:
...
volumes:
- ./server/nginx.conf:/etc/nginx/nginx.conf:ro
- vnode:/usr/src
...
volumes:
vnode:
docker-compose up
使用此 Dockerfile.node 和 docker-compose 部分创建一个 命名卷 ,其中数据保存在 /usr/src 中。
Dockerfile.nginx
FROM nginx:latest
COPY ./server/nginx.conf /etc/nginx/nginx.conf
RUN mkdir -p /var/www/tg/static
EXPOSE 80
EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]
- 这导致使用
docker-compose
创建的 nginx 容器将有一个空的 /var/www/tg/static/
docker-compose.yml
...
nginx:
build:
context: .
dockerfile: ./Dockerfile.nginx
container_name: tg_nginx
restart: always
volumes:
- ./server/nginx.conf:/etc/nginx/nginx.conf:ro
- vnode:/var/www/tg/static
ports:
- "80:80"
- "443:443"
depends_on:
- node
- gunicorn
networks:
- nw_web_tg
volumes:
vdata:
vnode:
docker-compose up
将生成 vnode
命名卷已创建并填充了从 /var/www/tg/static
(现在为空)到现有 vnode 的数据。
所以,在这一点上,
- nginx 容器 /var/www/tg/static 是空的,因为它创建时是空的(参见 Dockerfile.nginx 中的 mkdir)
- 节点容器有包含客户端文件的 /usr/src 目录(请参阅在 Dockerfile.node 中复制)
- vnode 具有来自 node
的 /usr/src 和来自 nginx 的 /var/www/tg/static
的内容。
Definitively, to pass data from /usr/src from your node
container to /var/www/tg/static
in nginx
container you need to do something that is not very pretty because Docker hasn't developed another way yet: You need to combine named volume in source folder with bind volume in destination:
nginx:
build:
context: .
dockerfile: ./Dockerfile.nginx
container_name: tg_nginx
restart: always
volumes:
- ./server/nginx.conf:/etc/nginx/nginx.conf:ro
- /var/lib/docker/volumes/vnode/_data:/var/www/tg/static
ports:
- "80:80"
- "443:443"
depends_on:
- node
- gunicorn
networks:
- nw_web_tg
只需将 docker-compose - vnode:/var/www/tg/static
更改为 - /var/lib/docker/volumes/vnode/_data:/var/www/tg/static
您需要进行两项更改。在您的节点服务中添加如下卷:
volumes:
- vnode:/usr/src/bundle_client
既然你想分享 /usr/src/bundle_client
你不应该使用 /usr/src/
因为那样也会分享完整的文件夹和结构。
然后在您的 nginx 服务中添加如下卷:
volumes:
- type: volume
source: vnode
target: /var/www/test/static
volume:
nocopy: true
nocopy: true
明确了我们的意图,即在容器的初始映射中,不应复制映射文件夹的内容。默认情况下,第一个映射到卷的容器将获取映射文件夹的内容。在您的情况下,您希望它成为 node
容器。
另外,在测试之前,请确保您 运行 下面的命令杀死了缓存的卷:
docker-compose down -v
你可以在我的测试中看到容器有文件:
我现在有一些用于 Web 应用程序的容器(nginx、gunicorn、postgres 和 node,用于从源代码和 React 服务器端渲染构建静态文件)。在节点容器的 Dockerfile 中,我有两个步骤:构建和 运行 (Dockerfile.node)。它最终在容器内有两个目录:bundle_client
- 对于 nginx 是静态的,bundle_server
- 它在节点容器本身中用于启动快速服务器。
然后我需要与 nginx 容器共享一个内置的静态文件夹 (bundle_client
)。根据我 docker-compose.yml
中的 docker-compose 参考,我有以下服务(参见完整 docker-compose.yml):
node:
volumes:
- vnode:/usr/src
nginx:
volumes:
- vnode:/var/www/tg/static
depends_on:
- node
和卷:
volumes:
vnode:
运行 docker-compose build
完成且没有错误。 运行 docker-compose up
运行一切正常,我可以打开 localhost:80
并且 nginx、gunicorn 和 node express SSR 都运行良好,我可以看到一个网页,但都是静态的文件 return 404 未找到错误。
如果我用 docker volume ls
检查卷,我可以看到两个新创建的卷,名为 tg_vnode
(我们在这里考虑)和 tg_vdata
(参见完整的 docker-compose.yml)
如果我进入带有 docker run -ti -v /tmp:/tmp tg_node /bin/bash
的 nginx 容器,我看不到我的 www/tg/static
文件夹,它应该从节点卷映射我的静态文件。我还尝试用 nginx 容器 Dockerfile.nginx
创建一个空的 /var/www/tg/static
文件夹,但它仍然是空的。
如果我在 nginx.volumes
部分的 docker-compose.yml
中将主机中的 bundle_client
文件夹映射为 - ./client/bundle_client:/var/www/tg/static
它工作正常,我可以看到所有静态在浏览器中使用 nginx 提供的文件。
我做错了什么以及如何使我的容器与 nginx 容器共享构建的静态内容?
PS: 我阅读了所有文档、所有 github 问题和 Whosebug 问答,据我所知,它必须有效,但没有信息什么时候没有。
更新: docker volume inspect vnode
的结果:
[
{
"CreatedAt": "2018-05-18T12:24:38Z",
"Driver": "local",
"Labels": {
"com.docker.compose.project": "tg",
"com.docker.compose.version": "1.21.1",
"com.docker.compose.volume": "vnode"
},
"Mountpoint": "/var/lib/docker/volumes/tg_vnode/_data",
"Name": "tg_vnode",
"Options": null,
"Scope": "local"
}
]
文件: Dockerfile.node, docker-compose.yml
Nginx docker文件:Dockerfile.nginx
UPD: 我创建了一个简化的 repo 来重现一个问题:repo
(在 npm install
上有一些警告,没关系,它安装和构建正常)。最终,当我们打开 localhost:80
时,我们在 Chrome 开发工具中看到一个空白页面和静态文件(vendor.js
和 app.js
)的 404 条消息,但应该有一条消息 React app: static loaded
由反应脚本生成。
逐步解释发生的事情
Dockerfile.node
...
COPY ./client /usr/src
...
docker-compose.yml
services:
...
node:
...
volumes:
- ./server/nginx.conf:/etc/nginx/nginx.conf:ro
- vnode:/usr/src
...
volumes:
vnode:
docker-compose up
使用此 Dockerfile.node 和 docker-compose 部分创建一个 命名卷 ,其中数据保存在 /usr/src 中。
Dockerfile.nginx
FROM nginx:latest
COPY ./server/nginx.conf /etc/nginx/nginx.conf
RUN mkdir -p /var/www/tg/static
EXPOSE 80
EXPOSE 443
CMD ["nginx", "-g", "daemon off;"]
- 这导致使用
docker-compose
创建的 nginx 容器将有一个空的/var/www/tg/static/
docker-compose.yml
...
nginx:
build:
context: .
dockerfile: ./Dockerfile.nginx
container_name: tg_nginx
restart: always
volumes:
- ./server/nginx.conf:/etc/nginx/nginx.conf:ro
- vnode:/var/www/tg/static
ports:
- "80:80"
- "443:443"
depends_on:
- node
- gunicorn
networks:
- nw_web_tg
volumes:
vdata:
vnode:
docker-compose up
将生成vnode
命名卷已创建并填充了从/var/www/tg/static
(现在为空)到现有 vnode 的数据。
所以,在这一点上,
- nginx 容器 /var/www/tg/static 是空的,因为它创建时是空的(参见 Dockerfile.nginx 中的 mkdir)
- 节点容器有包含客户端文件的 /usr/src 目录(请参阅在 Dockerfile.node 中复制)
- vnode 具有来自 node
的 /usr/src 和来自 nginx 的 /var/www/tg/static
的内容。
Definitively, to pass data from /usr/src from your
node
container to/var/www/tg/static
innginx
container you need to do something that is not very pretty because Docker hasn't developed another way yet: You need to combine named volume in source folder with bind volume in destination:nginx: build: context: . dockerfile: ./Dockerfile.nginx container_name: tg_nginx restart: always volumes: - ./server/nginx.conf:/etc/nginx/nginx.conf:ro - /var/lib/docker/volumes/vnode/_data:/var/www/tg/static ports: - "80:80" - "443:443" depends_on: - node - gunicorn networks: - nw_web_tg
只需将 docker-compose - vnode:/var/www/tg/static
更改为 - /var/lib/docker/volumes/vnode/_data:/var/www/tg/static
您需要进行两项更改。在您的节点服务中添加如下卷:
volumes:
- vnode:/usr/src/bundle_client
既然你想分享 /usr/src/bundle_client
你不应该使用 /usr/src/
因为那样也会分享完整的文件夹和结构。
然后在您的 nginx 服务中添加如下卷:
volumes:
- type: volume
source: vnode
target: /var/www/test/static
volume:
nocopy: true
nocopy: true
明确了我们的意图,即在容器的初始映射中,不应复制映射文件夹的内容。默认情况下,第一个映射到卷的容器将获取映射文件夹的内容。在您的情况下,您希望它成为 node
容器。
另外,在测试之前,请确保您 运行 下面的命令杀死了缓存的卷:
docker-compose down -v
你可以在我的测试中看到容器有文件: