Docker Compose: Centos, Apache, PHP, MySQL

April 5, 2020

With the Docker Compose utility we can create our own environment for web development.

We will be using two Dockerfiles created on previous posts:

Docker Compose

First, we create a file named docker-compose.yml.
On that file we will define two services "web" and "db"

docker-compose.yml


version: "3.7"
services:
  web:
    build:
      context: ./apache-php
      dockerfile: Dockerfile
    depends_on:
      - db
    ports:
      - "4000:80"
    volumes:
      - ./www:/var/www
  db:
    build:
      context: ./mysql
      dockerfile: Dockerfile
    environment:
      - MYSQL_ROOT_PASSWORD=root
      - MYSQL_ROOT_HOST=%
    ports:
      - "3306:3306"
    volumes:
      - ./data:/var/lib/mysql      
    command: --default-authentication-plugin=mysql_native_password

  • The "web" service will use the Dockerfile for our Apache/PHP container.

  • The "db" service will use the Dockerfile for our MySQL container.
  • For the root user we are using the password "root". You may want to use a more secure password.
  • We also use the port 3306 to access the MySQL server from the host machine. If you already have another instance of MySQL running, you may need to use a different port. (i.e. "4001:3306")

Dockerfile for Web Server

This is the Dockerfile for the web server.


FROM centos:7

# Install Apache
RUN yum -y update
RUN yum -y install httpd httpd-tools

# Install EPEL Repo
RUN rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm \
 && rpm -Uvh http://rpms.remirepo.net/enterprise/remi-release-7.rpm

# Install PHP
RUN yum --enablerepo=remi-php73 -y install php php-bcmath php-cli php-common php-gd php-intl php-ldap php-mbstring \
    php-mysqlnd php-pear php-soap php-xml php-xmlrpc php-zip

# Update Apache Configuration
RUN sed -E -i -e '/<Directory "\/var\/www\/html">/,/<\/Directory>/s/AllowOverride None/AllowOverride All/' /etc/httpd/conf/httpd.conf
RUN sed -E -i -e 's/DirectoryIndex (.*)$/DirectoryIndex index.php \1/g' /etc/httpd/conf/httpd.conf

EXPOSE 80

# Start Apache
CMD ["/usr/sbin/httpd","-D","FOREGROUND"]

Dockerfile for Database Server

This is the Dockerfile for the database server.


# Copyright (c) 2017, Oracle and/or its affiliates. All rights reserved.
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; version 2 of the License.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
FROM oraclelinux:7-slim

ARG MYSQL_SERVER_PACKAGE=mysql-community-server-minimal-8.0.19
ARG MYSQL_SHELL_PACKAGE=mysql-shell-8.0.19

# Install server
RUN yum install -y https://repo.mysql.com/mysql-community-minimal-release-el7.rpm \
        https://repo.mysql.com/mysql-community-release-el7.rpm \
    && yum-config-manager --enable mysql80-server-minimal \
    && yum install -y \
        $MYSQL_SERVER_PACKAGE \
        $MYSQL_SHELL_PACKAGE \
        libpwquality \
    && yum clean all \
    && mkdir /docker-entrypoint-initdb.d

VOLUME /var/lib/mysql

COPY docker-entrypoint.sh /entrypoint.sh
COPY healthcheck.sh /healthcheck.sh

RUN chmod +x /entrypoint.sh
RUN chmod +x /healthcheck.sh

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

Files

You can download the above files, as well as additional files as a zip file here.

Uncompress the zipped file, and you will have the following folder structure and files:


apache-php7-mysql8/
   ├─ apache-php/
   │  └─ Dockerfile
   ├─ data/
   ├─ docker-compose.yml
   ├─ mysql/
   │   ├─ docker-entrypoint.sh
   │   └─ Dockerfile
   │   └─ healthcheck.sh
   └─ www/
      └─ html/
          └─ test.php

Build and Start the Containers

Now we create the containers.
Open a terminal window, navigate to the folder with the docker-compose.yml file, and type the following command.


docker-compose up -d

You will see an output similar to this one (excerpts):

Creating network "apache-php7-mysql8_default" with the default driver
Building db
Step 1/13 : FROM oraclelinux:7-slim
7-slim: Pulling from library/oraclelinux
cd17e56c322c: Pull complete


...


Removing intermediate container 3a6206494b46
 ---> 4276c3affc43

Successfully built 4276c3affc43
Successfully tagged apache-php7-mysql8_db:latest
WARNING: Image for service db was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Building web
Step 1/9 : FROM centos:7
7: Pulling from library/centos
ab5ef0e58194: Pull complete


...


Removing intermediate container 376c3114e934
 ---> 2301a4fd609d

Successfully built 2301a4fd609d
Successfully tagged apache-php7-mysql8_web:latest
WARNING: Image for service web was built because it did not already exist. To rebuild this image you must use `docker-compose build` or `docker-compose up --build`.
Creating apache-php7-mysql8_db_1 ... done
Creating apache-php7-mysql8_web_1 ... done
Creating network "apache-php7-mysql8_default" with the default driver


After the containers have finished building, we can check the logs with the following command:


docker-compose logs

Output (excerpts):

Attaching to apache-php7-mysql8_db_1, apache-php7-mysql8_web_1
db_1   | [Entrypoint] MySQL Docker Image 8.0.19-1.1.15
db_1   | [Entrypoint] Initializing database
db_1   | 2020-04-05T04:36:37.316161Z 0 [System] [MY-013169] [Server] /usr/sbin/mysqld (mysqld 8.0.19) initializing of server in progress as process 21
web_1  | AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 172.18.0.3. Set the 'ServerName' directive globally to suppress this message
db_1   | 2020-04-05T04:36:38.448178Z 5 [Warning] [MY-010453] [Server] root@localhost is created with an empty password ! Please consider switching off the --initialize-insecure option.
db_1   | [Entrypoint] Database initialized


...


db_1   | [Entrypoint] ignoring /docker-entrypoint-initdb.d/*
db_1   | 
db_1   | 2020-04-05T04:36:42.919259Z 10 [System] [MY-013172] [Server] Received SHUTDOWN from user root. Shutting down mysqld (Version: 8.0.19).
db_1   | 2020-04-05T04:36:44.266774Z 0 [System] [MY-010910] [Server] /usr/sbin/mysqld: Shutdown complete (mysqld 8.0.19)  MySQL Community Server - GPL.
db_1   | [Entrypoint] Server shut down
db_1   | 
db_1   | [Entrypoint] MySQL init process done. Ready for start up.
db_1   | 
db_1   | [Entrypoint] Starting MySQL 8.0.19-1.1.15
db_1   | 2020-04-05T04:36:45.142817Z 0 [System] [MY-010116] [Server] /usr/sbin/mysqld (mysqld 8.0.19) starting as process 1
db_1   | 2020-04-05T04:36:45.438910Z 0 [Warning] [MY-010068] [Server] CA certificate ca.pem is self signed.
db_1   | 2020-04-05T04:36:45.454484Z 0 [System] [MY-010931] [Server] /usr/sbin/mysqld: ready for connections. Version: '8.0.19'  socket: '/var/lib/mysql/mysql.sock'  port: 3306  MySQL Community Server - GPL.
db_1   | 2020-04-05T04:36:45.611147Z 0 [System] [MY-011323] [Server] X Plugin ready for connections. Socket: '/var/run/mysqld/mysqlx.sock' bind-address: '::' port: 33060


Test the Containers

To test that our web and database servers are working correctly there is included a test.php file that will try to make a connection to the database.


<?php
$host = 'db';
$user = 'root';
$pass = 'root';

$mysqli = new mysqli($host, $user, $pass);

if (!$mysqli->connect_error) {
    echo 'Connection successful!';
}  else {
    echo 'Error (' . $mysqli->connect_errno . ') ' . $mysqli->connect_error;
}

$mysqli->close();
?>

  • As "host" variable we can use the name of our "db" service. We don't need to specify its IP address.
  • If you have specified a different password for the root user on the docker-compose.yml file. You would have to change it on this file as well.

Open your web browser and go to the http://localhost:4000/test.php url.

You should see the following text:

Connection successful!

If the connection couldn't be made, an error message, indicating the reason, will be displayed instead.



Stop the Containers

After you have finished working with your containers you can stop them:


docker-compose stop

To re-start them, you would execute the docker-compose up -d specified above.



Remove the Containers

If you don't need the containers any more you can remove them:


docker-compose down


Downloads

apache-php7-mysql8.zip


Check the docker-compose.yml and Dockerfiles on Github here.