
Introduction
While Nginx is popular for Docker-based local development environments due to its ease of setup and performance, there are scenarios where testing with Apache and .htaccess
files becomes necessary. Although solutions like Lando, Varnish, Woodby, or DDEV exist, this guide focuses on a custom setup that provides full control over container configuration, preferring Alpine-based containers for their lightweight nature.
Original Nginx Configuration
The typical Nginx setup in docker-compose.yml
consists of two main services:
web:
build:
context: docker/nginx
container_name: "${PROJECT_NAME}-web"
expose:
- '80'
volumes:
- ./:/drupal
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
environment:
- SERVER_NAME=${PROJECT_NAME}-web.docker.localhost
links:
- php-fpm
labels:
- "traefik.frontend.rule=Host:${PROJECT_NAME}-web.docker.localhost"
depends_on:
- reverse-proxy
- php-fpm
networks:
- default
reverse-proxy:
image: traefik:v1.7
container_name: "${PROJECT_NAME}-rp"
command: --api --docker
ports:
- "80:80"
- "9090:8080"
volumes:
- /var/run/docker.sock:/var/run/docker.sock
labels:
- "traefik.enable=false"
Apache Configuration
To switch to Apache, we'll use the httpd:2.4-alpine
image. The Apache configuration in docker-compose.yml
is similar to Nginx:
web-apache:
build:
context: docker/apache
container_name: "${PROJECT_NAME}-web-apache"
expose:
- '80'
volumes:
- ./:/drupal
- ./docker/apache/httpd.conf:/usr/local/apache2/conf/httpd.conf
environment:
- SERVER_NAME=${PROJECT_NAME}-web.docker.localhost
links:
- php-fpm
labels:
- "traefik.frontend.rule=Host:${PROJECT_NAME}-web.docker.localhost"
depends_on:
- reverse-proxy
- php-fpm
networks:
- default
Apache Virtual Host Configuration
The default httpd.conf
needs to be modified to include proper virtual host settings. Create a virtual host configuration with the following settings:
<VirtualHost *:80>
ServerAdmin admin@example.com
DocumentRoot /drupal/web
ErrorLog /proc/self/fd/2
CustomLog /proc/self/fd/1 combined
<Directory /drupal/web>
Options -Indexes +Includes +FollowSymLinks -MultiViews
AllowOverride All
Require all granted
</Directory>
<FilesMatch \.php$>
SetHandler "proxy:fcgi://php-fpm:9000"
</FilesMatch>
</VirtualHost>
This configuration:
- Sets the document root to
/drupal/web
- Enables necessary directory options
- Allows
.htaccess
overrides - Configures PHP-FPM handling
- Routes logs to Docker's standard output/error
Container Management
To manage the containers efficiently, use a Makefile:
PROJECT_NAME = my-project
DRUPAL_ROOT=/drupal/
SERVER_ROOT=/drupal/web/
CURRENT_UID=$(shell id -u)
CURRENT_GID=$(shell id -g)
GATEWAY=$$(docker inspect -f "{{ (index .IPAM.Config 0).Gateway }}" $${PROJECT_NETWORK_ID}); \
SETTINGS='\
export PROJECT_NAME=${PROJECT_NAME}; \
export CURRENT_UID=${CURRENT_UID}; \
export CURRENT_GID=${CURRENT_GID}; \
export DOCKER_ENV="docker compose --project-name $${PROJECT_NAME}"; \
'
DOCKER_UP=' \
$${DOCKER_ENV} up --detach --build --remove-orphans ; \
'
up:
@bash -c $(SETTINGS)$(DOCKER_UP)
Key Differences from Nginx
When switching from Nginx to Apache, note these key differences:
- Apache uses
httpd.conf
instead of Nginx'sdefault.conf
- Directory permissions and options are handled differently
.htaccess
files are natively supported in Apache- PHP-FPM configuration syntax differs between the servers
Source https://github.com/onesixromcom/drupal10_docker_apache
Conclusion
This setup provides a straightforward way to test Drupal sites with Apache in a Docker environment while maintaining full control over the configuration. The Alpine-based Apache image keeps the container lightweight, and the integration with Traefik ensures easy local domain handling.