In this video, you’ll learn how to permanently save your database
when using a database inside a Docker container.
I’ve created a few videos on how to set up a database in Docker,
but one of the common questions is “how can I save my database permanently?”
I didn’t know either, so I did some research.
By default, Docker does not keep data that you create inside a container. You can stop and
start a container, and from what I’ve seen, the data in your database is still there.
But if you remove a container, or want to recreate a container, then the data is gone.
What if you want to keep the data? Luckily, this can be done.
In Docker, there are two methods for keeping data on a more permanent basis.
The first is called a volume, and the second is called a bind mount.
I’ll explain the differences and show you how to set up both in this video.
During my research for this video, I read a range of articles.
Most of them just made me more confused: bind? mount? host? volume? whaaat?
I didn’t know what the difference was. But after some reading and experimentation,
I’ve got a basic understanding.
So what are they and what are the differences.
A volume in Docker is essentially a directory inside Docker.
It can be accessed by containers and it’s kept when you remove a container.
A bind mount in Docker is where you link a directory inside Docker to a directory on
your host machine, otherwise known as outside Docker or on your computer. You can browse
this folder using Windows Explorer or Finder and see the files. You can’t do this with a volume.
But volumes have more features within Docker and according to their documentation,
volumes are the preferred approach.
For this video, we’ll use a MySQL image,
but the concepts will work with whatever database image you want to use.
You’ll also need to have Docker set up on your computer. For the steps on how to do this, you
can refer to any of my other videos on setting up Docker, which I’ve linked to in the description.
So, now we’ve got an overview, let’s get started with creating them.
First, we’ll create a volume, then we’ll create a bind mount.
To do this, open a Terminal window or a Command Prompt.
We can create a volume using the docker volume create command.
We’ll call our new volume mysqlvol.
The command to do this is docker volume create mysqlvol, so type that and press Enter.
After a moment you’ll see the name of the volume appear, then you’ll see the prompt.
We can check it was created by listing all of the volumes,
which you can do with docker volume list or docker volume ls.
Run that command and you can see the mysqlvol
volume at the bottom of the list. The other entries in the list here
are other volumes from other databases that I’ve created, which we can ignore for now.
Now that we have our volume, we can create a container that uses this volume. To do this,
we use the docker run command, and add a parameter for it.
We’ll be using MySQL for this demo, but as mentioned before,
this should work for other databases such as Oracle, SQL Server, and PostgreSQL.
The command to run a container for MySQL without using this volume would look like this:
To use the volume we just created, we add a parameter called “mount”.
We add this before the word “mysql” at the end, which is the image name to use.
So, we add two dashes, then mount. After that, we add the source and the target,
separated by a comma. The source is the name of the volume we have created,
which is mysqlvol. The target is set to this location: /var/lib/mysql. I think this is the
location within Docker that MySQL uses, and when I set it to something else I had issues.
I’ve also set the name of the container to mysql-wvol,
which is short for “mysql with volume”, so I can tell that this one uses a volume I have created.
But you can call it whatever you like.
So, this is the command to run. The other details in this command, such as the port numbers 3306,
the password, were covered in my other video on setting up docker with MySQL.
If you run this command, a new container will be created.
You’ll see a random set of alphanumeric characters, which is the ID of the container,
and you’ll be returned to the prompt.
You can check the status of the container by running docker ps.
When you run this, you should see an entry with a name of “mysql-wvol” and a status of “Up”.
Now we can test the connection.
We’ll test the connection and create some data by using MySQL Workbench.
You can use any other IDE, but this is a popular one with MySQL.
So, open MySQL Workbench. If you already have a connection set up for Docker,
use that. Otherwise, you can create one using a hostname of 127.0.0.1,
a port of 3306, a username of root, and a password of my-secret-pw.
Once you have connected, you should see one schema on the left called sys.
We’re going to create a database and a table and insert a record,
just to give us something that we can check later to ensure the data is saved.
We’ll create a database called my_test_db using this create database command.
So run that command by entering it and clicking the Execute Statement button.
You should see an output down the bottom saying it was successful.
Run the command Use my_test_db to set it as the database to be used.
You can also click the refresh button on the left to have the database shown in the left panel.
Next, we’ll create a simple table to add some data to it. We’ll create this table here,
called test table, with a single column. Run the command and the table is created.
Then we will insert a record into that table. We’ll insert this value of “test insert”.
Next, commit the data so it’s saved.
Then, select from the test table and you should see the record you added.
So, we’ve added a table and a record,
and all of this should be stored in the mysqlvol volume that we created.
Now, we’ll take some steps to remove and create the container, and check the data is still there.
Let’s remove the container. First, we have to stop it as it’s currently running.
So, we run docker stop mysql-vol.
Once the command is finished, run docker ps -a
which shows all containers. Docker ps only shows the running containers. You
should see the mysql-vol container here and it should not be running.
Now we can remove the container. This will delete the container from the system.
To do this, type docker container rm mysql-wvol. This will remove the container called mysql-wvol.
Once you run that command, the container should be removed.
Run docker ps -a again, and you should not see that container in your list.
You can check the list of volumes by running docker volume list,
like we did before. If you run this, you’ll see the mysqlvol
volume in the list still. This was not deleted when we removed the container.
Now, let’s create a new container that uses this volume.
We’ll use the same command as before, just with a different container name.
You can use a different mysql version if you want, or other settings. We’ll keep ours the same.
So, create a container by using the docker run command.
We’ll call our container mysql-wvol2, so we can see it’s not the same name as the earlier one.
The important part here is the mount parameter. This is the same
as earlier. We’ve included the mysqlvol as the source, and the target as /var/lib/mysql.
Run this command and the container is created.
We can check the status of the container by running docker ps.
Run this command and you can see that the container is running. So far so good.
Finally, we can connect to this container and check that our data is there.
Open MySQL Workbench and connect to the database.
If your docker run command was the same as earlier, your connection should still work.
Once you connect to the database, you should see the database you created earlier
on the left panel. You may need to click refresh, but otherwise it will be showing.
Run a simple Select query on the test table you created, and you should see the
record that you inserted earlier. This table was created in the first container we made,
and the database was stored in the volume and kept when the container was removed.
This shows that the data is kept for different containers.
So, that’s how you can use a volume to store data in Docker.
The second way to store data permanently is using a bind mount.
As mentioned at the start of the video, a bind mount uses a folder on your computer
that is referred to from within the Docker container.
We start by setting up a folder on our computer.
At the command prompt, I’m in the “BB” folder. For this tutorial,
I’ll just create a new folder here. I’ll call it “mysql_bind_folder” using this mkdir
command. Alternatively, you can use the Finder program or Windows Explorer to create the folder.
Once that’s done, we can create a new container using the docker run command.
It’s similar to creating a new volume, but the mount parameter is different.
The mount parameter looks the same, except for a couple of things.
We have a parameter called type, which we specify as bind.
The default is volume, which is why we didn’t specify it for the volume we created earlier.
The other parameter is source. When we use a volume, we create a volume and refer to it here.
But for a bind mount, we need to refer to the folder on our computer. We need to specify the
“mysql_bind_folder” we just created. And we also need to specify the path to that folder. The easy
way to do that is to use this pwd command, which will be replaced with the folder you are in. So,
if I run this command from within the BB folder, it puts the BB folder into this parameter.
Ensure you surround it in quotes and make it look like this command here.
The target and everything else remains the same.
Now, run this command. A new container should be created.
Run docker ps -a to check the status of the container, and it should be up and running.
A bind mount refers to files on our computer.
So, we can actually look at the folder we created on our computer and see what’s inside.
If you browse to the mysql_bind_folder you can see a range of files and folders inside it.
There’s no need to edit or open any of them, but you can see they were created by Docker.
Now, let’s connect to the database and create some data.
We’ll use the same process as we did for volumes. Open MySQL Workbench and connect to the database.
There are no databases created so far, other than sys.
So, let’s create one. We can use the same commands as we did earlier.
We create a database here, then run the Use command. Run these one after the other.
Then, we create a table called test_table. Then,
add a record into it, and commit the inserted data.
We can refresh the database list on the left to see the new database created. So far, so good.
If we go back to our Finder window or Windows Explorer,
we can see a new folder created for the database. Inside the folder is a file for that table. We
don’t do anything with these files, but it’s just interesting to see that they have been created.
Now let’s remove the container and create a new one.
We can remove the container by using the docker container rm command.
Once this is run, we can check the list of containers by using docker ps -a.
The mysql container is no longer there.
Create a new container by using the same command as before.
We’ll change the container name to something different,
such as mysql-wbind2. Everything else is the same, especially the mount parameter.
Run this command and a new container is created.
Check the status of the container by running docker ps -a. We can see it is running.
Finally, we can connect to the database to see the data. Open MySQL Workbench again and
connect to the database. We can see our database on the left here has remained.
We can run a sample Select query and can see the record that we inserted earlier.
So, that’s how we can use a bind mount in Docker.
The data was saved in files on our host computer, or the computer outside of Docker.
According to the Docker documentation, they recommend using volumes instead of bind mounts
for several reasons, but I just wanted to demonstrate that both methods can work.
And that brings us to the end of this video
on saving databases permanently in Docker using volumes or bind mounts.
If you learned something new from this video, make sure to subscribe to my channel.
If you want to learn more about database design and development, visit databasestar.com.
That’s where I share my best database-related content.
Which tip from this video was the most helpful? Was it the syntax for running the container
using a volume or bind mount, or the simple definitions of what they mean, or something else?
Thanks for watching.