How to share volumes among containers by docker-compose - docker

My docker-compose defines two containers. I want one container shares a volume to the other container.
version: '3'
services:
web-server:
env_file: .env
container_name: web-server
image: web-server
build:
dockerfile: docker/Dockerfile
ports:
- 3000:3000
- 3500:3500
volumes:
- static-content: /workspace/static
command: sh /workspace/start.sh
backend-server:
volumes:
- static-content: /workspace/static
volumes:
static-content:
The above docker composer file declares two services, web-server and backend-server. And I declares the named volume static-content under services. I got below error when I run docker-composer -f docker-composer.yml up:
services.web-server.volumes contains an invalid type, it should be a string
services.backend-server.volumes contains an invalid type, it should be a string
so how can I share volumes throw docker-composer?

You have an extra space in your volume string that causes Yaml to change the parsing from an array of strings to an array of name/value maps. Remove that space in your volume entries (see below) to prevent this error:
version: '3'
services:
web-server:
env_file: .env
container_name: web-server
image: web-server
build:
dockerfile: docker/Dockerfile
ports:
- 3000:3000
- 3500:3500
volumes:
- static-content:/workspace/static
command: sh /workspace/start.sh
backend-server:
volumes:
- static-content:/workspace/static
volumes:
static-content:
For more details, see the compose file section on volumes short syntax.

You need to use the docker volumes syntax, without spaces
<local_path>:<service_path>:<optional_rw_attributes>
For example:
./:/your_path/
will map the present working directory to /your_path
And this example:
./:/your_path/:ro
will map the present working directory to /your_path with read only permissions
Read these docs for more info:
https://docs.docker.com/compose/compose-file/#volume-configuration-reference

Related

Docker compose Unsupported config option for service volume mongodb

I am trying to learn docker by reading the official documentation. I am on the task of Use Compose to develop locally. Trying to compose mongodb but I got an error
The Compose file './docker-compose.dev.yml' is invalid because:
Unsupported config option for services.volumes: 'mongodb'
here is docker-compose.dev.yml file:
version: '3.8'
services:
notes:
build:
context: .
ports:
- 8080:8080
- 9229:9229
environment:
- SERVER_PORT=8080
- DATABASE_CONNECTIONSTRING=mongodb://mongo:27017/notes
volumes:
- ./:/code
command: npm run debug
mongo:
image: mongo:4.2.8
ports:
- 27017:27017
volumes:
- mongodb:/data/db
- mongodb_config:/data/configdb
volumes:
mongodb:
mongodb_config:
How can I make it work?
That's a small mistake on your part, the volumes section of the docker-compose.yaml file is related to all services and not one in particular, because of how yaml files are formatted the indentation level matters a lot, in your example you didn't use the volumes parameter, instead you defined a service called volumes and services don't have a parameter called mongodb.
You have to simply decrease the identation level on the last 3 lines and it will work just fine.
version: '3.8'
services:
mongo:
image: mongo:4.2.8
ports:
- 27017:27017
volumes:
- mongodb:/data/db
- mongodb_config:/data/configdb
volumes:
mongodb:
mongodb_config:

Why aren't my docker images, built by "docker-compose build", using the correct version of my code?

Docker doesn't use the latest code after running git checkout <non_master_branch>, while I can see it in the vscode.
I am using the following docker-compose file:
version: '2'
volumes:
pgdata:
backend_app:
services:
nginx:
container_name: nginx-angular-dev
image: nginx-angular-dev
build:
context: ./frontend
dockerfile: /.docker/nginx.dockerfile
ports:
- "80:80"
- "443:443"
depends_on:
- web
web:
container_name: django-app-dev
image: django-app-dev
build:
context: ./backend
dockerfile: /django.dockerfile
command: ["./wait-for-postgres.sh", "db", "./django-entrypoint.sh"]
volumes:
- backend_app:/code
ports:
- "8000:8000"
depends_on:
- db
env_file: .env
environment:
FRONTEND_BASE_URL: http://192.168.99.100/
BACKEND_BASE_URL: http://192.168.99.100/api/
MODE_ENV: DOCKER_DEV
db:
container_name: django-db
image: postgres:10
env_file: .env
volumes:
- pgdata:/var/lib/postgresql/data
I have tried docker-compose build --no-cache, followed by docker-compose up --force-recreate but it didn't solve the problem.
What is the root of my problem?
Your volumes: are causing problems. Docker volumes aren't intended to hold code, and you should delete the volume declarations that mention backend_app:.
Your docker-compose.yml file says in part:
volumes:
backend_app:
services:
web:
volumes:
- backend_app:/code
backend_app is a named volume: it keeps data that must be persisted across container runs. If the volume doesn't exist yet the first time then data will be copied into it from the image, but after that, Docker considers it to contain critical user data that must not be updated.
If you keep code or libraries in a Docker volume, Docker will never update it, even if the underlying image changes. This is a common problem in JavaScript applications that mount an anonymous volume on their node_modules directory.
As a temporary workaround, if you docker-compose down -v, it will delete all of the volumes, including the one with your code in it, and the next time you start it will get recreated from the image.
The best solution is to simply not use a volume here at all. Delete the lines above from your docker-compose.yml file. Develop and test your application in a non-Docker environment, and when you're ready to do integration testing, run docker-compose up --build. Your code will live in the image, and an ordinary docker build will produce a new image with new code.

docker-compose volumes_from equivalent with version 3

I'm trying to create an Nginx/PHP FPM setup with docker compose and am having issues with the version 3 volumes syntax/changes.
My Dockerfile:
FROM php:7-fpm
VOLUME /var/www/html
My docker-compose.yml:
version: "3"
services:
php:
build: .
volumes:
- ./html:/var/www/html
web:
image: nginx
links:
- php
ports:
- "8888:80"
volumes:
- php:/var/www/html
- ./default.conf:/etc/nginx/conf.d/default.conf
volumes:
php:
When I add an index.php file into ./html, I can view that by going to http://localhost:8888, but any static files (like CSS) return a 404 because Nginx cannot find those in its container (/var/www/html is empty on the nginx container). With version 3 docker compose files do not have volumes_from anymore, which is basically what I'm trying to replicate.
How can I get this to work with version 3?
For using "Named volumes" for sharing files between containers you need to define
1) volumes: section on the top level of yml file and define volume name
volumes:
php:
2) define volume section on first container like you did (Where share will mount)
web:
volumes:
- php:/var/www/html #<container_name>:<mount_point>
3) define volume section on second container (Share will mount from)
php:
volumes:
- php:/var/www/html
4) (optionally) If you need to store volume data on the host machine you can use local-persist docker plugin. You can specify docker volume driver and path where you data will be stored.
volumes:
php:
driver: local-persist
driver_opts:
mountpoint: /path/on/host/machine/
In your case you forgot define volume name for php container. Just replace
php:
build: .
volumes:
- ./html:/var/www/html
to
php:
build: .
volumes:
- php:/var/www/html
and use Local Persist Docker Plugin

Docker Compose - How to store database data?

I am new to docker and developing a project using docker compose. From the documentation I have learned that I should be using data only containers to keep data persistant but I am unable to do so using docker-compose.
Whenever I do docker-compose down it removes the the data from db but by doing docker-compose stop the data is not removed. May be this is because that I am not creating named data volume and docker-compose down hardly removes all the containers. So I tried naming the container but it threw me errors.
Please have a look at my yml file:
version: '2'
services:
data_container:
build: ./data
#volumes:
# - dataVolume:/data
db:
build: ./db
ports:
- "5445:5432"
environment:
- POSTGRES_USER=postgres
- POSTGRES_DB=postgres
# - PGDATA=/var/lib/postgresql/data/pgdata
volumes_from:
# - container:db_bus
- data_container
geoserver:
build: ./geoserver
depends_on:
- db
ports:
- "8004:8080"
volumes:
- ./geoserver/data:/opt/geoserverdata_dir
web:
build: ./web
volumes:
- ./web:/code
ports:
- "8000:8000"
depends_on:
- db
command: python manage.py runserver 0.0.0.0:8000
nginx:
build: ./nginx
ports:
- "83:80"
depends_on:
- web
The Docker file for the data_container is:
FROM stackbrew/busybox:latest
MAINTAINER Tom Offermann <tom#offermann.us>
# Create data directory
RUN mkdir /data
# Create /data volume
VOLUME /data
I tried this but by doing docker-compose down, the data is lost. I tried naming the data_container as you can see the commented line, it threw me this error:
ERROR: Named volume "dataVolume:/data:rw" is used in service "data_container" but no declaration was found in the volumes section.
So right now what I am doing is I created a stand alone data only named container and put that in the volumes_from value of the db. It worked fine and didn't remove any data even after doing docker-compose down.
My queries:
What is the best approach to make containers that can store database's data using the docker-compose and to use them properly ?
My conscious is not agreeing with me on approach that I have opted, the one by creating a stand alone data container. Any thoughts?
docker-compose down
does the following
Stops containers and removes containers, networks, volumes, and images
created by up
So the behaviour you are experiencing is expected.
Use docker-compose stop to shutdown containers created with the docker-compose file but not remove their volumes.
Secondly you don't need the data-container pattern in version 2 of docker compose. So remove that and just use
db:
...
volumes:
- /var/lib/postgresql/data
docker-compose down stops containers but also removes them (with everything: networks, ...).
Use docker-compose stop instead.
I think the best approach to make containers that can store database's data with docker-compose is to use named volumes:
version: '2'
services:
db: #https://hub.docker.com/_/mysql/
image: mysql
volumes:
- "wp-db:/var/lib/mysql:rw"
env_file:
- "./conf/db/mysql.env"
volumes:
wp-db: {}
Here, it will create a named volume called "wp-db" (if it doesn't exist) and mount it in /var/lib/mysql (in read-write mode, the default). This is where the database stores its data (for the mysql image).
If the named volume already exists, it will be used without creating it.
When starting, the mysql image look if there are databases in /var/lib/mysql (your volume) in order to use them.
You can have more information with the docker-compose file reference here:
https://docs.docker.com/compose/compose-file/#/volumes-volume-driver
To store database data make sure your docker-compose.yml will look like
if you want to use Dockerfile
version: '3.1'
services:
php:
build:
context: .
dockerfile: Dockerfile
ports:
- 80:80
volumes:
- ./src:/var/www/html/
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
- mysql-data:/var/lib/mysql
adminer:
image: adminer
restart: always
ports:
- 8080:8080
volumes:
mysql-data:
your docker-compose.yml will looks like
if you want to use your image instead of Dockerfile
version: '3.1'
services:
php:
image: php:7.4-apache
ports:
- 80:80
volumes:
- ./src:/var/www/html/
db:
image: mysql
command: --default-authentication-plugin=mysql_native_password
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
- mysql-data:/var/lib/mysql
adminer:
image: adminer
restart: always
ports:
- 8080:8080
volumes:
if you want to store or preserve data of mysql then
must remember to add two lines in your docker-compose.yml
volumes:
- mysql-data:/var/lib/mysql
and
volumes:
mysql-data:
after that use this command
docker-compose up -d
now your data will persistent and will not be deleted even after using this command
docker-compose down
extra:- but if you want to delete all data then you will use
docker-compose down -v
to verify or check database data list by using this command
docker volume ls
DRIVER VOLUME NAME
local 35c819179d883cf8a4355ae2ce391844fcaa534cb71dc9a3fd5c6a4ed862b0d4
local 133db2cc48919575fc35457d104cb126b1e7eb3792b8e69249c1cfd20826aac4
local 483d7b8fe09d9e96b483295c6e7e4a9d58443b2321e0862818159ba8cf0e1d39
local 725aa19ad0e864688788576c5f46e1f62dfc8cdf154f243d68fa186da04bc5ec
local de265ce8fc271fc0ae49850650f9d3bf0492b6f58162698c26fce35694e6231c
local phphelloworld_mysql-data

Docker compose with two files

I have two docker-compose.yml files in separate folders.
I'd like to run the two of them in the same command, in order for the services from both to be able to talk to each other.
However, when I go to the lowest common path ancestor and try to run docker-compose with both files, here is what happens:
$ docker-compose -f ./api-folder/docker-compose.yml -f ./front-folder/docker-compose.yml up -d
ERROR: build path /projects/front-folder/api either does not exist, is not accessible, or is not a valid URL.
$ docker-compose -f ./front-folder/docker-compose.yml -f ./api-folder/docker-compose.yml up -d
ERROR: build path /projects/api-folder/app either does not exist, is not accessible, or is not a valid URL.
Here are the two docker-compose.yml files:
/projects/front-folder/docker-compose.yml
version: '2'
services:
app:
restart: always
build: ./app
environment:
NODE_ENV: 'dev'
ports:
- "4400:4400"
volumes:
- ./app:/usr/src/app
nginx:
restart: always
build: ./nginx
volumes:
- ./logs:/usr/local/var/log/nginx
links:
- app
ports:
- "80:80"
/projects/api-folder/docker-compose.yml
version: '2'
services:
api:
restart: always
build: ./api
expose:
- "4600"
volumes:
- ./api:/usr/src/app
- ./logs:/logs
nginx:
restart: always
build: ./nginx
volumes:
- ./logs:/usr/local/var/log/nginx
links:
- api
ports:
- "81:80"
networks:
- hackerz
And the directory structure:
- /projects
- /front-folder
- /app
Dockerfile
- /nginx
Dockerfile
docker-compose.yml
- /api-folder
- /api
Dockerfile
- /nginx
Dockerfile
docker-compose.yml
I'm guessing the problem is with the build paths, but what I don't understand is:
Why Docker insists on searching build: ./api in /front-folder or the other way around?
How to circumvent this problem and be able to run both files together?
DOCKERFILE
Alternate Dockerfile.
Compose uses an alternate file to build with. A build path must also be specified.
service3:
build:
context: .
dockerfile: Dockerfile-alternate
docker compose build giving custom file
This isn't how compose works (by design). See my comment here: https://github.com/docker/compose/issues/3530#issuecomment-222490501.

Resources