问题
I have some containers for a web app for now (nginx, gunicorn, postgres and node to build static files from source and a React server side rendering). In a Dockerfile for the node container I have two steps: build and run (Dockerfile.node). It ends up with two directories inside a container: bundle_client - is a static for an nginx and bundle_server - it used in the node container itself to start an express server.
Then I need to share a built static folder (bundle_client) with the nginx container. To do so according to docker-compose reference in my docker-compose.yml I have the following services (See full docker-compose.yml):
node:
volumes:
- vnode:/usr/src
nginx:
volumes:
- vnode:/var/www/tg/static
depends_on:
- node
and volumes:
volumes:
vnode:
Running docker-compose build completes with no errors. Running docker-compose up runs everyting ok and I can open localhost:80 and there is nginx, gunicorn and node express SSR all working great and I can see a web page but all static files return 404 not found error.
If I check volumes with docker volume ls I can see two newly created volumes named tg_vnode (that we consider here) and tg_vdata (see full docker-compose.yml)
If I go into an nginx container with docker run -ti -v /tmp:/tmp tg_node /bin/bash I can't see my www/tg/static folder which should map my static files from the node volume. Also I tried to create an empty /var/www/tg/static folder with nginx container Dockerfile.nginx but it stays empty.
If I map a bundle_client folder from the host machine in the docker-compose.yml in a nginx.volumes section as - ./client/bundle_client:/var/www/tg/static it works ok and I can see all the static files served with nginx in the browser.
What I'm doing wrong and how to make my container to share built static content with the nginx container?
PS: I read all the docs, all the github issues and stackoverflow Q&As and as I understood it has to work and there is no info what to do when is does not.
UPD: Result of 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"
}
]
Files: Dockerfile.node, docker-compose.yml
Nginx dockerfile: Dockerfile.nginx
UPD: I have created a simplified repo to reproduce a question: repo
(there are some warnings on npm install nevermind it installs and builds ok). Eventually when we open localhost:80 we see an empty page and 404 messages for static files (vendor.js and app.js) in Chrome dev tools but there should be a message React app: static loaded generated by react script.
回答1:
Two changes you need. In your node service ad d the volume like
volumes:
- vnode:/usr/src/bundle_client
Since you want to share /usr/src/bundle_client you should NOT be using /usr/src/ because that will share the full folder and the structure too.
And then in your nginx service add the volume like
volumes:
- type: volume
source: vnode
target: /var/www/test/static
volume:
nocopy: true
The nocopy: true keeps our intention clear that on initial map of the container the content of the mapped folder should not be copied. And by default the first container to get mapped to the volume will get the contents of the mapped folder. In your case you want this to be the node container.
Also before testing make sure you run below command to kill the cached volumes
docker-compose down -v
You can see during my test the container had the files
回答2:
Explanation of what happens step by step
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 upcreates with this Dockerfile.node and docker-compose section a named volume with data saved in /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;"]
- That produces that nginx containers created with
docker-composewill have an empty/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 upwill produce thatvnodenamed volume is created and filled with data from/var/www/tg/static(empty by now) to existing vnode.
So, at this point,
- nginx container has /var/www/tg/static empty because it was created empty (see mkdir in Dockerfile.nginx)
- node container has /usr/src dir with client file (see that was copied in Dockerfile.node)
- vnode has content of /usr/src from node and /var/www/tg/static from nginx.
Definitively, to pass data from /usr/src from your
nodecontainer to/var/www/tg/staticinnginxcontainer 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
Just change in docker-compose - vnode:/var/www/tg/static by - /var/lib/docker/volumes/vnode/_data:/var/www/tg/static
来源:https://stackoverflow.com/questions/50412368/docker-cant-share-data-between-containers-within-a-volume-docker-compose-3