Apache HTTP Server 完全指南 / Docker 部署
Docker 部署
Docker 为 Apache 提供了标准化、可移植的部署方式。本章介绍 Apache 的 Docker 化部署和管理。
1. 官方镜像
1.1 基本使用
# 拉取官方镜像
docker pull httpd:2.4
# 运行容器
docker run -d --name apache \
-p 80:80 \
httpd:2.4
# 验证
curl http://localhost/
# 查看日志
docker logs apache
1.2 自定义配置
# 挂载配置文件
docker run -d --name apache \
-p 80:80 \
-v $(pwd)/httpd.conf:/usr/local/apache2/conf/httpd.conf \
-v $(pwd)/website:/usr/local/apache2/htdocs \
httpd:2.4
# 挂载多个配置
docker run -d --name apache \
-p 80:80 \
-v $(pwd)/httpd.conf:/usr/local/apache2/conf/httpd.conf \
-v $(pwd)/extra:/usr/local/apache2/conf/extra \
-v $(pwd)/website:/usr/local/apache2/htdocs \
-v $(pwd)/logs:/usr/local/apache2/logs \
httpd:2.4
1.3 启用模块
# Dockerfile
FROM httpd:2.4
# 启用模块
RUN sed -i \
-e 's/^#\(LoadModule proxy_module\)/\1/' \
-e 's/^#\(LoadModule proxy_http_module\)/\1/' \
-e 's/^#\(LoadModule rewrite_module\)/\1/' \
-e 's/^#\(LoadModule ssl_module\)/\1/' \
-e 's/^#\(LoadModule headers_module\)/\1/' \
-e 's/^#\(LoadModule deflate_module\)/\1/' \
-e 's/^#\(LoadModule expires_module\)/\1/' \
-e 's/^#\(LoadModule cache_module\)/\1/' \
-e 's/^#\(LoadModule cache_disk_module\)/\1/' \
conf/httpd.conf
# 复制自定义配置
COPY httpd.conf /usr/local/apache2/conf/httpd.conf
COPY extra/ /usr/local/apache2/conf/extra/
# 复制网站文件
COPY website/ /usr/local/apache2/htdocs/
2. 自定义镜像
2.1 基本 Dockerfile
# Dockerfile
FROM httpd:2.4
# 安装依赖
RUN apt-get update && apt-get install -y \
libapache2-mod-security2 \
&& rm -rf /var/lib/apt/lists/*
# 启用模块
RUN a2enmod rewrite ssl headers deflate expires
# 复制配置
COPY httpd.conf /usr/local/apache2/conf/httpd.conf
COPY extra/ /usr/local/apache2/conf/extra/
# 创建日志目录
RUN mkdir -p /usr/local/apache2/logs
# 复制网站
COPY website/ /usr/local/apache2/htdocs/
# 暴露端口
EXPOSE 80 443
# 健康检查
HEALTHCHECK --interval=30s --timeout=5s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# 启动 Apache
CMD ["httpd-foreground"]
2.2 多阶段构建
# 构建阶段
FROM httpd:2.4 AS builder
# 安装构建工具
RUN apt-get update && apt-get install -y \
build-essential \
libpcre3-dev \
libssl-dev \
&& rm -rf /var/lib/apt/lists/*
# 编译自定义模块
COPY modules/ /tmp/modules/
RUN cd /tmp/modules && \
/usr/local/apache2/bin/apxs -cia mod_custom.c
# 运行阶段
FROM httpd:2.4
# 从构建阶段复制模块
COPY --from=builder /usr/local/apache2/modules/mod_custom.so \
/usr/local/apache2/modules/
# 配置
COPY httpd.conf /usr/local/apache2/conf/httpd.conf
EXPOSE 80
CMD ["httpd-foreground"]
2.3 PHP-FPM 集成
# Dockerfile.apache
FROM httpd:2.4
# 启用代理模块
RUN sed -i \
-e 's/^#\(LoadModule proxy_module\)/\1/' \
-e 's/^#\(LoadModule proxy_fcgi_module\)/\1/' \
-e 's/^#\(LoadModule rewrite_module\)/\1/' \
-e 's/^#\(LoadModule deflate_module\)/\1/' \
conf/httpd.conf
# 添加 PHP-FPM 配置
RUN echo 'ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://php:9000/var/www/html/$1' >> \
conf/httpd.conf
COPY website/ /usr/local/apache2/htdocs/
EXPOSE 80
CMD ["httpd-foreground"]
3. Docker Compose
3.1 基本 Compose 配置
# docker-compose.yml
version: '3.8'
services:
apache:
image: httpd:2.4
container_name: apache
ports:
- "80:80"
- "443:443"
volumes:
- ./httpd.conf:/usr/local/apache2/conf/httpd.conf
- ./extra:/usr/local/apache2/conf/extra
- ./website:/usr/local/apache2/htdocs
- ./logs:/usr/local/apache2/logs
- ./ssl:/usr/local/apache2/conf/ssl
restart: unless-stopped
networks:
- web
networks:
web:
driver: bridge
3.2 Apache + PHP-FPM
version: '3.8'
services:
apache:
build:
context: ./apache
dockerfile: Dockerfile
ports:
- "80:80"
- "443:443"
volumes:
- ./website:/var/www/html
- ./apache/httpd.conf:/usr/local/apache2/conf/httpd.conf
- ./logs/apache:/var/log/apache2
depends_on:
- php
restart: unless-stopped
networks:
- web
php:
image: php:8.2-fpm
container_name: php-fpm
volumes:
- ./website:/var/www/html
- ./php/www.conf:/usr/local/etc/php-fpm.d/www.conf
- ./php/php.ini:/usr/local/etc/php/php.ini
restart: unless-stopped
networks:
- web
networks:
web:
driver: bridge
3.3 Apache + MySQL + PHP
version: '3.8'
services:
apache:
build: ./apache
ports:
- "80:80"
- "443:443"
volumes:
- ./website:/var/www/html
depends_on:
- php
- mysql
restart: unless-stopped
networks:
- web
php:
image: php:8.2-fpm
volumes:
- ./website:/var/www/html
- ./php/www.conf:/usr/local/etc/php-fpm.d/www.conf
depends_on:
- mysql
restart: unless-stopped
networks:
- web
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
MYSQL_DATABASE: ${MYSQL_DATABASE}
MYSQL_USER: ${MYSQL_USER}
MYSQL_PASSWORD: ${MYSQL_PASSWORD}
volumes:
- mysql_data:/var/lib/mysql
restart: unless-stopped
networks:
- web
phpmyadmin:
image: phpmyadmin/phpmyadmin
environment:
PMA_HOST: mysql
PMA_PORT: 3306
ports:
- "8080:80"
depends_on:
- mysql
restart: unless-stopped
networks:
- web
volumes:
mysql_data:
networks:
web:
driver: bridge
3.4 WordPress 部署
version: '3.8'
services:
apache:
build: ./apache
ports:
- "80:80"
volumes:
- wordpress_data:/var/www/html
depends_on:
- php
- mysql
restart: unless-stopped
php:
image: php:8.2-fpm
volumes:
- wordpress_data:/var/www/html
restart: unless-stopped
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: root_password
MYSQL_DATABASE: wordpress
MYSQL_USER: wordpress
MYSQL_PASSWORD: wordpress_password
volumes:
- mysql_data:/var/lib/mysql
restart: unless-stopped
volumes:
wordpress_data:
mysql_data:
4. 配置管理
4.1 环境变量
# Dockerfile
FROM httpd:2.4
# 环境变量
ENV APACHE_SERVER_NAME=www.example.com
ENV APACHE_SERVER_ADMIN=admin@example.com
ENV APACHE_DOCUMENT_ROOT=/usr/local/apache2/htdocs
# 使用 envsubst 生成配置
RUN apt-get update && apt-get install -y gettext-base
COPY httpd.conf.template /usr/local/apache2/conf/httpd.conf.template
COPY entrypoint.sh /entrypoint.sh
RUN chmod +x /entrypoint.sh
ENTRYPOINT ["/entrypoint.sh"]
CMD ["httpd-foreground"]
#!/bin/bash
# entrypoint.sh
# 生成配置文件
envsubst '${APACHE_SERVER_NAME} ${APACHE_SERVER_ADMIN} ${APACHE_DOCUMENT_ROOT}' \
< /usr/local/apache2/conf/httpd.conf.template \
> /usr/local/apache2/conf/httpd.conf
# 执行原始入口点
exec "$@"
# httpd.conf.template
ServerName ${APACHE_SERVER_NAME}
ServerAdmin ${APACHE_SERVER_ADMIN}
DocumentRoot ${APACHE_DOCUMENT_ROOT}
4.2 配置文件挂载
version: '3.8'
services:
apache:
image: httpd:2.4
volumes:
# 主配置
- ./config/httpd.conf:/usr/local/apache2/conf/httpd.conf
# 虚拟主机配置
- ./config/vhosts:/usr/local/apache2/conf/vhosts
# SSL 证书
- ./ssl/certs:/usr/local/apache2/conf/ssl/certs:ro
- ./ssl/private:/usr/local/apache2/conf/ssl/private:ro
# 网站文件
- ./website:/usr/local/apache2/htdocs
# 日志
- ./logs:/usr/local/apache2/logs
4.3 秘密管理
version: '3.8'
services:
apache:
image: httpd:2.4
secrets:
- ssl_cert
- ssl_key
- htpasswd
volumes:
- ./website:/usr/local/apache2/htdocs
secrets:
ssl_cert:
file: ./ssl/certs/server.crt
ssl_key:
file: ./ssl/private/server.key
htpasswd:
file: ./config/.htpasswd
5. 生产环境部署
5.1 优化 Dockerfile
FROM httpd:2.4-alpine
# 安装必要工具
RUN apk add --no-cache \
curl \
openssl
# 创建非 root 用户
RUN addgroup -g 1000 apache && \
adduser -u 1000 -G apache -s /bin/sh -D apache
# 启用模块
RUN sed -i \
-e 's/^#\(LoadModule rewrite_module\)/\1/' \
-e 's/^#\(LoadModule ssl_module\)/\1/' \
-e 's/^#\(LoadModule headers_module\)/\1/' \
-e 's/^#\(LoadModule deflate_module\)/\1/' \
-e 's/^#\(LoadModule expires_module\)/\1/' \
conf/httpd.conf
# 复制配置
COPY httpd.conf /usr/local/apache2/conf/httpd.conf
COPY ssl/ /usr/local/apache2/conf/ssl/
# 创建必要目录
RUN mkdir -p /usr/local/apache2/logs && \
chown -R apache:apache /usr/local/apache2
# 设置权限
COPY --chown=apache:apache website/ /usr/local/apache2/htdocs/
# 健康检查
HEALTHCHECK --interval=30s --timeout=5s --start-period=10s --retries=3 \
CMD curl -f http://localhost/ || exit 1
# 暴露端口
EXPOSE 80 443
# 使用非 root 用户
USER apache
# 启动命令
CMD ["httpd-foreground"]
5.2 安全配置
version: '3.8'
services:
apache:
build: .
ports:
- "80:80"
- "443:443"
volumes:
- ./website:/usr/local/apache2/htdocs:ro
- ./logs:/usr/local/apache2/logs
# 安全选项
read_only: true
tmpfs:
- /tmp
security_opt:
- no-new-privileges:true
cap_drop:
- ALL
cap_add:
- NET_BIND_SERVICE
# 资源限制
deploy:
resources:
limits:
cpus: '2.0'
memory: 512M
reservations:
cpus: '0.5'
memory: 128M
restart: unless-stopped
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "3"
6. CI/CD 集成
6.1 自动构建
# .github/workflows/docker.yml
name: Build and Push
on:
push:
branches: [main]
pull_request:
branches: [main]
jobs:
build:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Build Docker image
run: docker build -t my-apache:${{ github.sha }} .
- name: Test Docker image
run: |
docker run -d --name test -p 80:80 my-apache:${{ github.sha }}
sleep 5
curl -f http://localhost/ || exit 1
docker stop test
- name: Push to Registry
if: github.ref == 'refs/heads/main'
run: |
docker tag my-apache:${{ github.sha }} registry.example.com/my-apache:latest
docker push registry.example.com/my-apache:latest
6.2 多环境部署
# docker-compose.prod.yml
version: '3.8'
services:
apache:
image: registry.example.com/my-apache:${IMAGE_TAG:-latest}
ports:
- "80:80"
- "443:443"
volumes:
- /data/website:/usr/local/apache2/htdocs
- /data/logs/apache:/usr/local/apache2/logs
- /etc/ssl/certs:/usr/local/apache2/conf/ssl/certs:ro
- /etc/ssl/private:/usr/local/apache2/conf/ssl/private:ro
environment:
- APACHE_SERVER_NAME=www.example.com
- APACHE_ENV=production
deploy:
replicas: 3
update_config:
parallelism: 1
delay: 30s
restart_policy:
condition: on-failure
networks:
- web
7. 监控与日志
7.1 Docker 日志
version: '3.8'
services:
apache:
image: httpd:2.4
logging:
driver: "json-file"
options:
max-size: "10m"
max-file: "5"
tag: "apache"
volumes:
- ./logs:/usr/local/apache2/logs
7.2 Prometheus 监控
version: '3.8'
services:
apache:
image: httpd:2.4
# ...
apache-exporter:
image: lusotycoon/apache-exporter
command: --scrape_uri=http://apache/server-status?auto
depends_on:
- apache
networks:
- monitoring
prometheus:
image: prom/prometheus
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
networks:
- monitoring
grafana:
image: grafana/grafana
ports:
- "3000:3000"
networks:
- monitoring
8. 备份与恢复
8.1 备份脚本
#!/bin/bash
# backup-apache.sh
BACKUP_DIR="/backup/apache/$(date +%Y%m%d)"
mkdir -p $BACKUP_DIR
# 备份配置
docker cp apache:/usr/local/apache2/conf $BACKUP_DIR/conf
# 备份网站文件
docker cp apache:/usr/local/apache2/htdocs $BACKUP_DIR/htdocs
# 备份日志
docker cp apache:/usr/local/apache2/logs $BACKUP_DIR/logs
# 备份 Docker 配置
cp docker-compose.yml $BACKUP_DIR/
cp Dockerfile $BACKUP_DIR/
# 压缩
tar -czf $BACKUP_DIR.tar.gz -C /backup/apache $(date +%Y%m%d)
rm -rf $BACKUP_DIR
echo "备份完成: $BACKUP_DIR.tar.gz"
8.2 恢复脚本
#!/bin/bash
# restore-apache.sh
BACKUP_FILE=$1
if [ -z "$BACKUP_FILE" ]; then
echo "用法: $0 <backup-file.tar.gz>"
exit 1
fi
# 解压
tar -xzf $BACKUP_FILE -C /tmp/
# 停止容器
docker stop apache
# 恢复配置
docker cp /tmp/*/conf apache:/usr/local/apache2/
# 恢复网站
docker cp /tmp/*/htdocs apache:/usr/local/apache2/
# 启动容器
docker start apache
# 清理
rm -rf /tmp/*
echo "恢复完成"
9. 业务场景
9.1 微服务架构
version: '3.8'
services:
# API 网关
gateway:
build: ./gateway
ports:
- "80:80"
- "443:443"
# 用户服务
user-service:
build: ./user-service
# 订单服务
order-service:
build: ./order-service
# 产品服务
product-service:
build: ./product-service
9.2 开发环境
version: '3.8'
services:
apache:
build: ./apache
ports:
- "80:80"
volumes:
- ./website:/usr/local/apache2/htdocs
- ./apache/httpd.conf:/usr/local/apache2/conf/httpd.conf
environment:
- APACHE_ENV=development
10. 注意事项
- 镜像选择:生产环境使用 Alpine 镜像减小体积
- 安全扫描:定期扫描镜像漏洞
- 资源限制:设置 CPU 和内存限制
- 日志管理:配置日志轮转,避免磁盘占满
- 健康检查:配置健康检查确保服务可用
11. 扩展阅读
12. 总结
Docker 为 Apache 部署带来了巨大优势:
- 标准化:统一的构建和部署流程
- 可移植:环境一致,避免"在我机器上能运行"
- 可扩展:轻松水平扩展
- 版本控制:配置和镜像版本化管理
结合 Docker Compose 和 CI/CD,可以实现高效的 Apache 部署和管理。