Docker / Docker-compose volume fill & share issue - docker

I have a few questions about Docker volumes. I have installed Docker and docker-compose on a fresh host running debian stretch. I managed to get a docker-compose file running for a simple nginx/php-fpm project, both containers mounted on the directory containing the source code. I wanted to try to create a single volume that would be shared across my containers but I have a few issue, and my understanding of the official documentation is not helping.
So this is an idea of what I'm trying to achieve :
Question 1 : Trying to create a volume from a dockerfile on a directory mounted from host
docker-compose.yml :
version: '3'
services:
php:
build:
context: .
dockerfile: php.dockerfile
volumes:
- ./host-project-directory:/project
php.dockerfile :
FROM php:7-fpm
VOLUME project
from my understanding, when running docker-compose we should have a volume created on host containing all files from /project from container. And /project from container should contain all files from ./host-project-directory from host.
If I ls the content of /project on container I can see the files from host, but using docker volume list, there are no volumes created on host, why ?
Question 2 : How to populate and use this volume from another container ?
version: '3'
services:
php:
build:
context: .
dockerfile: php.dockerfile
volumes:
- named-volume:/project
web:
image: nginx
links:
- php
volumes:
- named-volume:/project
volumes:
named-volume:
This should create a volume called 'named-volume' and bind it to /project directories on both containers php and web.
Now, how to populate this volume with content from ./host-project-directory ?
I've tried adding a dockerfile like
ADD ./host-project-directory /project
But nothing changed and the volume remained empty.
I'm sorry if this is due to my lack of experience using Docker but I can't figure out how to make this simple thing work.
Thank you for your time !

For the first question, I try a simple docker file like this:
FROM php:7-fpm
COPY ./project /project
And a docker-compose like this:
version: '3'
services:
php:
build: .
volumes:
- named-volume:/project
web:
image: nginx
links:
- php
volumes:
- named-volume:/project
volumes:
named-volume:
Since you create the volume on docker-compose you don't need to create that in the Dockerfile.
Running docker volume list, I'm able to see the volume created with a local driver. Making ls inside the folder I'm also able to see the file. It's important to note, that the file present in you local directory it's not the same that the file inside the container. So if you edit the files in the host this will not change the files in container. That's because you have your volume created in another path, probably at: /var/lib/docker/volumes/...
This happens because you map the volume to the path, but you not specifies where you want the volume. To do that just make your docker-compose like this:
version: '3'
services:
php:
build: .
volumes:
- ./project:/project
web:
image: nginx
links:
- php
volumes:
- ./project:/project
Making this I'm still able to see the volume with the volume list command but without a name.
So I don't know why you are not able to see the volume in the list.
For question 2:
Doing the example above I have the files inside the container that exists in my local "project" folder.
Please check that the path to the local folder is correct.

A bind mount is not the same thing as a volume. You're defining a named volume here, but wanting the functionality of a bind mount.
Try this
version: '3'
services:
php:
build:
context: .
dockerfile: php.dockerfile
volumes:
- ./host-project-directory:/project
web:
image: nginx
links:
- php
volumes:
- ./host-project-directory:/project

Related

How do I share a docker-compose volume with a linux host?

I have a docker-compose.yml
version: '3.3'
services:
ssh:
environment:
- TZ=Etc/UTC
- DEBIAN_FRONTEND=noninterative
build:
context: './'
dockerfile: Dockerfile
ports:
- '172.17.0.2:22:22'
- '443:443'
- '8025:8025'
volumes:
- srv:/srv:rw
restart: always
volumes:
srv:
After I run docker-compose up --build I can ssh to the docker vm and there are files in /srv. 'docker volume ls' shows 2 volumes, srv and dockersetupsrv. They are both in /var/lib/docker/volumes. They both contain _data directories and show creation time stamps that match the docker image creation times but are otherwise empty. Neither one contains any of the files that are in the docker container's /srv directory. How can I share the docker /srv directory with the host?
you should point out more specific for the mapping directory,
for example:
/srv:/usr/srv:rw
after that, when you add content inside your host machine /srv,it is automatically map into /usr/srv
--> make sure that directory exist
you can have a check in this link : https://docs.docker.com/storage/volumes/

Why docker container can't see volume on different container?

I have 2 containers that I fire up using docker-compose up.
The first I just pull from the docker hub nginx:stable
The second one I build on top of the php from the hub
dockerfile
FROM composer:1.9.3
RUN mkdir /fatfree
RUN ["composer","require","bcosca/fatfree-core","--working-dir","/fatfree"]
FROM php:7.4-fpm
COPY --from=0 /fatfree /fatfree
I also tried VOLUME /fatfree in the above file to no avail.
docker-compose.yml
version: "3.7"
services:
webserver:
image: nginx:stable
ports:
- "80:8080"
volumes:
- ./www:/www
- fatfree:/fatfree
links:
- php
php:
build:
context: .
dockerfile: dockerfile
volumes:
- ./www:/www
- "fatfree:/fatfree"
volumes:
fatfree:
If I interpreted correctly the docker documentation, my www/index.php should be able to see whatever is in /fatfree, but it doesn't. The folder itself shows up, but it appears empty.
If I run the dockerfile interactively docker container run -i -t test bash , the /fatfree folder exists and it has all the files I expect it to have.
There are plenty of stackoverflow questions asking how to achieve this, and they all seem to suggest that what I'm doing is actually ok, but it doesn't work, and I have no clue why.
Any suggestion is appreciated.
Your mapping is incorrect.
You want:
volumes:
- /fatfree:/www
The first entry /fatfree refers to the path on your host machine.
The second entry /www refers to the path in the container.
In my example, your host's /fatfree directory (and content) will be mapped to the container's /www directory.
Change as desired.

Share volumes between separate docker compose files

I am trying to allow nginx to proxy between multiple containers while also accessing the static files from those containers.
To share volumes between containers created using docker compose, the following works correctly:
version: '3.6'
services:
web:
build:
context: .
dockerfile: ./Dockerfile
image: webtest
command: ./start.sh
volumes:
- .:/code
- static-files:/static/teststaticfiles
nginx:
image: nginx:1.15.8-alpine
ports:
- "80:80"
volumes:
- ./nginx-config:/etc/nginx/conf.d
- static-files:/static/teststaticfiles
depends_on:
- web
volumes:
static-files:
However what I actually require is for the nginx compose file to be in a separate file and also in a completely different folder. In other words, the docker compose up commands would be run separately. I have tried the following:
First compose file:
version: '3.6'
services:
web:
build:
context: .
dockerfile: ./Dockerfile
image: webtest
command: ./start.sh
volumes:
- .:/code
- static-files:/static/teststaticfiles
networks:
- directorylocation-nginx_mynetwork
volumes:
static-files:
networks:
directorylocation-nginx_mynetwork:
external: true
Second compose file (ie: nginx):
version: '3.6'
services:
nginx:
image: nginx:1.15.8-alpine
ports:
- "80:80"
volumes:
- ./nginx-config:/etc/nginx/conf.d
- static-files:/static/teststaticfiles
networks:
- mynetwork
volumes:
static-files:
networks:
mynetwork:
The above two files work correctly in the sense that the site can be viewed. The problem is that the static files are not available in the nginx container. The site therefore displays without any images etc.
One work around which works correctly found here is to change the nginx container static files volume to instead be as follows:
- /var/lib/docker/volumes/directory_static-files/_data:/static/teststaticfiles
The above works correctly, but it seems 'hacky' and brittle. Is there another way to share volumes between containers which are housed in different compose files without needing to map the /var/lib/docker/volumes directory.
By separating the 2 docker-compose.yml files as you did in your question, 2 different volumes are actually created; that's the reason you don't see data from web service inside volume of nginx service, because there are just 2 different volumes.
Example : let's say you have the following structure :
example/
|- web/
|- docker-compose.yml # your first docker compose file
|- nginx/
|- docker-compose.yml # your second docker compose file
Running docker-compose up from web folder (or docker-compose -f web/docker-compose.yml up from example directory) will actually create a volume named web_static-files (name of the volume defined in docker-compose.yml file, prefixed by the folder where this file is located).
So, running docker-compose up from nginx folder will actually create nginx_static-files instead of re-using web_static-files as you want.
You can use the volume created by web/docker-compose.yml by specifying in the 2nd docker compose file (nginx/docker-compose.yml) that this is an external volume, and its name :
volumes:
static-files:
external:
name: web_static-files
Note that if you don't want the volume (and all resources) to be prefixed by the folder name (default), but by something else, you can add -p option to docker-compose command :
docker-compose \
-f web/docker-compose.yml \
-p abcd \
up
This command will now create a volume named abcd_static-files (that you can use in the 2nd docker compose file).
You can also define the volumes creation on its own docker-compose file (like volumes/docker-compose.yml) :
version: '3.6'
volumes:
static-files:
And reference this volume as external, with name volumes_static-files, in web and nginx docker-compose.yml files :
volumes:
volumes_static-files:
external: true
Unfortunately, you cannot set the volume name in docker compose, it will be automatically prefixed. If this is really a problem, you can also create the volume manually (docker volume create static-files) before running any docker-compose up command (I do not recommand this solution though because it adds a manual step that can be forgotten if you reproduce your deployment on another environment).

Share data between 2 containers

I do a Symfony project with Docker. In development, I mount my source folder in Nginx and PHP-FPM containers. But for the production, I want to put the code in the PHP-FPM container to do an app container, and share the code with the Nginx container.
In my Dockerfile, I use a VOLUME /var/www/html, but how can I permit the nginx container to access this volume (in docker-compose file) ?
Before the v3, I know there was a volumes_from, but not anymore.
I want place the code inside the container like say here (https://docs.docker.com/compose/production/)
Removing any volume bindings for application code, so that code stays inside the container and can’t be changed from outside
Thanks a lot for your help
Finally, it appear we can use a named volume to do it, remove the VOLUME from the Dockerfile, then just define a name volume, and it takes the value of the first container.
version: '3'
services:
nginx:
build: ./docker/nginx
volumes:
- app_data:/var/www/html:ro
depends_on:
- app
app:
build: ./
volumes:
- app_data:/var/www/html:rw
networks:
- default
volumes:
app_data:
driver: local

Docker ADD folder during build and then expose to VOLUME

I am using docker-compose for a basic web app. When the image is built, it copies the static JS files in (ADD) and then builds them.
I then want to expose that directory to other containers, using VOLUME.
E.g.
Dockerfile
ADD ./site/static /site/static
WORKDIR /site/static
RUN gulp
docker-compose.yml
app:
build: .
volumes:
- /site/static
http:
image: nginx
volumes_from:
- app
nginx.conf
location /static {
alias /site/static
}
(Note, this is just an example)
The problem is that it seems to work the first time (i.e. when the volume does not exist), but is then never overwritten by the modified image. If I was using purely a Dockerfile, I could achieve this by putting VOLUME after ADD.
Is there a way to allow this, or am I approaching it completely wrong?
Thanks
Possible solution 1
I might be wrong, but I think the trouble is that when (and if) you do
docker-compose down && docker-compose up
your containers are recreated, and new "anonymous" volume is created.
You can check my guess running:
docker volume ls
I would try to use named volume, like so:
version: "2"
volumes:
app-volume: ~
services:
app:
build: .
volumes:
- app-volume:/site/static
http:
image: nginx
volumes:
- app-volume:/site/static
You need docker-compose 1.6.0+ and require a Docker Engine of version 1.10.0+ for usinng version 2 of docker-compose file.
Possible solution 2
just
app:
build: .
volumes:
- ./site/static:/site/static # maps host directory `./site/static` (relative to docker-compose.yml) to /site/static inside container
http:
image: nginx
volumes_from:
- app
And remove
ADD ./site/static /site/static
from your Dockerfile

Resources