Let’s get straight into it. I needed a LAMP stack and to install and configure PHP plugins for something I was working on, I think it came out pretty well, not to be used in production but as a small test server it works great for me.
docker-compose.yml
x-variables: &mysql-env
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: your_database
MYSQL_USER: user
MYSQL_PASSWORD: password
services:
# Apache and PHP service
web:
build:
context: .
dockerfile: Dockerfile
container_name: php-apache-container
ports:
- "80:80"
volumes:
- './web-root:/var/www/html'
- ./web-config/virtual-host.conf:/etc/apache2/sites-enabled/000-default.conf
- ./web-config/apache2.conf:/etc/apache2/apache2.conf
depends_on:
- memcached
# - prometheus
# - grafana
networks:
- web-network
memcached:
container_name: memcached
image: memcached:latest
ports:
- "11211:11211"
restart: always
# MySQL service
mariadb:
image: mariadb:11.0
networks:
- web-network
container_name: mariadb-container
ports:
- "3306:3306"
environment:
<<: *mysql-env
volumes:
- ./web-database:/var/lib/mysql
# phpMyAdmin service
phpmyadmin:
image: phpmyadmin/phpmyadmin
networks:
- web-network
container_name: phpmyadmin-container
ports:
- "8081:80"
environment:
PMA_HOST: mariadb
MYSQL_ROOT_PASSWORD: root_password
depends_on:
- mariadb
# Define networks
networks:
web-network:
As you can see, main services are Apache, PHP, memcached, mariadb and phpmyadmin. The configuration is done in the actual DockerFile.
Dockerfile
# Use the official PHP image as a base
FROM php:8.3-apache
# Install system dependencies and PHP extensions
RUN apt-get update && apt-get install -y \
libssl-dev \
zlib1g-dev \
libmemcached-dev \
libfreetype6-dev \
libjpeg62-turbo-dev \
libpng-dev \
libzip-dev \
zip \
unzip \
curl \
libcurl4-openssl-dev \
libmagickwand-dev \
libxml2-dev \
libmcrypt-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd \
&& docker-php-ext-install -j$(nproc) \
pdo_mysql \
opcache \
mysqli \
zip \
exif \
xml \
iconv \
simplexml \
&& pecl install imagick \
&& docker-php-ext-enable imagick \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# Install memcached, pecl & enable
RUN yes '' | pecl install -f memcached-3.2.0 \
&& docker-php-ext-enable memcached
# Install mod_security2
RUN apt-get update && apt-get install -y \
libapache2-mod-security2
# Copy default modsecurity config & register it
COPY ./web-config/modsecurity.conf /etc/modsecurity/modsecurity.conf
RUN sed -i 's/SecRuleEngine DetectionOnly/SecRuleEngine On/' /etc/modsecurity/modsecurity.conf
# Enable OPcache and configure it
RUN echo "zend_extension=opcache.so" > /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.enable=1" >> /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.memory_consumption=128" >> /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.interned_strings_buffer=8" >> /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.max_accelerated_files=10000" >> /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.revalidate_freq=2" >> /usr/local/etc/php/conf.d/opcache.ini \
&& echo "opcache.fast_shutdown=1" >> /usr/local/etc/php/conf.d/opcache.ini
# Enable Apache mod_rewrite
RUN a2enmod rewrite
# Enable deflate compression
RUN a2enmod deflate
# Enable mod_expires for HTTP request response headers.
RUN a2enmod expires
# Adds and modifies HTTP request and response headers.
RUN a2enmod headers
# Cache responses to disk
RUN a2enmod cache cache_disk
# Optimize sessions & session security
RUN echo "session.gc_maxlifetime = 1440" >> /usr/local/etc/php/conf.d/php.ini \
&& echo "session.cookie_secure = 1" >> /usr/local/etc/php/conf.d/php.ini \
&& echo "session.cookie_httponly = 1" >> /usr/local/etc/php/conf.d/php.ini
# Set PHP upload_max_filesize and post_max_size
RUN echo "upload_max_filesize = 50M" > /usr/local/etc/php/conf.d/uploads.ini \
&& echo "post_max_size = 50M" >> /usr/local/etc/php/conf.d/uploads.ini
# Set Apache Security Headers
RUN echo "Header set X-XSS-Protection \"1; mode=block\"" >> /etc/apache2/conf-available/security.conf \
&& echo "Header set X-Content-Type-Options \"nosniff\"" >> /etc/apache2/conf-available/security.conf \
&& echo "Header set Referrer-Policy \"same-origin\"" >> /etc/apache2/conf-available/security.conf
# Enable HTTP/2 and HTTPS
RUN a2enmod http2 ssl
# Enable required Apache modules
RUN a2dismod -f autoindex
# Set working directory
WORKDIR /var/www/html
# Start Apache server
CMD ["apache2-foreground"]
That’s pretty much it. The structure looks like the following:
Which has the web-config for the apache virtual hosts, apache config and modsecurity. web-database contains the actual database for persistence and web-root contains the actual files for your web project.
It’s quick and dirty, but works. Hopefully that’s helped someone out there.