I have this docker-compose.yml
version: 2.4
services:
foo:
image: ubuntu:focal
container_name: oof
volumes:
- ./foo:/foo
bar:
image: ubuntu:focal
container_name: rab
volumes_from:
- container:oof
With compose 1.29.2 and docker 20.10.8. But it does not start.
I get an error
ERROR: Service "bar" mounts volumes from "oof", which is not the name of a service or container.
How do I properly reference volumes by container name in compose?
The best way is to explicitly spell out the volumes you're reusing. If the foo image has VOLUME directives, you'll also mount the automatically-created anonymous volumes; you also have no control over where the volumes will be mounted, and if the two containers aren't similar enough, there could be conflicts. (This is essentially the logic behind Compose file version 3 removing volumes_from:.)
version: 2.4
services:
foo:
volumes:
- ./foo:/foo
bar:
volumes:
- ./foo:/foo # or a different container path if that suits your needs
In general in Compose, you shouldn't need to manually specify container_name:. Compose will generate unique container names, within the docker-compose.yml file if you need to refer to things you can use the service name, and there are docker-compose wrapper commands that know how to find the right container. If you do need to use the older volumes_from: syntax use the service name instead:
version: '2.4' # does not work in version 3
services:
foo:
image: ...
volumes:
- ./foo:/foo
# no container_name:
bar:
image: ...
volumes_from: foo
Related
I got docker compose:
version: '2'
services:
elasticsearch:
image: 'elasticsearch:7.9.1'
environment:
- discovery.type=single-node
ports:
- '9200:9200'
- '9300:9300'
volumes:
- /var/lib/docker/volumes/elastic_search_volume:/usr/share/elasticsearch/data:rw
When I run:
docker volume ls
I see no results. How to list unnamed volumes?
docker volume ls as you've shown it will list all of the volumes that exist.
However, in the docker-compose.yml file you show, you're not creating a named or anonymous volume. Instead, you're creating a bind mount to connect a host directory to the container filesystem space. These aren't considered "volumes" in a technical Docker sense, and a docker volume command won't show or manipulate those.
Reaching directly into /var/lib/docker usually isn't a best practice. It's better to ask Docker Compose to manage the named volume for you:
version: '2'
services:
elasticsearch:
volumes:
# No absolute host path, just the volume name
- elastic_search_volume:/usr/share/elasticsearch/data:rw
volumes:
elastic_search_volume:
# Without this line, Compose will create the volume for you.
# With this line, Compose expects it to already exist; you may
# need to manually `docker volume create elastic_search_volume`.
# external: true
for some reason, I need to create the container with the same image, But when I started the second one, It just restarted the fist one's container
the first yml file:
version: "3.1"
services:
php:
image:php:php73-fpm
restart: always
ports:
- "9000:9000"
- "9501:9501"
volumes:
- $PWD/../:/var/www/html/
networks:
- app_net
container_name: php
networks:
app_net:
driver: bridge
the second yml file:
version: "3.1"
services:
php:
image:php:php73-fpm
restart: always
ports:
- "19000:19000"
- "19501:19501"
volumes:
- $PWD/../:/var/www/html/
networks:
- app_net2
container_name: php73
networks:
app_net2:
driver: bridge
when I run docker-compose up -d to start the first one:
$ cd ~/Document/php/work/docker/
$ docker-compose up -d
Creating network "docker_app_net" with driver "bridge"
Creating php ... done
then I switch the directory to the second yml file
$ cd ../../private/docker/
$ docker-compose up -d
Recreating php ... done
Compose has a notion of a project name. By default the project name is the basename of the directory containing the docker-compose.yml file. In your example both directories are named docker (even if they're in different parent directories) so Compose looks for a project named docker and a container named php, and finds a match.
There are four ways to override this:
Rename one of the directories.
Set the COMPOSE_PROJECT_NAME environment variable.
Create a .env file in the current directory, and set COMPOSE_PROJECT_NAME there.
Use the docker-compose -p option (on every docker-compose command).
Within your docker-compose.yml file, the second part of ports: needs to match what the container is listening on; this is allowed to be different from the first part. So use the same 9500/9501 in both files.
Another consequence of the Compose project naming is that the standard names of containers, volumes, and networks that Compose creates will be prefixed with the project name. If the project name (current directory name) is docker2, and you reduce the Compose file to
version: "3.1"
services:
php:
build: .
restart: always
ports:
- "19000:9000"
- "19501:9501"
# no manual container_name: or networks:
The container will be named docker2_php_1, and it will be attached to a network named docker2_default; these will be different from the container/network created in the docker1 project/directory.
You can't have two containers with the same name. Since both names are just php, Docker thought they were settings that were supposed to be merged for the same container. Rename one of them.
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).
With v2 of docker-compose synthax, we were able to do something like this:
version: '2'
services:
app:
image: tianon/true
volumes:
- ../app:/var/www/app
nginx:
image: nginx
volumes_from:
- app
php:
image: php
volumes_from:
- app
In v3.2 volumes_from is now invalid option. The documentation is all for using new top-level volumes synthax, which is all the ways better.
I've read some comments on github, and the only solution that people propose is
version: '3.2'
services:
nginx:
image: nginx
volumes:
- app:/var/www/app
php:
image: php
volumes:
- app:/var/www/app
volumes:
app:
driver_opts:
type: none
device: ../app
o: bind
Which looks worse obviously, and it even doesn't work for me. It gives me an error: no such file or directory. So what else should I try? It seems like I can still use links instead of top-level volumes, but it's considered as legacy option in documentation. So how to do it right with new syntax?
EDIT:
Question has been identified as a possible duplicate, but I don't agree. See my comment bellow for explanation.
As the topic starter already mentions, volumes_from has been removed from the new docker-compose syntax, according to the documentation in favour of named volumes defined in the top level key volumes. The documentation also states the difference between volumes and bind mounts, one of which is who manages the contents:
By contrast, when you use a volume, a new directory is created within Docker’s storage directory on the host machine, and Docker manages that directory’s contents.
If this is the case, then it does not make sense to bind mount a host folder into a volume and let it be controlled by the host's file system and by Docker simultaneously.
If you still want to bind mount the same folder into two or more containers you could try something like:
version: '3.2'
services:
nginx:
image: nginx
volumes:
- type: bind
source: ../app
target: /var/www/app
php:
image: php
volumes:
- type: bind
source: ../app
target: /var/www/app
I'm trying to create a docker-compose.yml file that contains a --volumes-from instruction. Does anyone know the syntax?
I have been looking online for some time now, and it appears that the --volumes-from command is only available as a docker command. I hope I'm wrong.
Aug. 2022:
brandt points out in the comments to the updated docker-compose documentation.
Note August 2017: with docker-compose version 3, regarding volumes:
The top-level volumes key defines a named volume and references it from each service’s volumes list.
This replaces volumes_from in earlier versions of the Compose file format. See Use volumes and Volume Plugins for general information on volumes.
Example:
version: "3.2"
services:
web:
image: nginx:alpine
volumes:
- type: volume
source: mydata
target: /data
volume:
nocopy: true
- type: bind
source: ./static
target: /opt/app/static
db:
image: postgres:latest
volumes:
- "/var/run/postgres/postgres.sock:/var/run/postgres/postgres.sock"
- "dbdata:/var/lib/postgresql/data"
volumes:
mydata:
dbdata:
This example shows a named volume (mydata) being used by the web service, and a bind mount defined for a single service (first path under db service volumes).
The db service also uses a named volume called dbdata (second path under db service volumes), but defines it using the old string format for mounting a named volume.
Named volumes must be listed under the top-level volumes key, as shown.
February 2016:
The docs/compose-file.md mentions:
Mount all of the volumes from another service or container, optionally specifying read-only access(ro) or read-write(rw).
(If no access level is specified, then read-write will be used.)
volumes_from:
- service_name
- service_name:ro
- container:container_name
- container:container_name:rw
For instance (from this issue or this one)
version: "2"
services:
...
db:
image: mongo:3.0.8
volumes_from:
- dbdata
networks:
- back
links:
- dbdata
dbdata:
image: busybox
volumes:
- /data/db