How To Run MySQL and PhpMyAdmin locally with Docker

Updated December 2018

Note: This write-up is intended for personal use, so I won't address issues of password and user security right now.

In this write-up I'll show you how to setup a local MySQL/MariaDB container with a PhpMyAdmin administrative interface. We will store the database on the host file system, so it will persist across sessions. I'll show you how to connect to an arbitrary MySQL/MariaDB container.

To start, pull the mysql image from Docker Hub. I used version 5.7.24.

docker pull mysql:5.7.24

Then pull the latest PhpMyAdmin image.

docker pull phpmyadmin/phpmyadmin

Next, we'll create a network that the two containers will share.

docker network create mysql-network

Since --link is depreciated we'll be using the new --net option in conjunction with the docker network we created.

Now we'll start both containers with the appropriate environment variables and command line options.

# Start MySQL
docker run --name a-mysql \
           --net=mysql-network \
           -p 3306:3306 \
           -e MYSQL_ROOT_PASSWORD=password \
           -v $(pwd)/database:/var/lib/mysql \
           -d mysql:5.7.24  > /dev/null

This is basically saying, "start a detached container named 'a-mysql', use the 'mysql-network', put the database in 'database' folder, and map port 3306 on the host machine to 3306 in the container." Then start PhpMyAdmin...

docker run --name a-mysql-admin \
           --net=mysql-network \
           -e MYSQL_ROOT_PASSWORD=password \
           -e PMA_HOST="a-mysql" \
           -e PMA_PORT=3306 \
           -p 8080:80 \
           -d phpmyadmin/phpmyadmin

If everything worked correctly, you should see the two running containers when you run docker ps, and you can access PhpMyAdmin at http://localhost:8080/. Log in using the username "root" and the password "password".

If you don't want to specify the environment variables on the command line, you can create an environment variable file and tell docker to use that instead, e.g. create the file sqlcredentials.list with the following content.

MYSQL_ROOT_PASSWORD=password
PMA_HOST=a-mysql
PMA_PORT=3306

And then you can use docker's --env-file flag to tell it to use sqlcredentials.list.

Connecting to Any SQL Server

The PhpMyAdmin container will let you connect to any SQL Server if you set environment variable PMA_ARBITRARY=1. Then when you visit the PhpMyAdmin front-end, it will ask you to enter the server ip, mysql username, and mysql password. You can find the IP address of a container by using docker inspect. If your container uses the host system's bridge network, you should be able to run this command to see what the container's IP is.

docker inspect --format '{{.NetworkSettings.Networks.bridge.IPAddress}}' a-mysql

If you're using a custom network, something like this might work.

docker inspect --format '{{ index .NetworkSettings.Networks "mysql-network" "IPAddress"}}' a-mysql

Tips for Debugging

In this tutorial I used Docker version 18.09.0, build 4d60db4 on Ubuntu Linux.

View Running Containers

docker ps

Get IP Address of Container

docker inspect --format '{{ .NetworkSettings.IPAddress }}' containername

Run an Interactive Shell in Container

docker exec -it containername /bin/bash

docker exec -it containername /bin/sh

Testing The MySQL Connection From The Host

Provided you have mysql installed, you can run mysql -uroot -h"localhost" -P"3306" -p"password" from the host to see if the mysql container is accepting connections.

Testing The MySQL Connection From Inside PhpMyAdmin Container

To test if the PhpMyAdmin Container can access mysql, you can create a interactive shell process in the PhpMyAdmin container...

# On the Host...
docker exec -it a-mysql-admin /bin/sh

# From inside the container test the
# mysql connection with php
php -r '$c = mysqli_connect("a-mysql", "root", "password", "", "3306"); if(!$c) {	echo "Cannot connect"; } else {	$result = $c->query("SELECT User from mysql.user"); print_r($result->fetch_all()); }'

You should see an array of users if the query executed successfully.

Array
(
    [0] => Array
        (
            [0] => root
        )

)