What is the impact on not using volumes in my docker-compose? - docker

I am new to docker, what a wonderful tool!. Following the Django tutorial, their docs provide a basic docker-compose.yml, that looks similar to the following one that I've created.
version: '3'
services:
web:
build: .
container_name: web
command: python manage.py migrate
command: python manage.py runserver 0.0.0.0:8000
volumes:
- ./src:/src
ports:
- "8000:8000"
depends_on:
- postgres
postgres:
image: postgres:latest
container_name: postgres
environment:
POSTGRES_USER: my_user
POSTGRES_PASSWORD: my_secret_pass!
POSTGRES_DB: my_db
ports:
- "5432:5432"
However, in every single docker-compose file that I see around, the following is added:
volumes:
- ./postgres-data:/var/lib/postgresql/data
What are those volumes used for? Does it mean that if I now restart my postgres container all my data is deleted, but if I had the volumes it is not?
Is my docker-compose.yml ready for production?

What are those volumes used for?
Volumes persist data from your container to your Docker host.
This:
volumes:
- ./postgres-data:/var/lib/postgresql/data
means that /var/lib/postgresql/data in your container will be persisted in ./postgres-data in your Docker host.
What #Dan Lowe commented is correct, if you do docker-compose down without volumes, all the data insisde your containers will be lost, but if you have volumes the directories, and files you specified will be kept in your Docker host
You can see this data in your Docker host in /var/lib/docker/volumes/<your_volume_name>/_data even after your container don't exist anymore.

Related

persistent data using map volume to kong container

I am trying to learn kong, using docker-compose, i am able to run kong+konga and create services. But whenever i do docker-compose down and then up again i lose all my data:
kong:
container_name: kong
image: kong:2.1.4-alpine
restart: unless-stopped
networks:
kong-net:
ipv4_address: 172.1.1.40
volumes:
- kong_data:/usr/local/kong/declarative
environment:
KONG_DATABASE: postgres
KONG_PG_HOST: kong-database
KONG_PG_USER: kong
KONG_PG_PASSWORD: password
KONG_ADMIN_LISTEN: "0.0.0.0:8001, 0.0.0.0:8444 ssl"
KONG_DB_UPDATE_FREQUENCY: 1m
KONG_PROXY_ACCESS_LOG: /dev/stdout
KONG_ADMIN_ACCESS_LOG: /dev/stdout
KONG_PROXY_ERROR_LOG: /dev/stderr
KONG_ADMIN_ERROR_LOG: /dev/stderr
depends_on:
- kong-migration
ports:
- "8001:8001"
- "8444:8444"
- "8000:8000"
- "8443:8443"
Looks like volume mapping not working. pleasE help
If you want to keep data when your kong docker-compose is down it is better to use kong in database mode.
So then you will create a persistent volume for your database and it will keep your changes.
By the kong manual you will find there are two type of database supported: postgresql and cassandra
Postgresql is my choice for small project as I'm not planning for huge horizontal scale with cassandra database.
As you will find in the manual starting your project with docker and database is very simple.
But remember to add a volume to your database service as in the sample mentioned in manual there is no volume.
For postgresql you can add: -v /custom/mount:/var/lib/postgresql/data in docker run command
or
volumes:
postgress-data:
driver: local
services:
postgress:
restart: unless-stopped
image: postgres:latest
environment:
- POSTGRES_USER=your_db_user
- POSTGRES_DB=kong
- POSTGRES_PASSWORD=your_db_password
volumes:
- postgres-data:/var/lib/postgresql/data
Answer : You should use docker volume for having persistent data
As reference says :
Volumes are the preferred mechanism for persisting data generated by and used by Docker containers
First step is to create a volume that you want your host and docker container communicate using :
docker volume create new-volume
Second step is to use that volume in a docker-compose (in your case)
A single docker compose service with a volume looks like this:
version: "3.9"
services:
frontend:
image: node:lts
volumes:
- myapp:/home/node/app
volumes:
myapp:
On the first invocation of docker-compose up the volume will be created. The same volume will be reused on following invocations.
A volume may be created directly outside of compose with docker volume create and then referenced inside docker-compose.yml as follows:
version: "3.9"
services:
frontend:
image: node:lts
volumes:
- myapp:/home/node/app
volumes:
myapp:
external: true

Possible to access files from a different docker image within a container?

I'm trying to set up a docker-compose file for running Apache Guacamole.
The compose file has 3 services, 2 for guacamole itself and 1 database image. The problem is that the database has to be initialized before the guacamole container can use it, but the files to initialize the database are in the guacamole image. The solution I came up with is this:
version: "3"
services:
init:
image: guacamole/guacamole:latest
command: ["/bin/sh", "-c", "cp /opt/guacamole/postgresql/schema/*.sql /init/" ]
volumes:
- dbinit:/init
database:
image: postgres:latest
restart: unless-stopped
volumes:
- dbinit:/docker-entrypoint-initdb.d
- dbdata:/var/lib/postgresql/data
environment:
POSTGRES_USER: guac
POSTGRES_PASSWORD: guac
depends_on:
- init
guacd:
image: guacamole/guacd:latest
restart: unless-stopped
guacamole:
image: guacamole/guacamole:latest
restart: unless-stopped
ports:
- "8080:8080"
environment:
GUACD_HOSTNAME: guacd
POSTGRES_HOSTNAME: database
POSTGRES_DATABASE: guac
POSTGRES_USER: guac
POSTGRES_PASSWORD: guac
depends_on:
- database
- guacd
volumes:
dbinit:
dbdata:
So I have one container whose job is to copy the database initialization files into a volume and then I mount that volume in the database. The problem is that this creates a race condition and is ugly. Is there some elegant solution for this? Is it possible to mount the files from the guacamole image into the database container? I would rather avoid having an extra sql file with the docker-compose file.
Thanks in advance!

Storing MySQL data in an image file (formatted as ext4)

I'm trying to use Docker to containerize a MySQL (MariaDB actually) database. I figured out how to store MySQL data (/var/lib/mysql) in a volume mounted from a host directory.
However, because the underlying filesystem is different from host to host there are some inconsistencies, for example table names are case insensitive on NTFS (Windows). Also, it looks like if the database is created on a Linux host it doesn't work on a Windows host (haven't figured out why exactly).
Therefore, I want to store the data on a disk image and mount it inside the container, i.e. db-data.img formatted as ext4. But I'm facing a strange problem, when mounting this image inside the container:
$ docker run -v $PWD:/outside --rm -it ubuntu /bin/bash
# dd if=/dev/zero of=/test.img bs=1M count=100
# mkfs.ext4 test.img
# mount -o loop -t ext4 test.img /mnt
mount: /mnt: mount failed: Operation not permitted.
Using another directory instead of /mnt didn't work either.
Why does it refuse to mount the img file?
I would suggest to use docker-compose and just use a volume declared in the docker-compose.yml configuration.
Something like this:
version: '3'
services:
mysql:
image: mysql
environment:
MYSQL_ROOT_PASSWORD: $MYSQL_ROOT_PASSWORD
MYSQL_USER: $MYSQL_USER
MYSQL_PASS: $MYSQL_PASSWORD
volumes:
- mysql-data:/var/lib/mysql
volumes:
mysql-data:
The mysql-data volume should be stored as a separate volume, independent from the host operating system. The difference to just mounting a directory on the host, it's basically mounting a volume container (which you could also do without docker-compose, but it's more work).
It will not work inside of docker image, Docker blocks access to mouning filesystems (and loop devices). Should be easier create these image earlier, mount and connect to docker as folder by -v.
P.S. Another option is dump your database to sql and restore from windows.
I managed to solve this by using the privileged option in docker-compose.yml:
privileged: true
(or --privileged in the docker command)
Here is my final docker-compose.yml:
version: '3'
services:
db:
build: ./db
image: my_db
container_name: db
privileged: true
ports:
- "3306:3306"
environment:
- MYSQL_ROOT_PASSWORD=${MYSQL_ROOT_PASSWORD}
- MYSQL_USER=${MYSQL_USER}
- MYSQL_PASSWORD=${MYSQL_PASSWORD}
- MYSQL_DATABASE=${MYSQL_DATABASE}
volumes:
- ${MYSQL_DATA_IMG}:/data.img
restart: always
Dockerfile:
FROM mariadb
COPY my-custom.cnf /etc/mysql/conf.d/custom.cnf
COPY run.sh /usr/local/bin/run-mariadb.sh
ENTRYPOINT ["run-mariadb.sh"]
and a custom entry point script that executes mount (run.sh):
#!/bin/sh
# For this mount comamnd to work the DB container must be started
# with --privileged.
mount -o loop /data.img /var/lib/mysql
# Call the entry point script of MariaDB image.
exec /usr/local/bin/docker-entrypoint.sh mysqld
for storing database data make 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
plus you can check your data list by this command
docker volume ls
DRIVER VOLUME NAME
local 35c819179d883cf8a4355ae2ce391844fcaa534cb71dc9a3fd5c6a4ed862b0d4
local 133db2cc48919575fc35457d104cb126b1e7eb3792b8e69249c1cfd20826aac4
local 483d7b8fe09d9e96b483295c6e7e4a9d58443b2321e0862818159ba8cf0e1d39
local 725aa19ad0e864688788576c5f46e1f62dfc8cdf154f243d68fa186da04bc5ec
local de265ce8fc271fc0ae49850650f9d3bf0492b6f58162698c26fce35694e6231c
local phphelloworld_mysql-data

docker-compose save/load images to another host

I have found this, but it does not work for me.
My (really) simple docker-compose.yml:
version: '3.1'
services:
wordpress:
image: wordpress
restart: always
ports:
- 8080:80
environment:
WORDPRESS_DB_PASSWORD: example
mysql:
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
Starting:
docker-compose up
After made some change to containers (install plugins and themes on wordpress).
docker-compose stop
docker commit main_mysql_1 test-mysql
docker commit main_wordpress_1 test-wordpress
docker save test-mysql > test-mysql.tar
docker save test-wordpress > test-wordpress.tar
Save the two tar files on another machine and load them:
docker load -i ./test-mysql.tar
docker load -i ./test-wordpress.tar
Now change the docker-compose.yml to:
version: '3.1'
services:
wordpress:
image: test-wordpress
restart: always
ports:
- 8080:80
environment:
WORDPRESS_DB_PASSWORD: example
mysql:
image: test-mysql
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
But the container started is wordpress from scratch. Nothing of work done (plugin, themes, etc) was preserved.
What is my mistake? I don't want to use online repository for these private purposes.. Could you suggest a more simple and powerful procedure for pass container between two hosts?
A workaround with volumes:
version: '3.1'
services:
wordpress:
container_name: GREB_wordpress
image: wordpress
restart: always
ports:
- 8080:80
environment:
WORDPRESS_DB_PASSWORD: example
volumes:
- ./www:/var/www/html
mysql:
container_name: GREB_mysql
image: mysql:5.7
restart: always
environment:
MYSQL_ROOT_PASSWORD: example
volumes:
- ./mysql_data:/var/lib/mysql
First of all, docker volumes are not part of an image and/or a container. So these should be saved further the docker images (docker save).
For a better understanding of docker file system, volumes, ro/rw layer,
could be read
http://container-solutions.com/understanding-volumes-docker/.
Figure out if our image use volumes (seek "Volumes" key):
docker inspect image_name
You have different advantage to use volumes (refer to docker documentation for well understand) such as I/O performance.
A the end, for backup volumes:
Simply backup volumes folder e.g. tar -cvzPf volume_name_backup.tar.gz /var/lib/docker/volumes/VOLUME_NAME...and restore them in the same place
Backup, restore, or migrate data volumes through another docker container
In case of db image (like my case with mysql) you can also dump the db: docker exec mysql_container /usr/bin/mysqldump -u root --password=root --all-databases > mysql_dump_backup.sql

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

Resources