TechEarl

How to Run Apache in Docker

Apache httpd in a Docker container: serve static files, mount a custom httpd.conf, enable mod_rewrite for .htaccess, and the patterns that come up most often (PHP, reverse proxy, virtual hosts).

Ishan KarunaratneIshan Karunaratne⏱️ 4 min readUpdated
Share thisCopied

Apache in Docker uses the official httpd image. The image is bare-bones — no PHP, no fancy modules pre-enabled beyond the defaults — so the recipes split into "static site server" (which works out of the box) and "do something more" (which means mounting a custom config or switching to a related image like php:apache).

How do I run Apache in Docker?

Serve the current directory as a static site:

bash
docker run -d --name apache \
  -p 8080:80 \
  -v "$(pwd):/usr/local/apache2/htdocs:ro" \
  httpd:2.4

Visit http://localhost:8080 — anything in the host directory is served.

Try it with your own values

Configure version, port, and the directory to serve.

Mount a custom httpd.conf

The image's config lives at /usr/local/apache2/conf/httpd.conf. To override:

bash
docker run -d --name :container_name \
  -p :host_port:80 \
  -v "$(pwd)/httpd.conf:/usr/local/apache2/conf/httpd.conf:ro" \
  -v ":site_dir:/usr/local/apache2/htdocs:ro" \
  httpd::httpd_version

Start from the image's own config as a base — copy it out first:

bash
docker run --rm httpd::httpd_version cat /usr/local/apache2/conf/httpd.conf > httpd.conf

Then edit locally and mount it back in.

Enable mod_rewrite (for .htaccess)

mod_rewrite is built into the image but not loaded by default. Without it, .htaccess files with RewriteRule are silently ignored. Two changes to the config:

apache
# Uncomment this line
LoadModule rewrite_module modules/mod_rewrite.so

# In the <Directory "/usr/local/apache2/htdocs"> block, change
AllowOverride None
# to
AllowOverride All

After mounting the edited config and restarting, .htaccess rules work.

Run as non-root

The official httpd image runs as root by default and starts worker processes as www-data. For a tighter setup, the httpd:2.4-alpine variant is smaller; for a non-root-by-default option, the bitnami/apache image is the common pick (listens on 8080 by default, runs entirely as user 1001).

Pair with PHP

For Apache plus PHP (a common LAMP stack), don't try to install PHP into the httpd image — use the php:apache image, which is httpd with mod_php baked in:

bash
docker run -d --name app \
  -p :host_port:80 \
  -v "$(pwd):/var/www/html" \
  php:8.4-apache

Document root is /var/www/html. PHP files in the bind-mounted directory just work.

Reverse proxy with mod_proxy

Less common than Nginx for reverse-proxy duty, but Apache can do it via mod_proxy:

apache
ProxyPreserveHost On
ProxyPass / http://app:3000/
ProxyPassReverse / http://app:3000/

mod_proxy is built in; load it the same way as mod_rewrite. For new reverse-proxy setups, Nginx or Caddy are more common picks; Apache fits when you already have Apache modules in play.

Compose example

yaml
services:
  apache:
    image: httpd::httpd_version
    ports:
      - "::host_port:80"
    volumes:
      - ./site:/usr/local/apache2/htdocs:ro
      - ./httpd.conf:/usr/local/apache2/conf/httpd.conf:ro
    restart: unless-stopped

Common pitfalls

  • .htaccess ignored. mod_rewrite not loaded, or AllowOverride None for the document root. Fix both in httpd.conf.
  • 404 on index.php. Wrong image — the plain httpd image has no PHP. Use php:VERSION-apache.
  • Permission errors on bind mount. Apache reads as www-data (UID 33). Ensure the host directory is world-readable, or run the file mounts read-only with :ro.
  • Port 80 in use on the host. Pick a different host port (-p 8080:80).
  • Editing httpd.conf and not seeing changes. Either the bind mount isn't pointing where you think, or you need to restart the container (docker restart :container_name). Apache doesn't reload config without a restart or apachectl graceful inside the container.

FAQ

Sources

Authoritative references this article was fact-checked against.

TagsDockerApachehttpdWeb Server.htaccessDevOps

Found this useful? Pass it on.

Copied
Ishan Karunaratne

Ishan Karunaratne

Tech Architect · Software Engineer · AI/DevOps

Tech architect and software engineer with 20+ years building software, Linux systems, and DevOps infrastructure, and lately working AI into the stack. Currently Chief Technology Officer at a healthcare tech startup, which is where most of these field notes come from.

Keep reading

Related posts

H

How to Run Nginx in Docker

Serve static files, mount a custom nginx.conf, run as non-root, and the practical patterns: dev server, reverse proxy in front of an app, and the SSL gotcha most tutorials skip.

A practical DNS health check walkthrough. Cover NS, A, AAAA, MX, SPF, DKIM, DMARC, CAA, DNSSEC in one pass, with real examples and fixes for the most common misconfigurations.

How to Run a DNS Health Check on Your Domain

A practical DNS health check covers nameservers, A and AAAA records, MX, SPF, DKIM, DMARC, and CAA. Here is the full checklist, what each record actually tells you, and how to verify all of them in one pass.