Docker Compose Volumes Basics - docker

I understand if it was:
volumes:
- /home/{user}/config:/config
You would find it in the local user directory -> /home/{user}/config
But when declaring;
volumes:
- ./:/config
Where is "./"?

. in Unix generally means "the current directory", and in the case of Compose it's the directory containing the (first) docker-compose.yml file.

Related

persist %USERPROFILE% folder using docker compose volume

I am searching on how to persist user profile folder in volume mounting
I have folder C:\Users\ABEL\source\repos which needs to be persisted for a windows container. The username should be from the host. It is unknown.
Below is my docker-compose file, The volume section is not correct.
Any comments will be helpful. Thanks in advance
version: '3.4'
services:
directoryservice:
image: abc-directoryservice:latest
build: .
ports:
- "44309:44309"
environment:
- ASPNETCORE_ENVIRONMENT=Development
- ASPNETCORE_URLS=https://+:44309;
- ASPNETCORE_Kestrel__Certificates__Default__Password=welcome123#
- ASPNETCORE_Kestrel__Certificates__Default__Path=/https/aspnetapp.pfx
volumes:
- ./devops/https/abccert.pfx:/https/aspnetapp.pfx:ro
# - "$env:USERPROFILE/source:$env:USERPROFILE/source"
- ${Env:USERPROFILE}\source:${Env:USERPROFILE}\source
I get below error
invalid interpolation format for services.directoryservice.volumes.[]: "${Env:USERPROFILE}\\source:${Env:USERPROFILE}\\source". You may need to escape any $ with another $.
The $env:USERPROFILE/ ${env:USERPROFILE} syntax is specific to PowerShell.
Judging by the docs, docker-compose uses its own syntax: $USERPROFILE / ${USERPROFILE}
You report a follow-up problem, namely that the Windows-style path stored in $USERPROFILE (%USERPROFILE%) (e.g. C:\Users\jdoe\source) isn't converted to a Unix-style path (e.g. c/Users/jdoe/source)
This answer suggests that you must set environment variable COMPOSE_CONVERT_WINDOWS_PATHS to 1, before running your docker-compose command.
E.g., in a PowerShell session:
$env:COMPOSE_CONVERT_WINDOWS_PATHS=1
Consider adding this statement to your $PROFILE file so that it takes effect in future PowerShell sessions too.

define volumes in docker-compose.yaml

I am writing a docker-compose.yaml file for my project. I have checked the volumes documentation here .
I also understand the concept of volume in docker that I can mount a volume e.g. -v my-data/:/var/lib/db where my-data/ is a directory on my host machine while /var/lib/db is the path inside database container.
My confuse is with the link I put above. There it has the following sample:
version: "3.9"
services:
db:
image: db
volumes:
- data-volume:/var/lib/db
backup:
image: backup-service
volumes:
- data-volume:/var/lib/backup/data
volumes:
data-volume:
I wonder does it mean that I have to create a directory named data-volume on my host machine? What if I have a directory on my machine with path temp/my-data/ and I want to mount that path to the database container /var/lib/db ? Should I do something like below?
version: "3.9"
services:
db:
image: db
volumes:
- temp/my-data/:/var/lib/db
volumes:
temp/my-data/:
My main confusion is the volumes: section at the bottom, I am not sure whether the volume name should be the path of my directory or should be just literally a name I give & if it is the latter case then how could the given name be mapped with temp/my-data/ on my machine? The sample doesn't indicate that & is ambiguous to clarify that.
Could someone please clarify it for me?
P.S. I tried with above docker-compose I guessed, ended up with the error:
ERROR: The Compose file './docker-compose.yaml' is invalid because:
volumes value 'temp/my-data/' does not match any of the regexes: '^[a-zA-Z0-9._-]+$'
Mapped volumes can either be files/directories on the host machine (sometimes called bind mounts in the documentation) or they can be docker volumes that can be managed using docker volume commands.
The volumes: section in a docker-compose file specify docker volumes, i.e. not files/directories. The first docker-compose in your post uses such a volume.
If you want to map a file or directory (like in your last docker-compose file), you don't need to specify anything in the volumes: section.
Docker volumes (the ones specified in the volumes: section or created using docker volume create) are of course also stored somewhere on your host computer, but docker manages that and you shouldn't normally need to know where or what the format is.
This part of the documentation is pretty good about explaining it, I think https://docs.docker.com/storage/volumes/
As #HansKilian mentions, you don't need both volumes and services.volumes. To use services.volumes, map the host directory to the container directory like this:
services:
db:
image: db
volumes:
- /host/path/lib/db:/container/path/lib/db
With that, the directory /host/path/lib/db on the host machine will be used by the container and available at /container/path/lib/db.
Now, if you're like me, I get really confused with fake examples, so let's say the real directory on your host machine is /var/lib/db and you just want to see it at /db when you run a shell in Docker (i.e., docker exec -it /bin/bash container-id).
docker-compose.yaml would look like this:
services:
db:
image: db
volumes:
- /var/lib/db:/db
Now when you run the shell, cd /logs and ls, you'll see the same results as if you'd cd /var/lib/db on the host.
If you want to use the volumes section to indicate a global volume to use, you first have to create that volume using docker volume create. The documentation Hans linked includes steps to do this. The syntax of /host/path:/container/path is replaced by volume-name:/container/path. Then, once defined, you'd alter your docker-compose.yaml to be more like this:
services:
db:
image: db
volumes:
- your-global-volume-name:/db
volumes:
your-global-volume-name:
external: true
Note that I have not tested or used the this configuration. I'm assuming it's correct based on the other method working and the few changes I can identify in the docs.

docker-compose volumes not mounting directories, only files inside directory

Might sound weird, but I am trying to get docker-compose to mount directories to a volume I created
volumes:
- backend-data:/app/migrations/autogen-migrations
- backend-data:/app/seeds/autogen-seeds
- backend-data:/app/server/public
- backend-data:/app/server/src/services/location
Only problem is, that instead of simply mapping the folders to the volume, it's mounting the content inside the volume. Is there any way to tell docker-compose to copy/map the folder itself?
Edit:
Already tried doing
backend-data/autogen-migrations:/app/migrations/autogen-migrations
And I get the following error:
Named volume "backend-data/autogen-migrations:/app/migrations/autogen-migrations:rw" is used in service "backend" but no declaration was found in the volumes section.
Btw this is how my volumes are declared
volumes:
backend-data:
driver: local
When you need mount a local directory as Docker volume, you have use this syntax in your service:
volumes:
- ./your/local/path:/app/migrations/autogen-migrations
In this way, Docker create a local path "./your/local/path" in the same folder where docker-compose.yml file is, to store the data of mounted volume. In this case you don't need specify the volume section in the docker-compose.yml because you manage the volumes by yourself.
If you need mount more than one folder, remember also to mount more than one local folder:
volumes:
- ./your/local/migrations/or/whatever/you/want:/app/migrations/autogen-migrations
- ./your/local/seeds:/app/seeds/autogen-seeds
- ./your/local/server/public:/app/server/public
- ./your/local/server/src:/app/server/src/services/location
You can also aggregate mounts folder under the same folder:
volumes:
- ./your/local/migrations:/app/migrations/autogen-migrations
- ./your/local/seeds:/app/seeds/autogen-seeds
- ./your/local/server:/app/server
In this case into './your/local/server' you found all '/app/server/' content.
If you use the syntax:
volumes:
backend-data:
driver: local
you tell Docker: "Docker, please, mount the folder which correspond to backend-data: (in your case backend-data:/app/migrations/autogen-migrations) when you want and store my data!". In this case, Docker manage the "local" folder by itself without use the the same folder where docker-compose.yml file is.

File in docker-entrypoint-initdb.d never get executed when using docker compose

I'm using Docker Toolbox on Windows 10
I can access the php part succesfully via http://192.168.99.100:8000, I have been working around with the mariadb part but still having several problems
I have an sql file as /mariadb/initdb/abc.sql so I should be copied into /docker-entrypoint-initdb.d, after the container is created I use docker-compose exec mariadb to access the container, there is the file as /docker-entrypoint-initdb.d/abc.sql but the file never get executed, I also have tested to import the sql file to the container manually, it was succesful so the sql file is valid
I don't quite understand about the data folder mapping, and what to do to get the folder sync with the container, I always get the warning when recreate the container using docker-compose up -d
WARNING: Service "mariadb" is using volume "/var/lib/mysql" from the previous container. Host mapping "/.../mariadb/data" has no effect. Remove the existing containers (with docker-compose rm mariadb) to use the Recreating db ... done
Questions
How to get the sql file in /docker-entrypoint-initdb.d to be executed ?
What is the right way to map the data folder with the mariadb container ?
Please guide
Thanks
This is my docker-compose.yml
version: "3.2"
services:
php:
image: php:7.1-apache
container_name: web
restart: always
volumes:
- /.../php:/var/www/html
ports:
- "8000:80"
mariadb:
image: mariadb:latest
container_name: db
restart: always
environment:
- MYSQL_ROOT_PASSWORD=12345
volumes:
- /.../mariadb/initdb:/docker-entrypoint-initdb.d
- /.../mariadb/data:/var/lib/mysql
ports:
- "3306:3306"
For me the issue was the fact that Docker didn't clean up my mounted volumes from previous runs.
Doing a:
docker volume ls
Will list any volumes, and if previous exist, then run 'rm' command on the volume to remove it.
As stated on docker mysql docks, scripts in the '/docker-entrypoint-initdb.d' folder is only evalutated the first time the container runs, and if a previous volume remains, it won't run the scripts.
As for the mapping, you simply need to mount your script folder to the '/docker-entrypoint-initdb.d' folder in the image:
volumes:
- ./db/:/docker-entrypoint-initdb.d
I have a single script file in a folder named db, relative to my docker-compose file.
In your Docker file for creating mariaDB, at the end add the abc.sql file to your docker entry point like so:
COPY abc.sql /docker-entrypoint-initdb.d/
Remove the - /.../mariadb/initdb:/docker-entrypoint-initdb.d mapping as any file copied into the entry point will be executed.
Note: Windows containers do not execute anything in docker-entrypoint-initdb.d/

docker-compose v3 prepend folder name to network name

When I run docker-compose up -d, docker always creates container name and network name prepended with the folder name that contains docker-compose.ymlfile.
I can specify the container name as follows:
nginx:
container_name: nginx
build:
context: .
dockerfile: .docker/docker-nginx.dockerfile
But how can I specify the network name so that it doesn't prepend folder name to it?
Thanks.
Docker Prepends the current folder name with all the components name created using docker compose file.
Eg : If the current folder name containing the docker-compose.yml file is test, all the volumes,network and container names will get test appended to it. In order to solve the problem people earlier proposed the idea of using -p flag with docker-compose command but the solution is not the most feasible one as a project name is required just after the -p attribute. The project name then gets appended to all the components created using docker compose file.
The Solution to the above problem is using the name property as in below.
volumes:
data:
driver: local
name: mongodata
networks:
internal-network:
driver: bridge
name: frontend-network
This volume can be referred in the service section as
services:
mongo-database:
volumes:
- data:/data/db
networks:
- internal-network
The above name attribute will prevent docker-compose to prepend folder name.
Note : For the container name one could use the property container_name
services:
mongo-database:
container_name: mongo
You have to place a ".env" file in the root of your docker-compose project directory.
COMPOSE_PROJECT_NAME=MyFancyProject
See Docker docs for further information: https://docs.docker.com/compose/reference/envvars/
If you don't use docker-compose, you can use the "-p" parameter to set this on docker run.

Resources