Get Rewarded! We will reward you with up to €50 credit on your account for every tutorial that you write and we publish!

Dockerizing MariaDB with Alpine Linux

profile picture
Author
Reza Gharabaghi
Published
2024-10-09
Time to read
9 minutes reading time

Introduction

The official MariaDB Docker image uses Red Hat Linux, which is large in size. In this tutorial you will see how to setup your database on Alpine Linux.

I use Alpine Linux as the base Docker image for most of my applications. Why? because Alpine is designed with security in mind. The C library used is musl and the base tools are all in BusyBox. Those are normally found in embedded systems and are smaller than the tools found in GNU/Linux systems.

Another great part of Alpine is their package manager called Alpine Package Keeper. For example, you can find and install most of the popular packages with the apk command. In this series I want to show you how to install MariaDB and import or export your database data with ease.

This tutorial is split into multiple parts.

Series index

  1. Dockerizing MariaDB with Alpine Linux (You are here)
  2. Import and Export data in Dockerized MariaDB
  3. Connect to Dockerized MariaDB with Node.js via Unix socket

Prerequisites

  • Server with Rocky Linux 9

Step 1 - Install Docker

First of all you have to install Docker on your VPS. I purchased a Rocky Linux 9 instance on Hetzner Cloud. If you have another Linux distribution, there are very straightforward steps on the official Docker website, which you can use.

# Update your instance
dnf -y update

# Install useful packages
dnf -y install \
    epel-release \
    bash-completion

# Reboot your Linux instance
reboot
# Add Docker repo
dnf config-manager \
    --add-repo \
    https://download.docker.com/linux/centos/docker-ce.repo

# Install Docker
dnf -y install \
    docker-ce \
    docker-ce-cli \
    containerd.io \
    docker-compose-plugin

# Enable and start Docker service
systemctl --now enable docker

Step 2 - Project structure

This is our project directory structure.

Directories are marked with / at the end of them.

maria/
│
├─── Dockerfile
├─── main.sh
│
├─── data/
├─── logs/
├─── socket/
├─── dump/
│    │
│    ├─── import/
│    └─── export/
│
└─── config/
     │
     ├─── my.cnf
     └─── my.cnf.d/
          │
          └─── mariadb-server.cnf
# Create project directory
mkdir /maria

# Change the current working directory to maria/
cd /maria

# Add the directories
mkdir -p data logs socket dump/import dump/export config/my.cnf.d

# Add the files
touch Dockerfile main.sh config/my.cnf config/my.cnf.d/mariadb-server.cnf

Step 3 - Build your image

After installing Docker, we have to create our Docker image. As you may know, Docker images are immutable, which means they can't be modified once created. For this reason, we should use Docker volumes. With volumes you are able to share files between your main Linux instance (Rocky Linux 9) and a Docker container.

This is our Dockerfile config file and instructions about how Docker should build the image.


Dockerfile

# Use Alpine as the base image
FROM alpine:3.20

# Copy the main shell script to image
COPY ["main.sh", "/usr/local/bin/"]

RUN \
    # Add MariaDB packages
    apk add --no-cache \
        mariadb \
        mariadb-client; \
    # Give execute permission to main.sh
    chmod +x /usr/local/bin/main.sh

# Specify the start point of our image
ENTRYPOINT ["main.sh"]

Step 4 - Shell script

So far you have done many steps, perfect.

It's time to write the most important part of your project. The main.sh is the controller and the start point of the project.

At this stage I show you how the bash script handles our MariaDB program. We need to start and stop MariaDB with that bash script.


main.sh

#!/bin/ash

set -e

signal_terminate_trap() {
    #
    # Shutdown MariaDB with mariadb-admin
    # https://mariadb.com/kb/en/mariadb-admin/
    mariadb-admin shutdown &
    #
    # Wait for mariadb-admin until sucessfully done (exit)
    wait $!
    echo "MariaDB shut down successfully"
}

trap "signal_terminate_trap" SIGTERM

# Run
if [ "$REQUEST" == "run" ]; then
    echo "Starting MariaDB ..."
    #
    # Run MariaDB with exec bash command
    exec mariadbd &
    #
    # Wait for MariaDB until stopped by Docker
    wait $!
    exit 1
fi

# Initialize
if [ "$REQUEST" == "initialize" ]; then
    initialize_status="MariaDB is already initialized"

    if [ ! -f "$DIR_DATA/ibdata1" ]; then
        initialize_status="MariaDB initialization done"

        # Initialize MariaDB with mariadb-install-db
        # https://mariadb.com/kb/en/mariadb-install-db/
        mariadb-install-db \
            --user=$USER \
            --datadir=$DIR_DATA \
            --auth-root-authentication-method=socket &
        #
        # Wait for mariadb-install-db until sucessfully done (exit)
        wait $!
    fi

    echo $initialize_status
fi
  • set -e command
    • Tell bash to exit the script if any command fails.
  • signal_terminate_trap function
    • Every bash script will exit eventually, whether our script is completely done or fails. We need to catch that exit and figure out why our script wants to exit.
  • trap command
    • This command helps us to catch the terminate signal (SIGTERM) of our process. In the first param of trap we specify the signal_terminate_trap function and in the second param we specify the termination signal (SIGTERM).
  • if statement
    • When we start our Docker container, we pass an environment variable to the container and we call it REQUEST. I will tell you more about this later.
  • --auth-root-authentication-method
    • In this tutorial series we will connect to MariaDB via Unix socket. The common way for connecting to a database is TCP connection (127.0.0.1:3306). Opening an extra port equals less security. Hackers try to connect to a database via open ports like 3306. Unix sockets are only available for processes inside our Linux machine.

SIGTERM important note: By default, Docker sends a SIGTERM signal to the main process of the container (main.sh) when you try to stop your container with the docker stop container_name command.



Now it's time to build the image.

# Build
docker build --rm -t maria:1.0.0 --file Dockerfile ./

# Check Docker images on your Linux machine
docker image list --all
  • I use --rm flag to clean up the temporary container and remove the filesystem after the build is complete.
  • Specify the name of your image and its version with -t.
  • Specify Dockerfile with --file flag.

Step 5 - MariaDB config files

Check the MariaDB official documents page.


config/my.cnf

[mysqld]
symbolic-links=0
!includedir /etc/my.cnf.d

config/my.cnf.d/mariadb-server.cnf

[client]
socket=/run/maria/maria.sock

[mysql]
default-character-set=utf8mb4

[mysqld]
pid-file=/run/maria/maria.pid
skip-networking

innodb_buffer_pool_size=64M
performance_schema=OFF

[mysqld_safe]
log_error=/var/log/maria/error_safe.log

[mariadbd]
user=mysql

datadir=/var/lib/maria/
socket=/run/maria/maria.sock

character_set_server=utf8mb4

log_output=FILE

general_log
general_log_file=/var/log/maria/general.log

slow_query_log
slow_query_log_file=/var/log/maria/slow.log
long_query_time=3

log_error=/var/log/maria/error.log
log_warnings=2

Step 6 - Initialize MariaDB

In this step we want to initialize our MariaDB for the first time. Remember, you should do this step only one time. After that, MariaDB will generate required files in the /maria/data/ directory inside the Rocky Linux 9 instance. These config files are required every time you want to run MariaDB.

To prevent permission errors, give the ownership of the data and socket directories to the mysql user.

# 100:101 -> equals to -> mysql:mysql in MariaDB container
chown -R 100:101 /maria/data/ /maria/socket/ /maria/dump/

It's time to initialize MariaDB with the docker run command.

# Initialize
docker run \
    --rm \
    --name maria_initialize \
    --user mysql \
    --env REQUEST=initialize \
    --env USER=mysql \
    --env DIR_DATA="/var/lib/maria" \
    -v /maria/config/my.cnf:/etc/my.cnf:ro \
    -v /maria/config/my.cnf.d/:/etc/my.cnf.d/:ro \
    -v /maria/data/:/var/lib/maria/ \
    maria:1.0.0
  • With the docker run command you are able to start your MariaDB container.
  • We are using the Docker volume feature with the -v flag. Check the official Docker docs here.
  • I define multiple environment variables which will pass to the container. One of them is --env REQUEST=initialize. Step back and take a look at the Shell script step and you will see we are using the REQUEST environment variable in the if [ "$REQUEST" == "initialize" ] line of main.sh.

Done, and now your Dockerized MariaDB is available.

Step 7 - Running MariaDB

And now, we want to run the MariaDB image in detach mode.

docker run \
    --detach \
    --name maria_detach \
    --restart always \
    --user mysql \
    --env REQUEST=run \
    -v /maria/config/my.cnf:/etc/my.cnf:ro \
    -v /maria/config/my.cnf.d/:/etc/my.cnf.d/:ro \
    -v /maria/data/:/var/lib/maria/ \
    -v /maria/logs/:/var/log/maria/ \
    -v /maria/socket/:/run/maria/ \
    maria:1.0.0

If you want to check the status of your container, you should use docker ps -a command and you will see something like this in your terminal:

CONTAINER ID   IMAGE          COMMAND      CREATED           STATUS          PORTS      NAMES
f0a2ac1365b7   maria:1.0.0    "main.sh"    5 minutes ago     Up 5 seconds               maria_detach

In order to stop your container, use the docker stop maria_detach command.


Go ahead and read the second tutorial and see how to import your database data into the MariaDB container.

If you don't have any SQL data and want to connect to your MariaDB via Unix socket, go to the third tutorial and see how to do it with Node.js.

Conclusion

In this tutorial you've learned how to Dockerize MariaDB on Alpine Linux and manage the Docker process with bash script.

License: MIT
Want to contribute?

Get Rewarded: Get up to €50 in credit! Be a part of the community and contribute. Do it for the money. Do it for the bragging rights. And do it to teach others!

Report Issue

Discover our

Dedicated Servers

Configure your dream server. Top performance with an excellent connection at an unbeatable price!

Want to contribute?

Get Rewarded: Get up to €50 credit on your account for every tutorial you write and we publish!

Find out more