Creating Apache, MariaDB and PHP-FPM container with Docker Compose

Reference

http://www.inanzzz.com/index.php/post/su76/creating-apache-mysql-and-php-fpm-containers-for-a-web-application-with-docker-compose

https://dev.to/veevidify/docker-compose-up-your-entire-laravel-apache-mysql-development-environment-45ea

https://codereviewvideos.com/course/docker-tutorial-for-beginners/video/docker-php-7-tutorial-7-7-1-and-higher

Example configuration where there will be a container which contains apache + php-fpm & another container which contains the MariaDB (database) for simple web application.

Initial Structure

.
├── bad.php
├── docker
│   ├── apache
│   │   ├── Dockerfile
│   │   ├── httpd.conf
│   │   └── httpd-vhosts.conf
│   ├── build.sh
│   ├── destroy.sh
│   ├── docker-compose.yml
│   ├── .env
│   ├── mariadb
│   │   └── Dockerfile
│   └── php
│       ├── Dockerfile
│       └── www.conf
└── index.php
 
4 directories, 12 files

build.sh

#!/bin/bash
set -e

SCRIPTPATH=$(dirname "$0")

# Set to to name of folder created
project_name=test-dev
 
if ! [[ -d $SCRIPTPATH/../logs/$project_name/apache ]]; then
    mkdir -p $SCRIPTPATH/../logs/$project_name/apache
fi
 
if ! [[ -d $SCRIPTPATH/../logs/$project_name/mariadb ]]; then
    mkdir -p $SCRIPTPATH/../logs/$project_name/mariadb
fi
 
if ! [[ -d $SCRIPTPATH/../logs/$project_name/php ]]; then
    mkdir -p $SCRIPTPATH/../logs/$project_name/php
fi

if ! [[ -d $SCRIPTPATH/../database/$project_name/mariadb ]]; then
    mkdir -p $SCRIPTPATH/../database/$project_name/mariadb
fi

docker-compose -f $SCRIPTPATH/docker-compose.yml --project-directory $SCRIPTPATH up -d --build

.env

# Project name - prefix for the container names
PROJECT_NAME=some_project_name


# Set this to the UID of the owner of document root folder for Apache in host machine. E.g. UID for apache is 48  ##requires BUILD
UID=48
# Set this to the UID of the owner in host machine of
UID_MARIADB=1000


# Set to the (exposed) location on the host where you will store the web server hosted files
APACHE_BIND_VOLUME=/var/www/html
# Set to the (exposed) location for MariaDB Data Directory
MARIADB_DATA_BIND_VOLUME=/opt/docker/database/some_project_name/mariadb
# Set to the (exposed) location for MariaDB Log Directory
MARIADB_LOG_BIND_VOLUME=/opt/docker/logs/some_project_name/mariadb


NODE_APACHE_IP=192.168.0.11
NODE_APACHE_EXPOSED_PORT=8080
# Exposed location in host
NODE_APACHE_DOCUMENT_ROOT=/var/www/html/some_location_to_app_files


MARIADB_IP=192.168.0.22
MARIADB_EXPOSED_PORT=3306
DB_ROOT_PASSWORD=some_password
DB_NAME=db_test
DB_USERNAME=user
DB_PASSWORD=123abc


NETWORK_SUBNET=192.168.0.0/24

docker-compose.yml

version: '3.5'

services:
  php-apache-node:
    container_name: ${PROJECT_NAME}_php-apache
    build:
      context: './php-apache/'
      args:
        uid: ${UID}
    environment:
      - APACHE_DOCUMENT_ROOT=${NODE_APACHE_DOCUMENT_ROOT}
      - APACHE_RUN_USER=#${UID}
      - APACHE_RUN_GROUP=#${UID}
    volumes:
      - ${APACHE_BIND_VOLUME}:/var/www/html
    ports:
      - ${NODE_APACHE_EXPOSED_PORT}:80
    networks:
      public_net:
        ipv4_address: ${NODE_APACHE_IP}
        aliases:
          - php-apache-node

  mariadb:
    container_name: ${PROJECT_NAME}_mariadb
    restart: always
    build:
      context: './mariadb'
      args:
        uid_mariadb: ${UID_MARIADB}
    volumes:
      - ${MARIADB_DATA_BIND_VOLUME}:/var/lib/mysql
      - ${MARIADB_LOG_BIND_VOLUME}:/var/log/mysql
    ports:
      - ${MARIADB_EXPOSED_PORT}:3306
    environment:
      - MYSQL_ROOT_PASSWORD=${DB_ROOT_PASSWORD}
      - MYSQL_DATABASE=${DB_NAME}
      - MYSQL_USER=${DB_USERNAME}
      - MYSQL_PASSWORD=${DB_PASSWORD}
    networks:
      public_net:
        ipv4_address: ${MARIADB_IP}
        aliases:
          - maria-db
    
networks:
  public_net:
    driver: bridge
    ipam: 
      driver: default
      config:
        - subnet: ${NETWORK_SUBNET}

apache/Dockerfile

FROM php:7.2-apache

RUN apt-get update

# 1. development packages
RUN apt-get install -y \
    git \
    zip \
    curl \
    sudo \
    unzip \
    libicu-dev \
    libbz2-dev \
    libpng-dev \
    libjpeg-dev \
    libmcrypt-dev \
    libreadline-dev \
    libfreetype6-dev \
    g++

# 2. apache configs + document root
### ENV APACHE_DOCUMENT_ROOT=/var/www/html/docker/3LC.systems-web/public  #ignore since it is set in docker-compse.yml#
RUN sed -ri -e 's!/var/www/html!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/sites-available/*.conf
RUN sed -ri -e 's!/var/www/!${APACHE_DOCUMENT_ROOT}!g' /etc/apache2/apache2.conf /etc/apache2/conf-available/*.conf

# 3. mod_rewrite for URL rewrite and mod_headers for .htaccess extra headers like Access-Control-Allow-Origin-
RUN a2enmod rewrite headers

# 4. start with base php config, then add extensions
RUN mv "$PHP_INI_DIR/php.ini-development" "$PHP_INI_DIR/php.ini"

RUN docker-php-ext-install \
    bz2 \
    intl \
    iconv \
    bcmath \
    opcache \
    calendar \
    mbstring \
    pdo_mysql \
    zip


## Install mongodb extension
RUN pecl install mongodb
RUN echo "extension=mongodb.so" >> $PHP_INI_DIR/php.ini

# 6. we need a user with the same UID/GID with host user
# so when we execute CLI commands, all the host file's ownership remains intact
# otherwise command from inside container will create root-owned files and directories
ARG uid
RUN useradd -G www-data,root -u $uid -d /home/devuser devuser
RUN mkdir -p /home/devuser/.composer && \
    chown -R devuser:devuser /home/devuser

mariadb/Dockerfile

FROM mariadb:10.3
 
ARG uid_mariadb

RUN usermod -u $uid_mariadb mysql \
 && groupmod -g $uid_mariadb mysql

Run docker-compose build or the build.sh script