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
- Dockerizing MariaDB with Alpine Linux (You are here)
- Import and Export data in Dockerized MariaDB
- 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 oftrap
we specify thesignal_terminate_trap
function and in the second param we specify the termination signal (SIGTERM
).
- This command helps us to catch the terminate signal (
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.
- When we start our Docker container, we pass an environment variable to the container and we call it
--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 like3306
. Unix sockets are only available for processes inside our Linux machine.
- In this tutorial series we will connect to MariaDB via Unix socket. The common way for connecting to a database is TCP connection (
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.
- Documents link:
- SIGTERM signal
- Docker container stop
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 yourMariaDB
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 theREQUEST
environment variable in theif [ "$REQUEST" == "initialize" ]
line ofmain.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.