Docker
Alpine Linux
Apache 2
Web Server
Containerization

How do I run Apache 2 on Alpine in Docker?

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

Introduction

Running Apache HTTP Server (httpd) on Alpine Linux in Docker produces a lightweight web server container — typically 50-60 MB compared to 200+ MB for Debian-based images. Alpine uses apk for package management and the package is named apache2, not httpd. The key differences from Debian-based setups are the package names, config file locations, and the need to run Apache in the foreground for Docker.

Basic Dockerfile

dockerfile
1FROM alpine:3.19
2
3# Install Apache
4RUN apk add --no-cache apache2
5
6# Create the run directory (required by Apache on Alpine)
7RUN mkdir -p /run/apache2
8
9# Expose port 80
10EXPOSE 80
11
12# Run Apache in the foreground
13CMD ["httpd", "-D", "FOREGROUND"]

Build and run:

bash
1docker build -t alpine-apache .
2docker run -d -p 8080:80 --name web alpine-apache
3
4# Test
5curl http://localhost:8080

With Custom HTML Content

dockerfile
1FROM alpine:3.19
2
3RUN apk add --no-cache apache2 && \
4    mkdir -p /run/apache2
5
6# Copy custom website files
7COPY ./html/ /var/www/localhost/htdocs/
8
9EXPOSE 80
10CMD ["httpd", "-D", "FOREGROUND"]
bash
1# Create content
2mkdir html
3echo '<h1>Hello from Alpine Apache</h1>' > html/index.html
4
5# Build and run
6docker build -t my-website .
7docker run -d -p 8080:80 my-website

With PHP Support

dockerfile
1FROM alpine:3.19
2
3RUN apk add --no-cache \
4    apache2 \
5    php83 \
6    php83-apache2 \
7    php83-common \
8    php83-json \
9    php83-mbstring \
10    php83-session \
11    php83-pdo \
12    php83-pdo_mysql && \
13    mkdir -p /run/apache2
14
15# Copy PHP application
16COPY ./app/ /var/www/localhost/htdocs/
17
18EXPOSE 80
19CMD ["httpd", "-D", "FOREGROUND"]
php
1<!-- app/index.php -->
2<?php
3phpinfo();
4?>

With SSL/TLS (HTTPS)

dockerfile
1FROM alpine:3.19
2
3RUN apk add --no-cache apache2 apache2-ssl openssl && \
4    mkdir -p /run/apache2
5
6# Generate self-signed certificate (for development)
7RUN openssl req -x509 -nodes -days 365 \
8    -newkey rsa:2048 \
9    -keyout /etc/ssl/private/server.key \
10    -out /etc/ssl/certs/server.crt \
11    -subj "/CN=localhost"
12
13# Enable SSL module
14RUN sed -i 's/#LoadModule ssl_module/LoadModule ssl_module/' /etc/apache2/httpd.conf && \
15    sed -i 's/#Include \/etc\/apache2\/conf.d\/ssl.conf/Include \/etc\/apache2\/conf.d\/ssl.conf/' /etc/apache2/httpd.conf
16
17EXPOSE 80 443
18CMD ["httpd", "-D", "FOREGROUND"]

Custom Apache Configuration

The default config location on Alpine is /etc/apache2/httpd.conf:

dockerfile
1FROM alpine:3.19
2
3RUN apk add --no-cache apache2 && \
4    mkdir -p /run/apache2
5
6# Copy custom configuration
7COPY httpd.conf /etc/apache2/httpd.conf
8COPY my-site.conf /etc/apache2/conf.d/my-site.conf
9
10COPY ./html/ /var/www/localhost/htdocs/
11
12EXPOSE 80
13CMD ["httpd", "-D", "FOREGROUND"]

Example custom virtual host (my-site.conf):

apache
1<VirtualHost *:80>
2    ServerName mysite.local
3    DocumentRoot /var/www/localhost/htdocs
4
5    <Directory /var/www/localhost/htdocs>
6        AllowOverride All
7        Require all granted
8    </Directory>
9
10    ErrorLog /var/log/apache2/error.log
11    CustomLog /var/log/apache2/access.log combined
12</VirtualHost>

Alpine vs Debian Apache Paths

ItemAlpineDebian/Ubuntu
Package nameapache2apache2
Binaryhttpdapache2 or apache2ctl
Main config/etc/apache2/httpd.conf/etc/apache2/apache2.conf
Site configs/etc/apache2/conf.d//etc/apache2/sites-available/
Document root/var/www/localhost/htdocs//var/www/html/
Modules/usr/lib/apache2//usr/lib/apache2/modules/
PID file/run/apache2/httpd.pid/run/apache2/apache2.pid

Using the Official httpd Image

Docker Hub provides an official httpd image (Debian-based), and an Alpine variant:

dockerfile
1# Official Apache image (Debian-based)
2FROM httpd:2.4
3
4COPY ./html/ /usr/local/apache2/htdocs/
5
6# Official Apache image (Alpine variant — smaller)
7FROM httpd:2.4-alpine
8
9COPY ./html/ /usr/local/apache2/htdocs/

The official image is pre-configured and production-ready. Use it unless you need custom Alpine packages.

Docker Compose

yaml
1version: '3.8'
2services:
3  web:
4    build: .
5    ports:
6      - "8080:80"
7    volumes:
8      - ./html:/var/www/localhost/htdocs:ro
9    restart: unless-stopped

Mount the content directory as a volume for development — changes are reflected without rebuilding.

Enabling Modules

bash
1# List available modules
2docker exec web ls /usr/lib/apache2/
3
4# Enable mod_rewrite (for .htaccess URL rewriting)
5# In httpd.conf, uncomment:
6# LoadModule rewrite_module modules/mod_rewrite.so
dockerfile
# In Dockerfile, enable mod_rewrite
RUN sed -i 's/#LoadModule rewrite_module/LoadModule rewrite_module/' /etc/apache2/httpd.conf

Common Pitfalls

  • Missing /run/apache2 directory: Apache on Alpine requires this directory to store the PID file. Without mkdir -p /run/apache2, Apache fails to start with a cryptic error about not being able to open the PID file.
  • Not running in foreground: Docker containers exit when the main process exits. Apache must run with -D FOREGROUND to stay in the foreground. Without this flag, Apache forks to the background and Docker thinks the container is done.
  • Package name confusion: On Alpine, the package is apache2 but the binary is httpd. On Debian, both the package and the common command are apache2.
  • PHP version in package names: Alpine uses versioned PHP packages (php83, not php). The available version depends on your Alpine release. Check with apk search php to find the correct package names.
  • Log output: By default, Apache logs to files in /var/log/apache2/. For Docker, redirect logs to stdout/stderr by symlinking: ln -sf /dev/stdout /var/log/apache2/access.log && ln -sf /dev/stderr /var/log/apache2/error.log.

Summary

  • Install Apache on Alpine with apk add --no-cache apache2
  • Create /run/apache2 directory for the PID file
  • Run with httpd -D FOREGROUND to keep the container alive
  • Document root is /var/www/localhost/htdocs/ (not /var/www/html/)
  • Use httpd:2.4-alpine from Docker Hub for a pre-configured Alpine Apache image
  • Add -v ./html:/var/www/localhost/htdocs:ro for development volume mounts

Related reading
Course
Beginner
27 lessons
10 hours
System Design Fundamentals

Build a strong foundation in designing scalable, reliable distributed systems.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

System Design practice on Codemia

Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.

Practice system design

All Rights Reserved.