BLOG POSTS
Apache Web Server Dockerfile Example

Apache Web Server Dockerfile Example

When you’re setting up containerized web services, Apache HTTP Server remains one of the most reliable and widely-used web servers for hosting everything from simple static sites to complex web applications. Building a proper Dockerfile for Apache requires understanding the container ecosystem, Apache configuration nuances, and Docker best practices to create secure, efficient, and maintainable images. This guide walks through creating production-ready Apache Dockerfiles, covers common configuration scenarios, troubleshooting techniques, and compares different approaches to help you deploy robust web services in containers.

How Apache Docker Containers Work

Apache runs as the main process inside a Docker container, typically listening on port 80 (HTTP) and 443 (HTTPS). The container includes the Apache binary, configuration files, modules, and your web content. When you start the container, Apache becomes the primary process (PID 1), which means proper signal handling and graceful shutdowns become crucial for production deployments.

The key components in an Apache Docker setup include:

  • Base operating system (usually Ubuntu, Debian, or Alpine)
  • Apache HTTP Server package and essential modules
  • Configuration files (httpd.conf, sites-enabled, etc.)
  • SSL certificates and security configurations
  • Your web application files and assets
  • Log management and volume mounting strategies

Basic Apache Dockerfile Implementation

Here’s a straightforward Dockerfile that sets up Apache with common configurations:

FROM ubuntu:22.04

# Avoid interactive prompts during package installation
ENV DEBIAN_FRONTEND=noninteractive

# Install Apache and essential tools
RUN apt-get update && \
    apt-get install -y \
        apache2 \
        apache2-utils \
        curl \
        vim \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Enable Apache modules
RUN a2enmod rewrite ssl headers deflate

# Create directory for SSL certificates
RUN mkdir -p /etc/apache2/ssl

# Copy custom configuration
COPY apache2.conf /etc/apache2/apache2.conf
COPY 000-default.conf /etc/apache2/sites-available/000-default.conf

# Copy web content
COPY ./html/ /var/www/html/

# Set proper permissions
RUN chown -R www-data:www-data /var/www/html \
    && chmod -R 755 /var/www/html

# Expose ports
EXPOSE 80 443

# Start Apache in foreground
CMD ["apache2ctl", "-D", "FOREGROUND"]

This Dockerfile creates a solid foundation, but you’ll need supporting configuration files. Here’s a sample apache2.conf with security hardening:

# /etc/apache2/apache2.conf
DefaultRuntimeDir ${APACHE_RUN_DIR}
PidFile ${APACHE_PID_FILE}
Timeout 60
KeepAlive On
MaxKeepAliveRequests 100
KeepAliveTimeout 5

User ${APACHE_RUN_USER}
Group ${APACHE_RUN_GROUP}

HostnameLookups Off

LogLevel warn
ErrorLog ${APACHE_LOG_DIR}/error.log
CustomLog ${APACHE_LOG_DIR}/access.log combined

# Security headers
Header always set X-Content-Type-Options nosniff
Header always set X-Frame-Options DENY
Header always set X-XSS-Protection "1; mode=block"
Header always set Strict-Transport-Security "max-age=63072000; includeSubDomains; preload"

# Hide Apache version
ServerTokens Prod
ServerSignature Off

# Include module configuration
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf
IncludeOptional conf-enabled/*.conf
IncludeOptional sites-enabled/*.conf

Advanced Multi-Stage Build Example

For production environments, you’ll want to optimize image size and security using multi-stage builds. This approach separates the build environment from the runtime environment:

# Build stage
FROM node:18-alpine AS builder

WORKDIR /app
COPY package*.json ./
RUN npm ci --only=production

COPY src/ ./src/
RUN npm run build

# Production stage
FROM httpd:2.4-alpine

# Install additional packages
RUN apk add --no-cache \
    openssl \
    curl \
    bash

# Copy built application
COPY --from=builder /app/dist/ /usr/local/apache2/htdocs/

# Copy Apache configuration
COPY httpd.conf /usr/local/apache2/conf/httpd.conf
COPY ssl.conf /usr/local/apache2/conf/extra/httpd-ssl.conf

# Create SSL directory and generate self-signed certificate for development
RUN mkdir -p /usr/local/apache2/conf/ssl && \
    openssl req -x509 -nodes -days 365 -newkey rsa:2048 \
    -keyout /usr/local/apache2/conf/ssl/apache.key \
    -out /usr/local/apache2/conf/ssl/apache.crt \
    -subj "/C=US/ST=State/L=City/O=Organization/CN=localhost"

# Set proper permissions
RUN chown -R daemon:daemon /usr/local/apache2/htdocs/

EXPOSE 80 443

# Health check
HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \
    CMD curl -f http://localhost/ || exit 1

CMD ["httpd-foreground"]

Real-World Use Cases and Examples

PHP Application with Apache

Many developers need Apache with PHP support. Here’s a Dockerfile for a PHP web application:

FROM php:8.2-apache

# Install PHP extensions and system dependencies
RUN apt-get update && apt-get install -y \
    libpng-dev \
    libjpeg-dev \
    libfreetype6-dev \
    libzip-dev \
    unzip \
    && docker-php-ext-configure gd --with-freetype --with-jpeg \
    && docker-php-ext-install -j$(nproc) gd pdo pdo_mysql zip \
    && apt-get clean \
    && rm -rf /var/lib/apt/lists/*

# Enable Apache modules
RUN a2enmod rewrite ssl headers

# Copy application files
COPY ./src/ /var/www/html/

# Copy custom Apache configuration
COPY apache-php.conf /etc/apache2/sites-available/000-default.conf

# Install Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# Install PHP dependencies
WORKDIR /var/www/html
RUN composer install --no-dev --optimize-autoloader

# Set permissions
RUN chown -R www-data:www-data /var/www/html

EXPOSE 80 443

Reverse Proxy Configuration

Apache can also serve as a reverse proxy for backend services. Here’s a configuration example:

# reverse-proxy.conf

    ServerName api.example.com
    
    ProxyPreserveHost On
    ProxyRequests Off
    
    # Load balancing between backend servers
    ProxyPass /api/ balancer://backend-cluster/
    ProxyPassReverse /api/ balancer://backend-cluster/
    
    
        BalancerMember http://backend1:3000
        BalancerMember http://backend2:3000
        ProxySet hcmethod GET
        ProxySet hcuri /health
    
    
    # Static files served directly
    ProxyPass /static/ !
    Alias /static/ /var/www/static/
    
    LogLevel info
    ErrorLog ${APACHE_LOG_DIR}/proxy_error.log
    CustomLog ${APACHE_LOG_DIR}/proxy_access.log combined

Performance Optimization and Best Practices

Apache performance in containers requires specific tuning approaches. Here’s a performance-optimized configuration:

# performance-tuned.conf
# MPM Configuration for containers

    StartServers 2
    MinSpareServers 2
    MaxSpareServers 5
    MaxRequestWorkers 150
    MaxConnectionsPerChild 1000


# Enable compression

    AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css text/javascript application/javascript application/json
    DeflateCompressionLevel 6


# Cache static files

    ExpiresActive On
    ExpiresByType image/jpg "access plus 1 month"
    ExpiresByType image/jpeg "access plus 1 month"
    ExpiresByType image/gif "access plus 1 month"
    ExpiresByType image/png "access plus 1 month"
    ExpiresByType text/css "access plus 1 month"
    ExpiresByType application/pdf "access plus 1 month"
    ExpiresByType text/javascript "access plus 1 month"
    ExpiresByType application/javascript "access plus 1 month"


# Limit request size and timeouts for container environments
LimitRequestBody 10485760
Timeout 30
KeepAliveTimeout 2

Comparison with Alternative Approaches

Approach Image Size Security Performance Maintenance Best Use Case
Official Apache (httpd:2.4) ~200MB High Excellent Low Static sites, reverse proxy
PHP-Apache (php:8.2-apache) ~500MB Medium Good Medium PHP applications
Alpine-based custom ~50MB High Very Good High Production microservices
Ubuntu-based custom ~300MB Medium Good Medium Development, complex apps

Common Issues and Troubleshooting

Here are the most frequent problems you’ll encounter and their solutions:

Permission Issues

One of the most common problems involves file permissions. Apache runs as www-data user but files are often copied as root:

# Fix in Dockerfile
RUN chown -R www-data:www-data /var/www/html && \
    find /var/www/html -type d -exec chmod 755 {} \; && \
    find /var/www/html -type f -exec chmod 644 {} \;

# Or use COPY with ownership
COPY --chown=www-data:www-data ./html/ /var/www/html/

Apache Won’t Start in Container

Apache needs to run in foreground mode inside containers. Check these common issues:

# Wrong - Apache will start and immediately exit
CMD ["service", "apache2", "start"]

# Correct - Apache runs in foreground
CMD ["apache2ctl", "-D", "FOREGROUND"]

# Alternative correct approach
CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]

Module Loading Issues

Enable required modules explicitly in your Dockerfile:

# Check available modules
RUN apache2ctl -M

# Enable specific modules
RUN a2enmod rewrite ssl headers deflate proxy proxy_http proxy_balancer lbmethod_byrequests

# Verify configuration
RUN apache2ctl configtest

Log Management

Container logs should go to stdout/stderr for proper Docker log handling:

# Link Apache logs to stdout/stderr
RUN ln -sf /dev/stdout /var/log/apache2/access.log && \
    ln -sf /dev/stderr /var/log/apache2/error.log

# Or configure in apache2.conf
ErrorLog /proc/self/fd/2
CustomLog /proc/self/fd/1 combined

Docker Compose Integration

Here’s a complete docker-compose.yml example that demonstrates Apache integration with other services:

version: '3.8'

services:
  web:
    build:
      context: .
      dockerfile: Dockerfile.apache
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - ./html:/var/www/html:ro
      - ./ssl:/etc/apache2/ssl:ro
      - apache-logs:/var/log/apache2
    environment:
      - APACHE_LOG_LEVEL=warn
    depends_on:
      - db
    networks:
      - webnet
    restart: unless-stopped
    healthcheck:
      test: ["CMD", "curl", "-f", "http://localhost/health"]
      interval: 30s
      timeout: 10s
      retries: 3

  db:
    image: mysql:8.0
    environment:
      MYSQL_ROOT_PASSWORD: rootpassword
      MYSQL_DATABASE: webapp
    volumes:
      - mysql-data:/var/lib/mysql
    networks:
      - webnet

volumes:
  apache-logs:
  mysql-data:

networks:
  webnet:
    driver: bridge

Security Considerations

Securing Apache in containers requires both container-level and Apache-level configurations:

# Dockerfile security improvements
FROM httpd:2.4-alpine

# Run as non-root user
RUN addgroup -g 1001 appgroup && \
    adduser -D -s /bin/sh -u 1001 -G appgroup appuser

# Remove unnecessary packages and files
RUN apk del --purge wget curl && \
    rm -rf /var/cache/apk/* && \
    rm -rf /usr/local/apache2/htdocs/index.html

# Copy security-hardened configuration
COPY --chown=appuser:appgroup security.conf /usr/local/apache2/conf/extra/

# Set secure file permissions
RUN chmod -R o-rwx /usr/local/apache2/conf/ && \
    chown -R appuser:appgroup /usr/local/apache2/

USER appuser

EXPOSE 8080

For comprehensive Apache documentation and advanced configuration options, check the official Apache HTTP Server documentation. The Docker development best practices guide provides additional insights for container optimization.

Running Apache in Docker containers offers excellent flexibility for both development and production environments. The key to success lies in understanding the interaction between Apache’s process model and Docker’s container lifecycle, implementing proper security measures, and optimizing for your specific use case. Whether you’re serving static sites, running PHP applications, or setting up reverse proxies, these patterns and configurations provide a solid foundation for reliable Apache deployments.



This article incorporates information and material from various online sources. We acknowledge and appreciate the work of all original authors, publishers, and websites. While every effort has been made to appropriately credit the source material, any unintentional oversight or omission does not constitute a copyright infringement. All trademarks, logos, and images mentioned are the property of their respective owners. If you believe that any content used in this article infringes upon your copyright, please contact us immediately for review and prompt action.

This article is intended for informational and educational purposes only and does not infringe on the rights of the copyright owners. If any copyrighted material has been used without proper credit or in violation of copyright laws, it is unintentional and we will rectify it promptly upon notification. Please note that the republishing, redistribution, or reproduction of part or all of the contents in any form is prohibited without express written permission from the author and website owner. For permissions or further inquiries, please contact us.

Leave a reply

Your email address will not be published. Required fields are marked