Skip to main content

[SOLVED] How can I initialize a MySQL database with schema in a Docker container? - docker

[SOLVED] Effective Methods for Initializing a MySQL Database with Schema in a Docker Container

In this guide, we explore different ways to set up a MySQL database with a specific schema in a Docker container. This is important for developers and database admins. It helps us work better, keep things the same across different setups, and automate how we set up databases. We discuss many solutions. These include using Docker Compose and running SQL scripts. We also share best practices to make our Docker experience better.

Here are the solutions we will look at closely:

  • Solution 1 - Using Docker Compose with Initialization Scripts
  • Solution 2 - Building a Custom Docker Image with SQL Scripts
  • Solution 3 - Using Docker Volumes for Persistent Schema Initialization
  • Solution 4 - Executing SQL Scripts with Docker Exec Command
  • Solution 5 - Using Environment Variables for Database Initialization
  • Solution 6 - Automating Schema Migration with Docker and MySQL

At the end of this chapter, we will understand how to set up a MySQL database in a Docker container. This will make sure our environment is ready for development or production.

For more insights on Docker, we can check our guide on how to manage Docker containers effectively and learn about using environment variables in Docker.

Solution 1 - Using Docker Compose with Initialization Scripts

We can initialize a MySQL database with a schema in a Docker container by using Docker Compose. MySQL has a built-in way to run initialization scripts. Let’s set it up step by step.

Step-by-Step Guide

  1. Create a Directory for Your Project
    First, we need to make a directory for our Docker Compose project:

    mkdir mysql-docker-init
    cd mysql-docker-init
  2. Create a MySQL Initialization Script
    Now, we will create a SQL script that has our schema. Let’s make a file called init.sql:

    -- init.sql
    CREATE DATABASE IF NOT EXISTS mydatabase;
    USE mydatabase;
    
    CREATE TABLE IF NOT EXISTS users (
        id INT AUTO_INCREMENT PRIMARY KEY,
        username VARCHAR(50) NOT NULL,
        password VARCHAR(50) NOT NULL
    );
  3. Create a Docker Compose File
    Next, we make a docker-compose.yml file to set up our services:

    version: "3.8"
    
    services:
      db:
        image: mysql:latest
        environment:
          MYSQL_ROOT_PASSWORD: rootpassword
          MYSQL_DATABASE: mydatabase
        volumes:
          - ./init.sql:/docker-entrypoint-initdb.d/init.sql
        ports:
          - "3306:3306"
    • The MYSQL_ROOT_PASSWORD sets the root password for MySQL.
    • The MYSQL_DATABASE makes a default database.
    • The volume connects the init.sql script to the /docker-entrypoint-initdb.d/ folder in the container. MySQL will run any scripts in this folder when it starts up.
  4. Start the Docker Container
    We run this command to start our MySQL container:

    docker-compose up

    This command will download the MySQL image if we don’t have it already. It will also set up the database with the schema in our init.sql file.

  5. Access MySQL
    When the containers are running, we can access the MySQL database by using:

    docker exec -it mysql-docker-init_db_1 mysql -u root -p

    We enter the rootpassword when asked. Now we can query our database and check if the schema is set up right.

Additional Notes

  • The initialization scripts can be in .sql, .sh, or .sql.gz formats. They will run in alphabetical order.
  • We should make sure our docker-compose.yml file and any SQL scripts are saved in the same directory before we run the docker-compose up command.

By using Docker Compose with initialization scripts, we can easily set up our MySQL database schema. For more info on managing multiple Docker containers, check this Docker Compose documentation.

Solution 2 - Building a Custom Docker Image with SQL Scripts

We can set up a MySQL database in a Docker container with a specific schema. To do this, we will create a custom Docker image that has our SQL scripts. This way, we can have a setup that is easy to move and repeat.

Step-by-Step Guide

  1. Create a Directory for Your Project: First, we need to make a new directory for our Docker project. This is where we will keep our Dockerfile and SQL scripts.

    mkdir mysql-docker-init
    cd mysql-docker-init
  2. Create Your SQL Script: Next, we will create a SQL file that has our schema. Let’s make a file called init.sql:

    -- init.sql
    CREATE DATABASE IF NOT EXISTS mydb;
    USE mydb;
    
    CREATE TABLE IF NOT EXISTS users (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(255) NOT NULL,
        email VARCHAR(255) NOT NULL UNIQUE
    );
  3. Create a Dockerfile: In the same directory, we will create a Dockerfile. This file tells how to build our custom image.

    # Dockerfile
    FROM mysql:latest
    
    ENV MYSQL_ROOT_PASSWORD=rootpassword
    ENV MYSQL_DATABASE=mydb
    
    COPY init.sql /docker-entrypoint-initdb.d/

    In this Dockerfile:

    • We use the official MySQL image as the base.
    • We set the MYSQL_ROOT_PASSWORD and MYSQL_DATABASE environment variables.
    • We copy the init.sql script to the /docker-entrypoint-initdb.d/ directory. MySQL checks this directory for scripts to run at the start.
  4. Build the Docker Image: Now, we open a terminal in the folder where our Dockerfile is and run this command to build our custom MySQL image:

    docker build -t custom-mysql .
  5. Run the Docker Container: After we build the image, we can create and start a MySQL container from our custom image:

    docker run --name=mysql-container -d custom-mysql

    Here, mysql-container is the name of our container. The -d flag makes it run in the background.

  6. Verify the Initialization: To check that our database and tables are created, we connect to our MySQL container with this command:

    docker exec -it mysql-container mysql -u root -p

    After we enter our password (rootpassword), we can see the database and tables:

    SHOW DATABASES;
    USE mydb;
    SHOW TABLES;

Advantages of This Approach

  • Reproducibility: We can easily make this setup on different machines or places.
  • Portability: We can share the custom image through Docker Hub or any other registry.
  • Automation: The scripts to set up will run by themselves every time we create a new container from our custom image.

By following these steps, we can build a custom Docker image that sets up a MySQL database with the schema we want using SQL scripts. If we want to learn more about Docker container management, we can check this article.

Solution 3 - Using Docker Volumes for Persistent Schema Initialization

We can use Docker volumes for persistent schema initialization in a MySQL database container. This helps us keep our database schema even when the container restarts or updates. This way, we use Docker’s volume management to save and access our schema files easily.

Steps to Use Docker Volumes for Schema Initialization

  1. Create a Docker Volume:
    First, we need to create a Docker volume. This is where we will store our SQL schema files. We will mount this volume to the MySQL container.

    docker volume create mysql-data
  2. Prepare Your SQL Schema File:
    Next, we create an SQL file. We can name it init.sql. This file will have the SQL commands to set up our database schema. For example:

    CREATE DATABASE IF NOT EXISTS my_database;
    USE my_database;
    CREATE TABLE IF NOT EXISTS users (
        id INT AUTO_INCREMENT PRIMARY KEY,
        name VARCHAR(100),
        email VARCHAR(100) UNIQUE
    );
  3. Mount the Volume to the MySQL Container:
    When we run the MySQL container, we need to mount the Docker volume to the right directory. The /docker-entrypoint-initdb.d directory is used by MySQL to run any scripts when it starts for the first time.

    Here is how we start the MySQL container with the volume:

    docker run --name my-mysql \
      -e MYSQL_ROOT_PASSWORD=my-secret-pw \
      -e MYSQL_DATABASE=my_database \
      -v mysql-data:/var/lib/mysql \
      -v $(pwd)/init.sql:/docker-entrypoint-initdb.d/init.sql \
      -p 3306:3306 \
      -d mysql:latest

    In this command:

    • -v mysql-data:/var/lib/mysql: This mounts the volume for saving data.
    • -v $(pwd)/init.sql:/docker-entrypoint-initdb.d/init.sql: This mounts the init.sql file to the right directory.
  4. Verify the Database Initialization:
    After the container starts, we can check if our database and schema were created. We can connect to the MySQL container:

    docker exec -it my-mysql mysql -u root -p

    We enter the password when asked (my-secret-pw) and then list the databases:

    SHOW DATABASES;

    We should see my_database listed. We can also check if the users table was made:

    USE my_database;
    SHOW TABLES;

Notes:

  • The SQL scripts in /docker-entrypoint-initdb.d/ run only if the MySQL data folder is empty. If we restart the container without removing the volume, the scripts will not run again.
  • To learn more about managing Docker volumes, we can see this guide on Docker Volumes.
  • For more details on successful MySQL container initialization, we can check the MySQL Docker Documentation.

This way helps us manage our MySQL schema and data persistence using Docker volumes. It makes our database management better within Docker containers.

Solution 4 - Executing SQL Scripts with Docker Exec Command

We can use the docker exec command to set up a MySQL database with a schema from SQL scripts in a running Docker container. This way, we can run SQL commands inside the MySQL container. This method is good for executing scripts when the container is already running.

Steps to Execute SQL Scripts with Docker Exec

  1. Make Sure Your MySQL Container is Running: First, we need to check if our MySQL Docker container is running. We can see the status of our containers with this command:

    docker ps
  2. Copy SQL Script into the Container (if needed): If our SQL script is on the host machine, we might want to copy it into the container. We can do this with the docker cp command:

    docker cp /path/to/your/script.sql <container_id>:/tmp/script.sql

    Here, we need to change /path/to/your/script.sql to the path of our SQL file on the host. Also, we put <container_id> with the real ID or name of our MySQL container.

  3. Run the SQL Script: After the script is in the container, we can run it using the MySQL command line inside the container. We use the docker exec command like this:

    docker exec -i <container_id> mysql -u <username> -p<password> <database_name> < /tmp/script.sql
    • <container_id>: This is the ID or name of our MySQL container.
    • <username>: This is the MySQL username (like root).
    • <password>: This is the password for the MySQL user (no space between -p and the password).
    • <database_name>: This is the name of the database where we want to use the schema.

Example

If we have a MySQL container named mysql-container, a user root, a password password, and a database called mydatabase, the command would be:

docker exec -i mysql-container mysql -u root -ppassword mydatabase < /tmp/script.sql

Notes

  • Check Permissions: The user we use (<username>) must have the right permissions to run the SQL script on the chosen database.
  • Environment Variables: If we set environment variables for MySQL when we created the container (like MYSQL_ROOT_PASSWORD), we need to use the correct credentials.
  • Running Multiple Scripts: If we have many scripts to run, we can run the command for each script one by one. Or, we can combine them into one script and run that.

Using the docker exec command is a good way to manage MySQL database setup in Docker. For more details on managing Docker containers, we can check out how to keep a container running.

Solution 5 - Using Environment Variables for Database Initialization

One good way to start a MySQL database in a Docker container is by using environment variables. MySQL Docker images let us set up the database settings right through environment variables when we start the container. This includes setting the database name, user, and password. These are very important for a successful setup.

Step-by-step Guide

  1. Create a Docker Compose File: We need to create a docker-compose.yml file to define our MySQL service. This makes it easier to manage environment variables and other settings.

    version: "3.8"
    
    services:
      mysql:
        image: mysql:latest
        restart: always
        environment:
          MYSQL_ROOT_PASSWORD: root_password
          MYSQL_DATABASE: my_database
          MYSQL_USER: my_user
          MYSQL_PASSWORD: user_password
        ports:
          - "3306:3306"
        volumes:
          - mysql_data:/var/lib/mysql
    
    volumes:
      mysql_data:

    In this setup:

    • MYSQL_ROOT_PASSWORD sets the root password for MySQL.
    • MYSQL_DATABASE creates a new database called my_database.
    • MYSQL_USER and MYSQL_PASSWORD create a new user with the given details.
  2. Start the Container: We run this command in the terminal to start the MySQL service from our Docker Compose file:

    docker-compose up -d

    This command will run the MySQL container in the background.

  3. Verify Initialization: After the container is running, we can check the setup by connecting to the MySQL database. Use this command to access the MySQL command line:

    docker exec -it <container_name> mysql -u my_user -p

    Replace <container_name> with the name of our MySQL container. We can find this name using docker ps. When it asks for a password, we enter user_password to log in.

  4. Access with Environment Variables: If we want to change the environment variables while running, we can define them in our Docker command:

    docker run -d \
      -e MYSQL_ROOT_PASSWORD=root_password \
      -e MYSQL_DATABASE=my_database \
      -e MYSQL_USER=my_user \
      -e MYSQL_PASSWORD=user_password \
      -p 3306:3306 \
      --name my_mysql_container \
      mysql:latest

    This command creates a new container with the environment variables we set, starting the MySQL database as we need.

Notes

  • We should use strong passwords for production to keep it safe.
  • We can find more info about using environment variables for MySQL with Docker here.
  • For more complicated setups, we can use .env files to manage environment variables better. This helps avoid putting sensitive info directly in the code.

Using environment variables for database setup in a Docker container makes the process easier and more flexible. Many developers prefer this method.

Solution 6 - Automating Schema Migration with Docker and MySQL

We can automate schema migration in a Docker setup with MySQL. This helps us apply database changes easily in different environments. We will use tools like Flyway or Liquibase. These can fit well into our Docker workflow.

Using Flyway for Automated Schema Migration

Flyway is a well-known tool for database migration. It helps us control our database schema changes. Let’s see how to set it up in a Docker container with MySQL.

  1. Create a Docker Compose File: First, we need to make a docker-compose.yml file. This file will define the MySQL service and the Flyway service.

    version: "3.8"
    
    services:
      mysql:
        image: mysql:latest
        environment:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: mydb
        ports:
          - "3306:3306"
        volumes:
          - mysql-data:/var/lib/mysql
    
      flyway:
        image: flyway/flyway:latest
        environment:
          FLYWAY_URL: jdbc:mysql://mysql:3306/mydb
          FLYWAY_USER: root
          FLYWAY_PASSWORD: root
        volumes:
          - ./sql/migrations:/flyway/sql
        depends_on:
          - mysql
    
    volumes:
      mysql-data:
  2. Create Migration Scripts: Next, we create a folder called sql/migrations. This folder is where we will put our SQL migration scripts. The filenames need to follow Flyway’s naming rules, like V1__Create_users_table.sql.

    Example migration script (V1__Create_users_table.sql):

    CREATE TABLE users (
        id INT AUTO_INCREMENT PRIMARY KEY,
        username VARCHAR(50) NOT NULL,
        password VARCHAR(50) NOT NULL
    );
  3. Run the Services: Now we can start the Docker containers with Docker Compose. This command will set up MySQL and run the Flyway migrations.

    docker-compose up

    Flyway connects to the MySQL database and applies the migrations. We will see messages in the Flyway container logs showing that the migrations worked.

  4. Verify the Migration: After the services are running, we can check the MySQL database. We want to make sure that the schema is created right. We can connect to the MySQL container with this command:

    docker exec -it <mysql_container_id> mysql -u root -p

    Then we run:

    USE mydb;
    SHOW TABLES;

Using Liquibase for Schema Migration

We can use Liquibase for similar tasks. Here is how to set it up quickly.

  1. Docker Compose Configuration: We update our docker-compose.yml file to add Liquibase.

    version: "3.8"
    
    services:
      mysql:
        image: mysql:latest
        environment:
          MYSQL_ROOT_PASSWORD: root
          MYSQL_DATABASE: mydb
        ports:
          - "3306:3306"
        volumes:
          - mysql-data:/var/lib/mysql
    
      liquibase:
        image: liquibase/liquibase:latest
        environment:
          LIQUIBASE_URL: jdbc:mysql://mysql:3306/mydb
          LIQUIBASE_USER: root
          LIQUIBASE_PASSWORD: root
        volumes:
          - ./liquibase:/liquibase/changelog
        command: "--changeLogFile=/liquibase/changelog/db.changelog-master.xml update"
    
    volumes:
      mysql-data:
  2. Create ChangeLog File: We need a liquibase folder. Inside this folder, we create a db.changelog-master.xml file. This file will hold our changes.

    Example db.changelog-master.xml:

    <?xml version="1.0" encoding="UTF-8"?>
    <databaseChangeLog
        xmlns="http://www.liquibase.org/xml/ns/dbchangelog"
        xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://www.liquibase.org/xml/ns/dbchangelog
            http://www.liquibase.org/xml/ns/dbchangelog/dbchangelog-3.8.xsd">
    
        <changeSet id="1" author="yourname">
            <createTable tableName="users">
                <column name="id" type="int">
                    <autoIncrement/>
                    <constraints primaryKey="true"/>
                </column>
                <column name="username" type="varchar(50)">
                    <constraints nullable="false"/>
                </column>
                <column name="password" type="varchar(50)">
                    <constraints nullable="false"/>
                </column>
            </createTable>
        </changeSet>
    </databaseChangeLog>
  3. Run the Services: We can start the Docker containers again with:

    docker-compose up

This setup makes sure that our MySQL database schema migrates automatically when we run our Docker containers. This helps us have a smooth development process. For more details on managing migrations with Docker and MySQL, we can look at resources like this article on Docker Compose or this guide on environment variables.

Conclusion

In this article, we looked at different ways to set up a MySQL database with its schema in a Docker container. We talked about using Docker Compose, custom images and environment variables. These options help us to make the database setup easier. It also helps us to manage our MySQL instances better.

For more tips on Docker configurations, we can check out our guides on using environment variables and Docker volumes.

Comments