- 示例工程
【免费下载链接】awesome-compose
Awesome Docker Compose samples
本指南围绕 awesome-compose 仓库中 apache-php 示例展开,讲解如何用 Docker Compose 将一个最简 PHP 应用与 Apache2 Web 服务器打包、构建、启动、验证并清理。读完本文,你将掌握compose.yaml中构建上下文、端口映射、卷挂载等核心配置的实战写法,理解官方 PHP-Apache 镜像的多阶段构建机制,并能独立复现从docker compose up -d到curl localhost:80的完整部署闭环。
示例概览:一个"单服务"PHP 应用的样板
apache-php 是 awesome-compose 仓库中典型的**单服务(single service)**示例,其定位在仓库根 README.md 中被明确归类为 "Single service samples"。它的用途不是演示多容器协作,而是展示最基础也最常用的一种容器化形态:把一个带 Apache2 的 PHP 应用通过 Compose 一条命令跑起来。
该示例的完整目录结构如下(与文档一致):
. ├── compose.yaml # Compose 编排文件(服务定义入口) └── app ├── Dockerfile # PHP + Apache2 镜像构建脚本 └── index.php # 唯一的路由/页面入口整条链路只有两个角色:compose.yaml负责描述服务,app/目录负责承载应用代码与镜像构建逻辑。
核心配置解析:compose.yaml
文档给出了示例的服务编排配置,当前仓库中的实际文件 compose.yaml 内容如下:
services: web: build: context: app target: builder ports: - '80:80' volumes: - ./app:/var/www/html/相比文档中的简写build: app,仓库当前版本使用了build.context+build.target的完整写法,语义上更精确。逐项拆解:
services.web:定义一个名为web的服务,这是本示例唯一的服务,后续docker compose up默认启动它。build.context: app:构建上下文为app目录,Docker 会以该目录为基准解析Dockerfile与 COPY 的源路径。注意 Compose 会自动在该上下文内查找名为Dockerfile的构建文件。build.target: builder:指定多阶段构建的目标阶段为builder(对应 Dockerfile 中的AS builder)。这保证了默认部署时只产出轻量的运行镜像,而不会把后文提到的开发工具阶段(dev-envs)带入运行产物。ports: - '80:80':将容器内 Apache 的 80 端口映射到宿主机的 80 端口,'80:80'是hostPort:containerPort的标准写法。若宿主机 80 端口被占用,可自行改为如'8080:80'。volumes: - ./app:/var/www/html/:把宿主机app/目录挂载为容器内 Apache 文档根目录/var/www/html/。Apache 的默认站点根目录正是/var/www/html,因此容器启动后即可直接以/var/www/html/index.php作为首页入口。
这里有一个值得强调的实战要点:卷挂载意味着应用代码不在镜像内、而在宿主机上实时可见。修改app/index.php后无需重新构建镜像,刷新浏览器即可生效,非常适合本地开发调试。
应用源码与 Dockerfile 深度解析
页面入口 index.php
app/index.php 是整个应用的唯一业务代码:
<?php echo '<h1>Hello World!</h1>'; ?>它通过 PHP 直接输出一个一级标题Hello World!。由于 Apache 的mod_php处理.php请求,当浏览器访问根路径时,Apache 会把请求交给 PHP 解释器执行该文件,并把渲染后的 HTML 返回客户端。
说明:文档中
curl localhost:80的示例输出为纯文本Hello World!,那是示例早期版本(无 HTML 标签)的返回结果;当前仓库 index.php 会返回带<h1>标签的 HTML 内容,实际 curl 输出为<h1>Hello World!</h1>。
多阶段 Dockerfile
app/Dockerfile 采用多阶段构建,整体结构如下:
# syntax=docker/dockerfile:1.4 FROM --platform=$BUILDPLATFORM php:8.0.9-apache as builder CMD ["apache2-foreground"] FROM builder as dev-envs RUN <<EOF apt-get update apt-get install -y --no-install-recommends git EOF RUN <<EOF useradd -s /bin/bash -m vscode groupadd docker usermod -aG docker vscode EOF # install Docker tools (cli, buildx, compose) COPY --from=gloursdocker/docker / / CMD ["apache2-foreground"]几个值得展开的关键点:
- 基础镜像
php:8.0.9-apache:这是官方 PHP 镜像的 Apache 变体,内置 Apache2 与 PHP 模块。文档部署日志中出现的php:7.2-apache是示例早期使用的镜像版本,当前仓库已升级到 8.0.9。 --platform=$BUILDPLATFORM:配合 BuildKit 的跨平台构建能力,允许在不同架构的宿主机上为构建阶段选取合适的平台,提升多架构构建效率。CMD ["apache2-foreground"]:以前台模式启动 Apache,保证容器主进程持续运行且日志直接输出到 stdout,这是容器内运行 Web 服务的标准姿势(容器内不能用service apache2 start这类后台启动方式)。dev-envs阶段:在builder基础上追加 git、vscode用户、docker 用户组以及 Docker CLI 工具链,专供开发容器(如 Dev Containers)使用。由于 compose.yaml 的target: builder指向了builder阶段,默认部署不会携带这些开发依赖,镜像更精简。- Dockerfile 语法
# syntax=docker/dockerfile:1.4:启用 Dockerfile 1.4 语法,从而支持RUN <<EOF这种 heredoc 写法与COPY --from跨阶段拷贝等 BuildKit 特性。
一键部署:docker compose up -d
进入示例根目录执行部署命令:
$ docker compose up -d-d(detached)让容器在后台运行。文档中展示的典型构建与启动日志如下:
Creating network "php-docker_web" with the default driver Building web Step 1/6 : FROM php:7.2-apache ... ... Creating php-docker_web_1 ... done日志中的两处细节值得注意:
- 网络名与容器名:Compose 默认以所在目录名作为 project 名,并以此派生网络、卷与容器名。
php-docker_web、php-docker_web_1表明该示例早期位于名为php-docker的目录中;当前目录名为apache-php,因此实际生成的名字会是apache-php_web、apache-php-web-1。若想显式控制 project 名,可用docker compose -p <name> up -d指定。 - 首次构建耗时:首次执行需要拉取
php:8.0.9-apache基础镜像并完成构建,日志中的Step 1/6即对应 Dockerfile 的逐步执行;再次启动时镜像已缓存,速度会快得多。
验证运行结果
部署完成后,先检查容器与端口映射是否符合预期:
$ docker ps CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 2bc8271fee81 apache-php_web "docker-php-entrypoi…" About a minute ago Up About a minute 0.0.0.0:80->80/tcp apache-php-web-1关键信息解读:
STATUS: Up:容器正常运行,说明apache2-foreground前台进程没有退出;PORTS: 0.0.0.0:80->80/tcp:宿主机 80 端口已成功映射到容器 80 端口;NAMES:容器名遵循{project}-{service}-{序号}规则。
随后在浏览器访问http://localhost:80,或直接用 curl 验证:
$ curl localhost:80 <h1>Hello World!</h1>返回的<h1>Hello World!</h1>正是 index.php 中echo的输出,证明"浏览器 → Apache2 → mod_php → index.php"整条请求链路已打通。若使用-i参数还能看到HTTP/1.1 200 OK状态码与Content-Type: text/html响应头。
停止与清理
开发或测试结束后,用以下命令停止并移除容器:
$ docker compose down该命令会按 Compose 项目维度清理:停止并删除web容器、移除由up创建的默认网络。若还需一并删除挂载卷或构建缓存,可扩展使用:
$ docker compose down -v # 同时删除该项目的匿名卷 $ docker build --no-cache # 需要强制重建镜像时跳过缓存注意:本示例通过卷将宿主机
./app映射进容器,应用数据存于宿主机,因此down不会丢失代码。
关键机制与注意事项小结
- 文档与仓库的版本差异属正常演进:README 中
php:7.2-apache、简写build: app与纯文本Hello World!均来自示例早期版本,当前仓库的 compose.yaml、Dockerfile、index.php 已升级为 PHP 8.0.9 多阶段构建形态,实操时以仓库现行为准。 - 卷挂载是开发利器也是生产隐患:
./app:/var/www/html/让代码改动即时生效,省去重建镜像;但生产环境通常应把代码 COPY 进镜像、去掉卷映射,以获得可复现的交付物。 - 镜像必须前台运行:容器存活的前提是主进程不退出,
CMD ["apache2-foreground"]正是为容器化定制的启动方式,勿改成 Apache 默认的后台守护模式。 - 适用范围:与仓库根 README.md 的声明一致,本示例面向本地开发环境(项目初始化、技术栈验证等),不应直接用于生产部署。
至此,从配置解读、镜像构建、一键部署到结果验证与清理回收,你已经完整掌握了 apache-php 示例的全部实战链路,这套"compose.yaml+app/"的组织模式同样适用于迁移到你自己的 PHP 项目。
- 示例工程
【免费下载链接】awesome-compose
Awesome Docker Compose samples
相关推荐
Firefox Send 容器化部署指南:基于 Docker 与 docker-compose 的完整实战
Firefox Send 容器化部署指南:基于 Docker 与 docker compose 的完整实战 本篇技术指南以 Firefox Send 官方文档
后端前端Spark Java 应用容器化部署实战:基于 Awesome Compose 的 Docker Compose 单服务示例
Spark Java 应用容器化部署实战:基于 Awesome Compose 的 Docker Compose 单服务示例 本篇技术指南以仓库中的 spark
示例工程使用 PHP mysqli 扩展连接 Apache Doris:完整示例与实战指南
使用 PHP mysqli 扩展连接 Apache Doris:完整示例与实战指南 导读 Apache Doris 对外提供 MySQL 协议兼容的访问接口(默
OLAP数据库大数据实时分析
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考