PHP and MySQL Docker Image

The versioning, extensions, and settings for PHP systems can be difficult to keep consistent across multiple development environments....

a year ago

Latest Post Automatic Offline Backup With a Raspberry Pi by Tyler Moon

There can be a need from time to time to develop PHP code with a MySQL database. The versioning, extensions, and settings for PHP systems can be difficult to keep consistent across multiple development environments. This is a good use case for Docker containerization. In this article we will go through a very simple setup for installing specific PHP versions and MySQL version in a Docker container.

Prerequisites

Setup

First thing we need to do is create the needed files. For this simple example we are just going to use three files. A Dockerfile that defines how to build the Docker container, and two utility shell scripts.

touch Dockerfile dockerip.sh start.sh index.php

Dockerfile

A Dockerfile defines the base image and build instructions for a Docker container. Copy the following code into the Dockerfile:

# Dockerfile
# Use the PHP image based off Alpine Linux
FROM php:5.6.38-alpine

# Setup some environment variables
# PHP Variables
ENV APP_DIR /approved
ENV APPLICATION_ENV development
# MySQL Variables
ENV TIMEZONE Europe/Paris
ENV MYSQL_ROOT_PASSWORD newpassword
ENV MYSQL_DATABASE FaithfulScholars
ENV MYSQL_USER root
ENV MYSQL_PASSWORD newpassword
ENV MYSQL_USER_MONITORING monitoring
ENV MYSQL_PASSWORD_MONITORING monitoring

# Create app directory for the PHP code
RUN mkdir $APP_DIR
WORKDIR $APP_DIR
VOLUME $APP_DIR

# Install php composer to setup additional php components
RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');    \
    \$sig = file_get_contents('https://composer.github.io/installer.sig');      \
    if (trim(\$sig) === hash_file('SHA384', 'composer-setup.php')) exit(0);     \
    echo 'ERROR: Invalid installer signature' . PHP_EOL;                        \
    unlink('composer-setup.php');                                               \
    exit(1);"                                                                   \
 && php composer-setup.php -- --filename=composer --install-dir=/usr/local/bin  \
 && rm composer-setup.php

# Install MySQL using Alpines APK package manager
RUN apk add --no-cache mysql
RUN addgroup mysql mysql

# Setup the MySQL startup script
WORKDIR /scripts

COPY start.sh start.sh

# Volume to persist MySQL data
VOLUME [ "/var/lib/mysql" ]

# Export port 80 to view php app
EXPOSE 80

# Run the php servlet on port 80
CMD ["php", "-S", "0.0.0.0:80", "-t", "/app/public"]

This code uses PHP 5.6 but if you want a different version of PHP replace the FROM php:5.6.38-alpine line with another version found here.

Note: If you choose an image not based off Alpine Linux the MySQL install commands may differ

For more information on the syntax of the Dockerfile check out the very useful documentation site here.

Shell Scripts

Now that we have our Docker container specified we need to fill out the shell scripts. The first script start.sh is some code to initialize MySQL and start the MySQL daemon.

# start.sh
#!/bin/sh

if [ ! -d "/run/mysqld" ]; then
	mkdir -p /run/mysqld
	chown -R mysql:mysql /run/mysqld
fi

if [ -d /var/lib/mysql/mysql ]; then
	echo '[i] MySQL directory already present, skipping creation'
else
	echo "[i] MySQL data directory not found, creating initial DBs"

	chown -R mysql:mysql /var/lib/mysql

	# init database
	echo 'Initializing database'
	mysql_install_db --user=mysql > /dev/null
	echo 'Database initialized'

	echo "[i] MySql root password: $MYSQL_ROOT_PASSWORD"

	# create temp file
	tfile=`mktemp`
	if [ ! -f "$tfile" ]; then
	    return 1
	fi

	# save sql
	echo "[i] Create temp file: $tfile"
	cat << EOF > $tfile
USE mysql;
FLUSH PRIVILEGES;
DELETE FROM mysql.user;
GRANT ALL PRIVILEGES ON *.* TO 'root'@'localhost' IDENTIFIED BY '$MYSQL_ROOT_PASSWORD' WITH GRANT OPTION;
GRANT SELECT, SHOW VIEW, PROCESS ON *.* TO '$MYSQL_USER_MONITORING'@'%' IDENTIFIED BY '$MYSQL_PASSWORD_MONITORING' WITH GRANT OPTION;
EOF


	# Create new database
	if [ "$MYSQL_DATABASE" != "" ]; then
		echo "[i] Creating database: $MYSQL_DATABASE"
		echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` CHARACTER SET utf8 COLLATE utf8_general_ci;" >> $tfile

		# set new User and Password
		if [ "$MYSQL_USER" != "" ] && [ "$MYSQL_PASSWORD" != "" ]; then
		echo "[i] Creating user: $MYSQL_USER with password $MYSQL_PASSWORD"
		echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* to '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD';" >> $tfile
		fi
	else
		# don`t need to create new database,Set new User to control all database.
		if [ "$MYSQL_USER" != "" ] && [ "$MYSQL_PASSWORD" != "" ]; then
		echo "[i] Creating user: $MYSQL_USER with password $MYSQL_PASSWORD"
		echo "GRANT ALL ON *.* to '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD';" >> $tfile
		fi
	fi

	echo 'FLUSH PRIVILEGES;' >> $tfile

	# run sql in tempfile
	echo "[i] run tempfile: $tfile"
	/usr/bin/mysqld --user=mysql --bootstrap --verbose=0 < $tfile
	rm -f $tfile
fi

echo "[i] Sleeping 5 sec"
sleep 5

echo "Starting all process"
exec /usr/bin/mysqld --user=mysql --console

And the dockerip.sh file is just a utility to help get the IP address of a running docker container. This is useful because to access our site we will use the Docker containers IP address and it can change every time you redeploy the container.

# dockerip.sh
docker inspect -f '{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}' php_container

Next change the permissions to allow the script to be executed

sudo chmod +x dockerip.sh

PHP File

The last file we need to add code to is our PHP file itself. Add the following code that simply displays Hello World

<?php
echo "Hello World";
?>

Build and Run

Now that we have all our files in place its time to build and then run the Docker container. Use the following docker commands to do so:

docker build -t phpd .
docker run -dit -p 80:80 -v "$PWD":/app/public --name php_container phpd

And now docker ps should show that your php_container is running!

Use the following curl command to view your hello world program

curl $(sh dockerip.sh)

Summary

In this article we saw how to install MySQL in a PHP Docker image for easier management of PHP and MySQL versions.

Tyler Moon

Published a year ago

Comments?

Leave us your opinion.