Docker 与 PHP:高级应用容器化
使用 Docker 对 PHP 应用进行容器化早已不仅仅是便捷的开发工具。在高级层面,它是创建可扩展、安全且可重现环境的关键。本文将探讨帮助你从基础 PHP 容器启用到专业编排的技术:多阶段构建、镜像优化、使用 Docker Compose 进行微服务架构以及高级缓存。
1. 多阶段构建:最小化最终镜像
标准 Docker 镜像的主要问题之一是其大小。基础 php:8.2-apache 镜像重量超过 400 MB,安装扩展后可达 600+ MB。这对生产环境是不可接受的:大镜像加载缓慢,占用仓库空间,并增加攻击面。
多阶段构建允许将过程分为多个阶段:一个用于编译和安装依赖(包含全套工具),另一个用于最小运行时环境。最终镜像仅包含编译后的制品和必要的库。
Laravel 应用的 Dockerfile 示例:
# 第一阶段:编译和安装依赖FROM composer:latest AS vendorWORKDIR /appCOPY composer.json composer.lock ./RUN composer install --no-dev --optimize-autoloader --no-interaction
# 第二阶段:构建 Node 资源(如果有前端)FROM node:18-alpine AS frontendWORKDIR /appCOPY package.json package-lock.json ./RUN npm ci --productionCOPY resources/ ./resources/RUN npm run production
# 第三阶段:最终 PHP 镜像FROM php:8.2-fpm-alpine AS productionRUN docker-php-ext-install pdo_mysql opcacheCOPY --from=vendor /app/vendor /var/www/html/vendorCOPY --from=frontend /app/public/build /var/www/html/public/buildCOPY . /var/www/html
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cacheEXPOSE 9000CMD ["php-fpm"]此方法将镜像大小从 500+ MB 减少到约 120 MB。composer:latest 和 node:18-alpine 仅在构建阶段使用,不会进入最终层。
2. 优化 Docker 层缓存
Dockerfile 中的每条指令都会创建一个层。为加速重新构建,应尽可能将不常变化的层放在前面。对于 PHP 项目,这意味着:
- 在复制代码之前,先复制
composer.json和composer.lock。 - 在复制源文件之前,运行
composer install。 - 最后复制代码。
优化指令顺序示例:
FROM php:8.2-fpm-alpine AS baseWORKDIR /var/www/html
# 一次性安装系统依赖RUN apk add --no-cache $PHPIZE_DEPS \ && docker-php-ext-install pdo_mysql opcache bcmath
# 仅复制依赖文件COPY composer.json composer.lock ./RUN composer install --no-dev --no-interaction --no-scripts --prefer-dist
# 复制其余代码COPY . .
# 生成并优化自动加载器RUN composer dump-autoload --optimize提示:使用 .dockerignore 排除 vendor、.git、node_modules 及其他临时文件,这能加快将上下文传输到 Docker 守护进程的速度。
3. Docker Compose 用于微服务架构
现代 PHP 应用很少由单一服务组成。典型架构包括 PHP-FPM、Nginx、Redis、任务队列(RabbitMQ/Beanstalkd)和数据库。Docker Compose 允许你在单个 docker-compose.yml 中描述整个基础设施。
PHP 微服务的配置示例:
version: '3.8'services: app: build: context: . target: production