Severalnines Blog
The automation and management blog for open source databases

How to Deploy MariaDB Server to a Docker Container

Sebastian Insausti

Nowadays, terms like Docker, Images or Containers are pretty common in all database environments, so it’s normal to see a MariaDB server running on Docker in both production and non-production setups. It is possible, however, that while you may have heard the terms, you might now know the differences between them. In this blog, we provide an overview of these terms and how we can apply them in practice to deploy a MariaDB server.

What is Docker?

Docker is the most common tool to create, deploy, and run applications by using containers. It allows you to package up an application with all of the parts it needs (such as libraries and other dependencies) and ship it all out as one package, allowing for the portable sharing of containers across different machines.

Container vs Virtual Machine
Container vs Virtual Machine

What is an Image?

An Image is like a virtual machine template. It has all the required information to run the container. This includes the operating system, software packages, drivers, configuration files, and helper scripts… all packed into one bundle.

A Docker image can be built by anyone who has the ability to write a script. That is why there are many similar images being built by the community, each with minor differences...but serving a common purpose.

What is a Docker Container?

A Docker Container is an instance of a Docker Image. It runs completely isolated from the host environment by default, only accessing host files and ports if configured to do so.

A container could be considered as a virtual machine, but instead of creating a whole virtual operating system, it allows applications to use the same Linux kernel as the system that they're running on. It only requires applications to be shipped with parts not already running on the host computer. This gives you a significant performance boost and reduces the size of the application.

Keep in mind that any changes made to the container are recorded on a separate layer, not in the same Docker Image. This means if you delete the container, or if you create a new one based on the same Docker Image, the changes won’t be there. To preserve the changes you must commit it into a new Docker Image or create a Docker File.

What is a DockerFile?

A DockerFile is a script used to generate a Docker Image where you have the steps to generate it based on any modifications that you want to apply.

Docker Components
Docker Components

Let’s see a Docker File example.

$ vi Dockerfile
# MariaDB 10.3 with SSH
# Pull the mariadb latest image
FROM mariadb:latest
# List all the packages that we want to install
ENV PACKAGES openssh-server openssh-client
# Install Packages
RUN apt-get update && apt-get install -y $PACKAGES
# Allow SSH Root Login
RUN sed -i 's|^#PermitRootLogin.*|PermitRootLogin yes|g' /etc/ssh/sshd_config
# Configure root password
RUN echo "root:root123" | chpasswd

Now, we can build a new Docker Image from this Docker File:

$ docker build --rm=true -t severalnines/mariadb-ssh .

Check the new image created:

$ docker images
REPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZE
severalnines/mariadb-ssh                   latest              a8022951f195        17 seconds ago      485MB

And now, we can use the new image as a common Docker Image as we’ll see in the next section.

Severalnines
 
DevOps Guide to Database Management
Learn about what you need to know to automate and manage your open source databases

How to Deploy MariaDB on Docker Without Dockerfile

Now that we know more about the Docker world, let’s see how to use it to create a MariaDB server. For this, we’ll assume you already have Docker installed.

We can use the image created by using the Dockerfile, but we’ll pull the official MariaDB Docker Image.

$ docker search mariadb
NAME                                   DESCRIPTION                                     STARS               OFFICIAL            AUTOMATED
mariadb                                MariaDB is a community-developed fork of MyS…   2804                [OK]

Without specifying a TAG, by default, it’ll pull the latest image version, in this case, MariaDB Server 10.3 on Ubuntu 18.04.

$ docker pull mariadb

We can check the image downloaded.

$ docker images
REPOSITORY                                 TAG                 IMAGE ID            CREATED             SIZE
mariadb                                    latest              e07bb20373d8        2 weeks ago         349MB

Then, we’ll create two directories under our MariaDB Docker directory, one for the datadir and another one for the MariaDB configuration files. We’ll add both on our MariaDB Docker Container.

$ cd ~/Docker
$ mkdir datadir
$ mkdir config

The startup configuration is specified in the file /etc/mysql/my.cnf, and it includes any files found in the /etc/mysql/conf.d directory that end with .cnf.

$ tail -1 /etc/mysql/my.cnf
!includedir /etc/mysql/conf.d/

The content of these files will override any repeated parameter configured in /etc/mysql/my.cnf, so you can create an alternative configuration here.

Let’s run our first MariaDB Docker Container:

$ docker run -d --name mariadb1 \
-p 33061:3306 \
-v ~/Docker/mariadb1/config:/etc/mysql/conf.d \
-v ~/Docker/mariadb1/datadir:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=root123 \
-e MYSQL_DATABASE=dbtest \
mariadb

After this, we can check our containers running:

$ docker ps
CONTAINER ID        IMAGE               COMMAND                  CREATED              STATUS              PORTS                     NAMES
12805cc2d7b5        mariadb             "docker-entrypoint.s…"   About a minute ago   Up About a minute   0.0.0.0:33061->3306/tcp   mariadb1

The container log:

$ docker logs mariadb1
MySQL init process done. Ready for start up.
2019-06-03 23:18:01 0 [Note] mysqld (mysqld 10.3.15-MariaDB-1:10.3.15+maria~bionic) starting as process 1 ...
2019-06-03 23:18:01 0 [Note] InnoDB: Using Linux native AIO
2019-06-03 23:18:01 0 [Note] InnoDB: Mutexes and rw_locks use GCC atomic builtins
2019-06-03 23:18:01 0 [Note] InnoDB: Uses event mutexes
2019-06-03 23:18:01 0 [Note] InnoDB: Compressed tables use zlib 1.2.11
2019-06-03 23:18:01 0 [Note] InnoDB: Number of pools: 1
2019-06-03 23:18:01 0 [Note] InnoDB: Using SSE2 crc32 instructions
2019-06-03 23:18:01 0 [Note] InnoDB: Initializing buffer pool, total size = 256M, instances = 1, chunk size = 128M
2019-06-03 23:18:01 0 [Note] InnoDB: Completed initialization of buffer pool
2019-06-03 23:18:01 0 [Note] InnoDB: If the mysqld execution user is authorized, page cleaner thread priority can be changed. See the man page of setpriority().
2019-06-03 23:18:01 0 [Note] InnoDB: 128 out of 128 rollback segments are active.
2019-06-03 23:18:01 0 [Note] InnoDB: Creating shared tablespace for temporary tables
2019-06-03 23:18:01 0 [Note] InnoDB: Setting file './ibtmp1' size to 12 MB. Physically writing the file full; Please wait ...
2019-06-03 23:18:02 0 [Note] InnoDB: File './ibtmp1' size is now 12 MB.
2019-06-03 23:18:02 0 [Note] InnoDB: Waiting for purge to start
2019-06-03 23:18:02 0 [Note] InnoDB: 10.3.15 started; log sequence number 1630824; transaction id 21
2019-06-03 23:18:02 0 [Note] Plugin 'FEEDBACK' is disabled.
2019-06-03 23:18:02 0 [Note] InnoDB: Loading buffer pool(s) from /var/lib/mysql/ib_buffer_pool
2019-06-03 23:18:02 0 [Note] Server socket created on IP: '::'.
2019-06-03 23:18:02 0 [Note] InnoDB: Buffer pool(s) load completed at 190603 23:18:02
2019-06-03 23:18:02 0 [Note] Reading of all Master_info entries succeded
2019-06-03 23:18:02 0 [Note] Added new Master_info '' to hash table
2019-06-03 23:18:02 0 [Note] mysqld: ready for connections.
Version: '10.3.15-MariaDB-1:10.3.15+maria~bionic'  socket: '/var/run/mysqld/mysqld.sock'  port: 3306  mariadb.org binary distribution

And the content of our Docker datadir path (host):

$ ls -l ~/Docker/mariadb1/datadir/
total 249664
-rw-rw----   1 sinsausti  staff     16384 Jun  3 20:18 aria_log.00000001
-rw-rw----   1 sinsausti  staff        52 Jun  3 20:18 aria_log_control
drwx------   3 sinsausti  staff        96 Jun  3 20:18 dbtest
-rw-rw----   1 sinsausti  staff       976 Jun  3 20:18 ib_buffer_pool
-rw-rw----   1 sinsausti  staff  50331648 Jun  3 20:18 ib_logfile0
-rw-rw----   1 sinsausti  staff  50331648 Jun  3 20:17 ib_logfile1
-rw-rw----   1 sinsausti  staff  12582912 Jun  3 20:18 ibdata1
-rw-rw----   1 sinsausti  staff  12582912 Jun  3 20:18 ibtmp1
-rw-rw----   1 sinsausti  staff         0 Jun  3 20:17 multi-master.info
drwx------  92 sinsausti  staff      2944 Jun  3 20:18 mysql
drwx------   3 sinsausti  staff        96 Jun  3 20:17 performance_schema
-rw-rw----   1 sinsausti  staff     24576 Jun  3 20:18 tc.log

We can access the MariaDB container running the following command and using the password specified in the MYSQL_ROOT_PASSWORD variable:

$ docker exec -it mariadb1 bash
root@12805cc2d7b5:/# mysql -p -e "SHOW DATABASES;"
Enter password:
+--------------------+
| Database           |
+--------------------+
| dbtest             |
| information_schema |
| mysql              |
| performance_schema |
+--------------------+

Here we can see our dbtest created.

Docker Commands

Finally, let’s see some useful commands for managing Docker.

  • Image search
    $ docker search Image_Name
  • Image download
    $ docker pull Image_Name
  • List the images installed
    $ docker images
  • List containers (adding the flag -a we can see also the stopped containers)
    $ docker ps -a
  • Delete a Docker Image
    $ docker rmi Image_Name
  • Delete a Docker Container (the container must be stopped)
    $ docker rm Container_Name
  • Run a container from a Docker Image (adding the flag -p we can mapping a container port to localhost)
    $ docker run -d --name Container_Name -p Host_Port:Guest_Port Image_Name
  • Stop container
    $ docker stop Container_Name
  • Start container
    $ docker start Container_Name
  • Check container logs
    $ docker logs Container_Name
  • Check container information
    $ docker inspect Container_Name
  • Create a container linked
    $ docker run -d --name Container_Name --link Container_Name:Image_Name Image_Name
  • Connect to a container from localhost
    $ docker exec -it Container_Name bash
  • Create a container with volume added
    $ docker run -d --name Container_Name --volume=/home/docker/Container_Name/conf.d:/etc/mysql/conf.d Image_Name
  • Commit changes to a new image
    $ docker commit Container_ID Image_Name:TAG

Conclusion

Docker is a really useful tool for sharing a development environment easily using a Dockerfile or publishing a Docker Image. By using it you can make sure that everyone is using the same environment. At the same time it’s also useful to recreate or clone an existing environment. Docker can share volumes, use private networks, map ports, and even more.

In this blog, we saw how to deploy MariaDB Server on Docker as a standalone server. If you want to use a more complex environment like Replication or Galera Cluster, you can use bitnami/mariadb to achieve this configuration.