Skip to content

Data Persistence and Docker Compose

Have you ever wondered, what happens if you shut down the containers - what will happen with the precious content of the Database?

Or ... where does the Data even go?! 🤔

In this lecture we're going to explore just that: Different options for volume mounting inside Docker-Compose!

View the Full Course Now

Databases and Data Persistence in Host-Volume Mounted Directories in Docker Step by Step

In the previous example we were spinning up our database with our web-app. But docker containers are ephemeral. This means they are losing all data once removed and re-started. So, somehow, we must find a way to make data persistent if we want to keep it. Use this docker-compose.yml file:

version: '3'

services:
  db:
    image: mysql:latest
    restart: always
    container_name: myphpapp-db
    environment:
       MYSQL_ROOT_PASSWORD: somepass
       MYSQL_DATABASE: somedatabase

  dbclient:
    image: mysql:latest
    depends_on:
      - db
    command: mysql -uroot -psomepass -hdb
  • MYSQL_DATABASE will create an empty database with the name "somedatabase" at first spin-up
  • depends_on waits for the container to start on the other containers

command

If you look at the command for the dbclient service, you see that we wrote mysql -uroot -psomepass -hdb. There is no space between -u and the username root, -p and the password and -h and the host.

Start the Containers

Let's run the containers and see what will happen:

Run the command:

docker-compose up -d
  • starts both containers in detached mode (-d)
docker-compose ps
  • will show the "db" running, while the other one stopped

docker-compose run --rm dbclient
* should connect to the "db" and open a mariadb shell Enter the following SQL queries:

USE somedatabase;
SHOW TABLES;
Observe that it's empty!

CREATE TABLE mytable (id INT);
SHOW TABLES;

Now you have one table in your database, which we created.

mysql> SHOW TABLES;
+------------------------+
| Tables_in_somedatabase |
+------------------------+
| mytable                |
+------------------------+
1 row in set (0.00 sec)

Exit the console with

exit;

Now stop the container:

docker-compose stop

and remove the containers

docker-compose rm
  • removes all (not running) containers from docker-compose

Remove Containers

You can also stop and remove all containers by doing docker-compose down

Let's re-run everything and see if data persisted:

docker-compose up -d
  • Re-Run the containers based on the images
  • Only the database container is running

Login to the mysql shell again:

docker-compose run --rm dbclient

Then run again:

USE somedatabase;
SHOW TABLES;
Observe it's empty again. But why?! And what can we do about it?!
exit;

and remove the containers:

docker-compose stop
docker-compose rm
* Stop and remove the containers before we continue

So, how can we make data persistent, even we remove the containers? With volumes and a host-mounted data directory, for example.

mkdir data
* Create a new "data" directory on the host

And add a volumes key to your docker-compose.yml file:

version: '3'

services:
  db:
    image: mysql:latest
    restart: always
    container_name: myphpapp-db
    environment:
       MYSQL_ROOT_PASSWORD: somepass
       MYSQL_DATABASE: somedatabase
    volumes:
      - ./data:/var/lib/mysql

  dbclient:
    image: mysql:latest
    depends_on:
      - db
    command: mysql -uroot -psomepass -hdb

Now start the db service:

docker-compose db -d up
  • Observe the data directory, it gets populated with data

We can also enter the container now.

docker-compose run --rm dbclient

Recreate the table:

USE somedatabase;
SHOW TABLES;

Then create the table, because it is empty right now.

CREATE TABLE mytable (id INT);
SHOW TABLES;

And then exit and stop and remove the container:

exit;
docker-compose stop
docker-compose rm

Now spin up the db container again:

docker-compose up -d db
Then login to the mysql client:

docker-compose run --rm dbclient
USE somedatabase;
SHOW TABLES;

Observe the database is now persistent. But maybe writing on the host into a directory is not the best solution in this case. Maybe a named volume would be better?! Oh wait there's a lecture about that in the next step 🎉