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.
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.
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.
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.
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
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.