MySQL 5.7 Docker Container for Raspberry Pi using Debian Sid

Estimated reading time of this article: 6 minutes

How to run MySQL 5.7 on Raspberry Pi?
Can MySQL 5.7 be run in a Docker container on Raspberry Pi?
Which Distribution provides MySQL 5.7 on arm32v7/armel architecture?

I'm using a Raspberry Pi 3 for weekly database jobs. For compatibility with the rest of the project, I need a recent database, either MariaDB 10.2 or MySQL 5.7. However Raspian Jessie and Stretch do not provide these DB server versions.

People installed MySQL 5.7 on Raspian Jessie or Stretch using Debian Sid packages (Raspberry Pi: Installing MySQL 5.7 on Raspbian Jessie and Install Mysql 5.7 on raspbian jesse - pi 3). However, I don't want to risk breaking the current Raspbian setup.

A clean approach would be to use virtualization technology such as a Docker container. Luckily, Docker is supported on Raspberry Pi.

Docker Introduction

Docker allows to run isolated containers providing services.

A Docker image is "a saved Docker container" and it contains everything that is required to run it.

My approach is to create a Docker image for MySQL 5.7 and to run the Docker container on my Raspberry Pi.

Installation of Docker on Raspberry Pi

The installation of Docker on Raspbian is easy, see Get Started with Docker on Raspberry Pi for further information.

curl -sSL https://get.docker.com | sh

Create the Debian based MySQL 5.7 Docker image

There are MySQL 5.7 Docker images, but they are not compatible with Raspberry Pi since Raspbian uses the arm32v7/armel architecture.

However existing MySQL 5.7 Docker images can be used as reference. I used the official MySQL 5.7 Docker image of Oracle as template.

My research showed that currently only Debian Sid provides MySQL 5.7 among its databases.

Note: Debian Sid is the development version of Debian. Debian Sid is not stable nor officially supported. Security is not ensured. Please consider carefully when using such images.

I created the following Dockerfile.

Dockerfile

The Dockerfile:

# Build image cmd: docker build -t debian-mysql-server-5.7 .

FROM debian:sid-slim

# add our user and group first to make sure their IDs get assigned consistently, regardless of whatever dependencies get added
RUN groupadd -r mysql && useradd -r -g mysql mysql \
  \
  && echo "***** Init bash..." \
  && printf "\nalias ll='ls -l'\nalias l='ls -lA'\n" >> /root/.bashrc \
  # Map Ctrl-Up and Ctrl-Down to history based bash completion
  && printf '"\\e[1;5A": history-search-backward\n"\\e[1;5B": history-search-forward\n"\\e[1;5C": forward-word\n"\\e[1;5D": backward-word' > /etc/inputrc \
  \
  && echo "***** Install packages..." \
  && apt-get update \
  # Install apt-get allowing subsequent package configuration
  && DEBIAN_FRONTEND=noninteractive apt-get install -y apt-utils \
  # Install minimal admin utils
  && DEBIAN_FRONTEND=noninteractive apt-get install -y less nano procps \
  # Install MySQL server
  && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends libpwquality-tools mysql-server-5.7 \
  # Clean cache
  && rm -rf /var/lib/apt/lists/* \
  \
  && echo "***** Config mysql..." \
  && rm -rf /var/lib/mysql && mkdir -p /var/lib/mysql /var/run/mysqld \
  && touch /var/log/mysqld.log \
  && chown -R mysql:mysql /var/lib/mysql /var/run/mysqld /var/log/mysqld.log \
  # Ensure that /var/run/mysqld (used for socket and lock files) is writable regardless of the UID our mysqld instance ends up having at runtime
  && chmod 777 /var/run/mysqld \
  && chmod 775 /var/log \
  # Disable Debian MySQL config since it overwrites config from volume
  && mv /etc/mysql/mysql.conf.d/mysqld.cnf /etc/mysql/mysql.conf.d/mysqld.cnf.disabled \
  && mv /etc/mysql/conf.d/mysqldump.cnf /etc/mysql/conf.d/mysqldump.cnf.disabled \
  && mv /etc/mysql/conf.d/mysql.cnf /etc/mysql/conf.d/mysql.cnf.disabled \
  # Create placeholder for custom my.cnf
  && touch /etc/mysql/conf.d/my.cnf \
  # Set docker settings, these settings always win
  && printf '[client]\nsocket=/var/lib/mysql/mysql.sock\n\n[server]\nsocket=/var/lib/mysql/mysql.sock\ndatadir=/var/lib/mysql\nsecure-file-priv=/var/lib/mysql-files\nuser=mysql\nskip-host-cache\nskip-name-resolve\n' > /etc/mysql/mysql.conf.d/docker.cnf \
  \
  && mkdir /docker-entrypoint-initdb.d \
  && echo "***** RUN commands finished"

VOLUME /var/lib/mysql

COPY docker-entrypoint.sh /entrypoint.sh
COPY healthcheck.sh /healthcheck.sh
ENTRYPOINT ["/entrypoint.sh"]
HEALTHCHECK CMD /healthcheck.sh
EXPOSE 3306 33060
CMD ["mysqld"]

This Dockerfile adds an inputrc config file as I recommended in Bash history search: Partial + Ctrl-Up or Ctrl-Down.

Source code:

Build the Docker image

Building a Docker image is easy. Put the Dockerfile, docker-entrypoint.sh and healthcheck.sh in a directory and call docker build.

docker build -t debian-mysql-server-5.7 .
Argument Description
build Docker command that creates a docker image
-t debian-mysql-server-5.7 Name of the image to create

Check the images:

docker images

I uploaded my image to hub.docker.com.

Run the Docker container

The following command starts the MySQL docker container running the MySQL DB as daemon.

docker run --name mysql57 \
           -d \
           --restart unless-stopped \
           -p 127.0.0.1:3306:3306 \
           -p 127.0.0.1:33060:33060 \
           -v /path/to/mysql57/data:/var/lib/mysql \
           -v /path/to/mysql57/my.cnf:/etc/mysql/conf.d/my.cnf \
           -e MYSQL_ALLOW_EMPTY_PASSWORD=yes \
           debian-mysql-server-5.7

Explanation of the docker parameters:

Argument Description
run Docker command that creates and runs a docker container
--name mysql57 Name of the container to create
-d Runs the container as daemon in the background
--restart unless-stopped Autostarts this docker container with docker after startup
-p 127.0.0.1:3306:3306 Host IP and host port to use for the exposed ports of the container
-p 127.0.0.1:33060:33060 Host IP and host port to use for the exposed ports of the container
-v /path/to/mysql57/data:/var/lib/mysql Maps a directory of the host into the Docker container since we want to store the data outside the docker container; /var/lib/mysql is predefined by the Docker image
-v /path/to/mysql57/my.cnf:/etc/mysql/conf.d/my.cnf Maps a custom MySQL config file into the docker container; /etc/mysql/conf.d/my.cnf is predefined by the Docker image
-e MYSQL_ALLOW_EMPTY_PASSWORD=yes Allows to create MySQL instances with an empty root passwort
debian-mysql-server-5.7 The name of the image to use for the container

Check the container state

docker ps

Run a mysql inside the container

docker exec -it mysql57 mysql -uroot

Run a mysql outside the container

mysql -h 127.0.0.1 -uroot

More about MySQL and Docker can be found on:

localhost != 127.0.0.1 on Linux

localhost is not the same as 127.0.0.1 on Linux.

  • localhost may use sockets for communication and may ignore ports.
  • 127.0.0.1 uses the TCP/IP stack for communication and respects ports.

If you want to use localhost with PHP or with local MySQL clients, you have to set the socket file in php.ini or ~/.my.cnf.

~/.my.cnf:

[client]
socket=/path/to/mysql57/data/mysql.sock

php.ini:

[Pdo_mysql]
pdo_mysql.default_socket=/path/to/mysql57/data/mysql.sock

[MySQLi]
mysqli.default_socket =/path/to/mysql57/data/mysql.sock

Thus, it's better to use 127.0.0.1 when working with database containers.

Conclusion

It is quite easy and straight forward to create and run MySQL 5.7 database server in a Docker container on Raspberry Pi.

Unfortunately, Debian Sid is currently the only distribution providing MySQL 5.7 for the Raspberry Pi.