{"id":106526,"date":"2025-05-29T20:51:37","date_gmt":"2025-05-29T20:51:37","guid":{"rendered":"https:\/\/www.red-gate.com\/simple-talk\/?p=106526"},"modified":"2025-06-05T11:42:42","modified_gmt":"2025-06-05T11:42:42","slug":"running-a-mysql-database-in-a-docker-container","status":"publish","type":"post","link":"https:\/\/www.red-gate.com\/simple-talk\/databases\/mysql\/running-a-mysql-database-in-a-docker-container\/","title":{"rendered":"Running a MySQL database in a Docker Container"},"content":{"rendered":"\n<h1 class=\"wp-block-heading\" id=\"h-\"><\/h1>\n\n\n\n<p>Relational databases provide a structured approach for storing and organizing large volumes of data into tables consisting of rows for records, and columns for attributes. They use primary keys which are unique identifiers for records and foreign keys, to establish well defined relationships between tables.<\/p>\n\n\n\n<p>These databases are widely used since they are reliable, consistent, and highly adaptable to various applications. They also provide complex database queries and operations capabilities using a <a href=\"https:\/\/www.w3schools.com\/sql\/sql_intro.asp\">structured query language (SQL)<\/a>. They are backed up with a strong and mature ecosystem; with extensive tooling and community support.<\/p>\n\n\n\n<p>MySQL, PostgreSQL, MariaDB, Microsoft SQL Server, and Oracle databases are all examples of relational databases. You can run them within virtual machines or Docker containers. This article, on the other hand, will include the steps to run MySQL, which is one of the widely used relational databases in a Docker container.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-why-run-a-relational-database-with-docker\"><a id=\"post-106526-_1hk3nsj6gz5r\"><\/a><a id=\"post-106526-_2rszzcyxin1c\"><\/a>Why run a Relational Database with Docker<\/h2>\n\n\n\n<p>You might be wondering why one would run a complex system like a relational database in a Docker container in the first place, well hang on. There is no doubt that containers are designed primarily for stateless applications. That is to say, containers are ephemeral in nature and without proper configuration, the operational status of a container could be disrupted, resulting in data loss.<\/p>\n\n\n\n<p>Databases, on the other hand, are stateful and require persistent storage to run optimally, especially in times of restarts and even crashes. Yes, Docker volumes are designed to persist data beyond the lifecycle of a container; however, running a relational database is fine for development and testing purposes but is not recommended for production. Instead, for production environments you should run them on standalone servers, managed database services like AWS RDS or Azure SQL database, or store data on an external volume like cloud storage or block storage (AWS EBS, Azure managed Disks, etc).<\/p>\n\n\n\n<p>Here are some of the reasons why you might need to run a relational database with Docker in detail:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li><strong>Isolation and reproducibility<\/strong>: Docker containers provide you with the ability to run applications in a completely isolated environment; to test new database features, configurations, or updates like security parameters, user roles, authentication, and many more. <\/li>\n\n\n\n<li><strong>Microservice Decoupling<\/strong>: To implement a microservice architecture whereby you can ensure data isolation to one service\u2019s database without affecting the database of a different service. <\/li>\n\n\n\n<li><strong>Try and Error<\/strong>: To experiment with different database configurations on the same machine using multiple database instances. You can test different database engines or different versions of the same engine. <\/li>\n<\/ul>\n<\/div>\n\n\n<p>In this article, I will show you how to get MySQL up and running, and show you how to set it up and use MySQL On Docker for your non-production environments.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-prerequisites\">Prerequisites<\/h2>\n\n\n\n<p>To follow along, you are required to have Docker engine installed on your machine. This tutorial uses the latest versions of Docker (28.0.1) on an Ubuntu 24.04 LTS server from when this piece was written. There may be subtle differences as time passes, and if you are using a different operating system.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-pulling-the-official-mysql-docker-image\">Pulling the Official MySQL Docker Image<\/h2>\n\n\n\n<p>Whether it&#8217;s a relational or non-relational database, or something else entirely, you need to pull a base image if you would like to run anything with Docker. In the case of a relational database like MySQL, the <a href=\"https:\/\/hub.docker.com\/_\/mysql\">official Docker image from DockerHub<\/a> is maintained by the MySQL team. It is pre-configured with all dependencies to run MySQL effectively. It is also properly documented to help you quickly install and make configurations for MySQL on your host system.<\/p>\n\n\n\n<p>Execute the following command to pull the official MySQL docker image from DockerHub:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker pull mysql<\/pre><\/div>\n\n\n\n<p>This should pull the latest version from DockerHub. Once the MySQL image has been pulled successfully, you are expected to have the following output:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">Using default tag: latest\nlatest: Pulling from library\/mysql\n43759093d4f6: Pull complete\nd255dceb9ed5: Pull complete\n23d22e42ea50: Pull complete\n431b106548a3: Pull complete\n2be0d473cadf: Pull complete\nf56a22f949f9: Pull complete\n277ab5f6ddde: Pull complete\ndf1ba1ac457a: Pull complete\ncc9646b08259: Pull complete\n893b018337e2: Pull complete\nDigest: sha256:146682692a3aa409eae7b7dc6a30f637c6cb49b6ca901c2cd160becc81127d3b\nStatus: Downloaded newer image for mysql:latest\ndocker.io\/library\/mysql:latest<\/pre><\/div>\n\n\n\n<p>Confirm that the MySQL image is available on your machine using the following command:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker images<\/pre><\/div>\n\n\n\n<p>You are good to go if it is listed among the Docker images available on your machine:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">REPOSITORY                    TAG       IMAGE ID       CREATED         SIZE\nmysql                         latest    5568fddd4f66   6 weeks ago     797MB<\/pre><\/div>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-creating-a-docker-network\"><a id=\"post-106526-_93k0uaqljr0x\"><\/a>Creating a Docker Network<\/h2>\n\n\n\n<p>Networks in Docker represent a communication environment that allows containers to communicate and interact with each other in a secure manner. Regardless of what kind of image or application you are running with Docker, you should always consider creating a Docker network to ensure isolated communication between your containers.<\/p>\n\n\n\n<p>Docker supports seven network drivers by default, you can find them <a href=\"https:\/\/docs.docker.com\/engine\/network\/\">on the official Docker documentation<\/a>. If other network drivers are not set, the bridge network driver is the default. Additionally, a Docker network is automatically created when you run a Docker image as a container. In our case, we will create a custom docker network using the bridge network driver and give it a generic name <em>mysql-net<\/em> with the following command:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker network create -d bridge mysql-net<\/pre><\/div>\n\n\n\n<p>Confirm that <code>mysql-net<\/code><em> <\/em>is listed amongst the list of Docker networks on your machine:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker network ls<\/pre><\/div>\n\n\n\n<p>You should see it listed in the list like so:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">NETWORK ID     NAME        DRIVER    SCOPE\n29931b56ee5a   mysql-net   bridge    local<\/pre><\/div>\n\n\n\n<p>Run the MySQL image as a Docker container, connect to the <code>mysql-net<\/code><em> <\/em>network and initialize the MySQL database with a root password. If you are going to use this instance for any work, use a proper password:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker run -d --network=mysql-net -e MYSQL_ROOT_PASSWORD=superadminuser mysql<\/pre><\/div>\n\n\n\n<p>Take note, you can also initialize the MySQL database with two more authentication-related environment variables. For example:<\/p>\n\n\n<div class=\"block-core-list\">\n<ul class=\"wp-block-list\">\n<li><code>MYSQL_ALLOW_EMPTY_PASSWORD<\/code>: This environment variable allows the MySQL database to start without a root password; which is not proper for production environments. <\/li>\n\n\n\n<li><code>MYSQL_RANDOM_ROOT_PASSWORD<\/code>: This environment variable allows the MySQL database to start with a random root password and then print it in the logs. <\/li>\n<\/ul>\n<\/div>\n\n\n<p>For our case, our current setup will suffice. Verify that the MySQL database is up and running using the command below:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker ps<\/pre><\/div>\n\n\n\n<p>You should have the output similar to the following:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">CONTAINER ID   IMAGE     COMMAND                  CREATED         STATUS         PORTS                 NAMES\n9c8b1f4a9b57   mysql     \"docker-entrypoint.s\u2026\"   9 seconds ago   Up 8 seconds   3306\/tcp, 33060\/tcp   blissful_noether<\/pre><\/div>\n\n\n\n<p>Dates, times and the <code>CONTAINER ID<\/code> value will be different, but the output should look very similar.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-checking-for-data-persistence\"><a id=\"post-106526-_odmdst6pqghh\"><\/a>Checking for Data Persistence<\/h2>\n\n\n\n<p>Again, containers are stateless, a database that runs in a container risks losing all its data if the container is deleted whether on purpose or unexpectedly. Therefore, it is mandatory to use data persistence mechanisms to ensure that data is retained even if the container stops or is removed. In this case, you\u2019ll consider common persistence mechanisms like Docker volumes or bind mounts.<\/p>\n\n\n\n<p>To begin, let\u2019s confirm data is not persistent when a container is deleted. Go into the MySQL container using the following command, replacing <code>&lt;container-id&gt;<\/code><em> <\/em>with your MySQL container ID:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker exec -it &lt;container-id&gt; mysql -uroot -p<\/pre><\/div>\n\n\n\n<p>For example, in my case it would be:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker exec -it 9c8b1f4a9b57 mysql -uroot -p<\/pre><\/div>\n\n\n\n<p>Input your password and you should get a prompt to enter MySQL commands. So to start, we will create a database named: <code>book_hub<\/code>:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:mysql\" highlight=\"true\" decode=\"true\">CREATE DATABASE book_hub;<\/pre><\/div>\n\n\n\n<p>You should see messages after most commands. Like after this one you will see \u201cQuery OK, 1 row affected\u201d for example. Next, select the <code>book_hub<\/code><em> <\/em> database:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:mysql\" highlight=\"true\" decode=\"true\">USE book_hub;<\/pre><\/div>\n\n\n\n<p>Create a table <code>Publishers<\/code><em> <\/em>in the <code>book_hub<\/code><em> <\/em>database:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"wrap:true lang:mysql decode:true block\">CREATE TABLE Publisher(pubID varchar(255) not NULL, bname text(50) not NULL,city varchar(255) not NULL, country text(50) not NULL, PRIMARY KEY(pubID));<\/pre><\/div>\n\n\n\n<p>Next, add some data into the <code>Publishers<\/code><em> <\/em>table, the following values:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:mysql\" highlight=\"true\" decode=\"true\">INSERT INTO Publisher (pubID, bname, city, country)  \nVALUES\n    ('p22', 'Random House', 'Las Vegas', 'United States'),\n    ('p10', 'Dell Books', 'Colorado', 'United States'),\n    ('p078', 'Pen Books', 'London', 'United Kingdom'),\n    ('p279', 'Signet Books', 'Aberdeen', 'United Kingdom'),\n    ('p12', 'Macmillan', 'London', 'United Kingdom'),\n    ('p29', 'Madhavan', 'Aberdeen', 'United Kingdom');<\/pre><\/div>\n\n\n\n<p>Confirm that all values have been inserted (in addition to the message you will have received):<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:mysql\" highlight=\"true\" decode=\"true\">SELECT * FROM Publisher;<\/pre><\/div>\n\n\n\n<p>You should have the following output:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">+-------+--------------+-----------+----------------+\n| pubID | bname        | city      | country        |\n+-------+--------------+-----------+----------------+\n| p078  | Pen Books    | London    | United Kingdom |\n| p10   | Dell Books   | Colorado  | United States  |\n| p12   | Macmillan    | London    | United Kingdom |\n| p22   | Random House | Las Vegas | United States  |\n| p279  | Signet Books | Aberdeen  | United Kingdom |\n| p29   | Madhavan     | Aberdeen  | United Kingdom |\n+-------+--------------+-----------+----------------+<\/pre><\/div>\n\n\n\n<p>Exit out of the MySQL container and <em>exec <\/em>back into the MySQL container:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">exit\n\ndocker exec -it &lt;container-id&gt; mysql -uroot -p<\/pre><\/div>\n\n\n\n<p>The aim here is to check if the data is still available even after exiting out of the MySQL container.<\/p>\n\n\n\n<p>Now select the <code>book_hub<\/code> database and view the <em>publishers<\/em> table with the following commands:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">USE book_hub;\n\nSELECT * FROM Publisher;<\/pre><\/div>\n\n\n\n<p>You should see the contents of the Publisher table outputted to you which is expected. This simply means that exiting out of the MySQL container doesn\u2019t incur data loss. To simulate data loss, you\u2019ll need to remove the MySQL container and run a new one.<\/p>\n\n\n\n<p>Stop and remove the MySQL container:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker rm &lt;container-id&gt; -f<\/pre><\/div>\n\n\n\n<p style=\"padding-right:0;padding-left:var(--wp--preset--spacing--md)\">Note: While containers do not lose data when you exit it, or even if you restart the container (which you can do with the Docker <a href=\"https:\/\/docs.docker.com\/reference\/cli\/docker\/container\/start\/&quot; \\o &quot;https:\/\/docs.docker.com\/reference\/cli\/docker\/container\/start\/&quot; \\t &quot;_blank\">start <\/a>and <a href=\"https:\/\/docs.docker.com\/reference\/cli\/docker\/container\/stop\/&quot; \\o &quot;https:\/\/docs.docker.com\/reference\/cli\/docker\/container\/stop\/&quot; \\t &quot;_blank\">stop <\/a>commands), being able to destroy and recreate the container makes it easier to test new features or updates without affecting the data you have stored. Some care may need to be taken to use a compatible version of MySQL (or any tool you are using), and it may be best to make a copy of your data before attaching that new container. <\/p>\n\n\n\n<p>Next, Initialize a new MySQL instance:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker run -d --network=mysql-net -e MYSQL_ROOT_PASSWORD=superadminuser mysql<\/pre><\/div>\n\n\n\n<p>Then connect to it by finding the container Id:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker ps<\/pre><\/div>\n\n\n\n<p>Then connecting to it by using the container id.:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker exec -it &lt;container-id&gt; mysql -uroot -p<\/pre><\/div>\n\n\n\n<p>Input your password and attempt to use the <em>book_hub<\/em> database:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">USE book_hub;<\/pre><\/div>\n\n\n\n<p>You should see an error message similar to the one below:<\/p>\n\n\n\n<p class=\"has-roboto-mono-font-family\">ERROR 1049 (42000): Unknown database &#8216;book_hub&#8217;<\/p>\n\n\n\n<p>This is expected because the <em>book_hub<\/em> database and its data were stored inside the previous container. Since we removed that container, all its data was lost.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-configuring-data-persistence-with-docker-volumes\"><a id=\"post-106526-_gt53gm4hz166\"><\/a>Configuring Data Persistence with Docker Volumes<\/h2>\n\n\n\n<p>Docker volumes allow you to store data outside of Docker containers. With Docker volumes data can be maintained across container lifecycles so you don\u2019t have to worry about data loss in time of container crashes or disruptions.<\/p>\n\n\n\n<p>To begin, you must run the MySQL container with a volume. You can create a volume separately and then attach it to the MySQL container, or you create one on the go while running the MySQL container. Use the following command to run the MySQL container with a volume called <em>mysql-data<\/em>:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker run -d --network=mysql-net \\\n  -e MYSQL_ROOT_PASSWORD=superadminuser \\\n  -v mysql-data:\/var\/lib\/mysql \\\n  mysql<\/pre><\/div>\n\n\n\n<p>Confirm the MySQL container is running and get its container ID:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker ps<\/pre><\/div>\n\n\n\n<p>Go into the MySQL container:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker exec -it &lt;container-id&gt; mysql -uroot -p<\/pre><\/div>\n\n\n\n<p>Create a database with the name <em>book_hub <\/em>and select it as your database. Follow the same process as before using these commands:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:mysql\" highlight=\"true\" decode=\"true\">CREATE DATABASE book_hub;<\/pre><\/div>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:mysql\" highlight=\"true\" decode=\"true\">USE book_hub;<\/pre><\/div>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:mysql\" highlight=\"true\" decode=\"true\">CREATE TABLE Author (\n    authorID VARCHAR(255) NOT NULL,\n    bname TEXT NOT NULL,\n    city VARCHAR(255) NOT NULL,\n    country TEXT NOT NULL,\n    PRIMARY KEY (authorID)\n);<\/pre><\/div>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">INSERT INTO Author (authorID, bname, city, country)  \nVALUES\n    ('A21', 'Grisham', 'New York', 'United States'),\n    ('A01', 'Cook', 'London', 'United States'),\n    ('A27', 'Hailey', 'Manchester', 'United Kingdom'),\n    ('A301', 'Segal', 'Houton', 'United Kingdom'),\n    ('A478', 'Forsyth', 'New York', 'United Kingdom');<\/pre><\/div>\n\n\n\n<p>Now, view the <em>Author<\/em> data;<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">SELECT * FROM Author;<\/pre><\/div>\n\n\n\n<p>And just like earlier in the article, you should see the following output:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">+----------+---------+------------+----------------+\n| authorID | bname   | city       | country        |\n+----------+---------+------------+----------------+\n| A01      | Cook    | London     | United States  |\n| A21      | Grisham | New York   | United States  |\n| A27      | Hailey  | Manchester | United Kingdom |\n| A301     | Segal   | Houston    | United Kingdom |\n| A478     | Forsyth | New York   | United Kingdom |\n+----------+---------+------------+----------------+<\/pre><\/div>\n\n\n\n<p>Exit the MySQL container by typing <em>exit<\/em> and proceed to delete the MySQL container using the following command:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker rm &lt;container_id&gt; -f <\/pre><\/div>\n\n\n\n<p>Confirm that the Docker volume <code>mysql-data<\/code><em> <\/em> still exists:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker volume ls<\/pre><\/div>\n\n\n\n<p>Because the MySQL container was removed doesn\u2019t mean the Docker volume is also, you should see it listed among other Docker volumes present on your machine:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">DRIVER    VOLUME NAME\nlocal     5c2849d0dbfca9187b96438ef37c613b384978d5d18e3fc35c6b3a462f3d0025\nlocal     mysql-data<\/pre><\/div>\n\n\n\n<p>Now spin up a new container and attach the volume<em> (mysql-data)<\/em> to it:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker run -d --network=mysql-net \\\n  -e MYSQL_ROOT_PASSWORD=superadminuser \\\n  -v mysql-data:\/var\/lib\/mysql \\\n  mysql<\/pre><\/div>\n\n\n\n<p>Connect to the MySQL container (again finding the container id with <code>docker ps<\/code>):<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker exec -it &lt;container-id&gt; mysql -uroot -p<\/pre><\/div>\n\n\n\n<p>Confirm that the <code>book_hub<\/code> database exists by attempting to select it:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">USE book_hub;<\/pre><\/div>\n\n\n\n<p>If you have the following output, you have successfully persisted data with Docker volumes.<\/p>\n\n\n\n<p>This shows that the database exists:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">Database changed<\/pre><\/div>\n\n\n\n<p>This is also true for all tables in the <code>book_hub<\/code> database, for example, view the <code>Author<\/code> table:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:mysql\" highlight=\"true\" decode=\"true\">SELECT * FROM Author;<\/pre><\/div>\n\n\n\n<p>Should return:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">+----------+---------+------------+----------------+\n| authorID | bname   | city       | country        |\n+----------+---------+------------+----------------+\n| A01      | Cook    | London     | United States  |\n| A21      | Grisham | New York   | United States  |\n| A27      | Hailey  | Manchester | United Kingdom |\n| A301     | Segal   | Houtons    | United Kingdom |\n| A478     | Forsyth | New York   | United Kingdom |\n+----------+---------+------------+----------------+<\/pre><\/div>\n\n\n\n<p>So now we have part of the picture.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-configuring-data-persistence-with-bind-mounts\"><a id=\"post-106526-_nm1ptejm4okk\"><\/a>Configuring Data Persistence with Bind Mounts<\/h2>\n\n\n\n<p>Bind mounts can also ensure data persistence; especially when you want your container to have direct access to host files. While slower due to direct filesystem access, you can persist data as we have done with Docker volumes.<\/p>\n\n\n\n<p>To use bind mounts, you must first create the directory on your host machine that you want to mount into the container. If the directory already exists you\u2019ll need to mount the host on the go while running the MySQL container. Keep in mind that bind mounts use your host filesystem and are not managed by Docker.<\/p>\n\n\n\n<p>Create a directory <code>mysql-data<\/code> on the host with the following command:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">sudo mkdir -p \/documents\/mysql-data<\/pre><\/div>\n\n\n\n<p>Run the MySQL container and mount the host directory inside the MySQL container:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker run -d --network=mysql-net -e MYSQL_ROOT_PASSWORD=superadminuser \\\n-v \/home\/user\/documents\/mysql-data:\/var\/lib\/mysql \\\nMysql<\/pre><\/div>\n\n\n\n<p>Check that the MySQL container is running:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker ps<\/pre><\/div>\n\n\n\n<p>Go inside the MySQL container and create a database :<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker exec -it &lt;container-id&gt; mysql -uroot -p<\/pre><\/div>\n\n\n\n<p>Enter the root password and then execute the following commands sequentially:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block lang:mysql\" highlight=\"true\" decode=\"true\">CREATE DATABASE testdb;\nSHOW DATABASES;\nEXIT;<\/pre><\/div>\n\n\n\n<p>Remove the MySQL container:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker rm &lt;container-id&gt; -f<\/pre><\/div>\n\n\n\n<p><code>Rerun<\/code> the MySQL container:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker run -d --network=mysql-net -e MYSQL_ROOT_PASSWORD=superadminuser \\\n-v \/home\/user\/documents\/mysql-data:\/var\/lib\/mysql \\\nMysql<\/pre><\/div>\n\n\n\n<p>Check if the <code>testdb<\/code><em> <\/em>still exists by running the below command:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">docker exec -it &lt;container-id&gt; mysql -uroot -p<\/pre><\/div>\n\n\n\n<p>Then execute:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">SHOW DATABASES;<\/pre><\/div>\n\n\n\n<p>You should see the <code>testdb<\/code><em> <\/em>database listed among all available databases:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">mysql&gt; SHOW DATABASES;<\/pre><\/div>\n\n\n\n<p>Then you should see:<\/p>\n\n\n\n<div class=\"wp-block-urvanov-syntax-highlighter-code-block\"><pre class=\"block\" highlight=\"false\" decode=\"true\">+--------------------+\n| Database           |\n+--------------------+\n| information_schema |\n| mysql              |\n| performance_schema |\n| sys                |\n| testdb             |\n+--------------------+\n5 rows in set (0.02 sec)<\/pre><\/div>\n\n\n\n<p>This shows that data has persisted, so you can now drop and recreate the container, referencing the Bind Mount, and the data you expect will be there.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\" id=\"h-conclusion\">Conclusion<\/h2>\n\n\n\n<p>You can run any application in a containerized environment with Docker, including a relational database like MySQL, and have an understanding how to keep data persisted, even after a reboot.<\/p>\n\n\n\n<p>In this article, you have seen how to run a MySQL database in Docker over a custom Docker network, configured data persistence using Docker volumes and bind mounts, and most of all, understand why you might want to run MySQL in a Docker container in the first place.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Relational databases provide a structured approach for storing and organizing large volumes of data into tables consisting of rows for records, and columns for attributes. They use primary keys which are unique identifiers for records and foreign keys, to establish well defined relationships between tables. These databases are widely used since they are reliable, consistent,&#8230;&hellip;<\/p>\n","protected":false},"author":341730,"featured_media":106527,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_acf_changed":false,"footnotes":""},"categories":[143513,53,145792],"tags":[159078,5854],"coauthors":[158989],"class_list":["post-106526","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-containers-and-virtualization","category-featured","category-mysql","tag-docker","tag-mysql"],"acf":[],"_links":{"self":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/106526","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/users\/341730"}],"replies":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/comments?post=106526"}],"version-history":[{"count":3,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/106526\/revisions"}],"predecessor-version":[{"id":107117,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/posts\/106526\/revisions\/107117"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media\/106527"}],"wp:attachment":[{"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/media?parent=106526"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/categories?post=106526"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/tags?post=106526"},{"taxonomy":"author","embeddable":true,"href":"https:\/\/www.red-gate.com\/simple-talk\/wp-json\/wp\/v2\/coauthors?post=106526"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}