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:
- My sources of the Docker image on GitHub.
- The original Docker files mysql/mysql-docker @ GitHub.
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:
- MySQL 5.7 docker image documentation on hub.docker.com
- Deploying MySQL 5.7 on Linux with Docker on dev.mysql.com
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.