PHP 完全指南 / 第 25 章 — Docker 部署
第 25 章 — Docker 部署:PHP-FPM、Nginx 与多阶段构建
25.1 PHP-FPM + Nginx
Dockerfile
# 多阶段构建
FROM composer:2 AS vendor
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader --no-interaction --prefer-dist
FROM php:8.3-fpm
# 安装系统依赖
RUN apt-get update && apt-get install -y \
libpng-dev libjpeg-dev libfreetype6-dev libzip-dev \
libicu-dev libonig-dev libxml2-dev \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) \
pdo_mysql mbstring zip intl bcmath gd xml opcache \
&& pecl install redis && docker-php-ext-enable redis \
&& apt-get clean && rm -rf /var/lib/apt/lists/*
# OPcache 配置
COPY docker/php/opcache.ini /usr/local/etc/php/conf.d/opcache.ini
# PHP 配置
COPY docker/php/php.ini /usr/local/etc/php/conf.d/custom.ini
# 复制 Composer 依赖
COPY --from=vendor /app/vendor /app/vendor
# 复制应用代码
COPY . /app
WORKDIR /app
# 设置权限
RUN chown -R www-data:www-data /app/storage /app/bootstrap/cache
EXPOSE 9000
CMD ["php-fpm"]
Nginx 配置
# docker/nginx/default.conf
server {
listen 80;
server_name localhost;
root /app/public;
index index.php;
# Gzip
gzip on;
gzip_types text/plain application/json application/javascript text/css;
# 静态文件缓存
location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff2)$ {
expires 1y;
add_header Cache-Control "public, immutable";
}
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass app:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_read_timeout 300;
}
location ~ /\.ht {
deny all;
}
}
25.2 docker-compose.yml
services:
app:
build:
context: .
dockerfile: Dockerfile
volumes:
- .:/app
depends_on:
- mysql
- redis
networks:
- app
nginx:
image: nginx:alpine
ports:
- "8080:80"
volumes:
- .:/app
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- app
networks:
- app
mysql:
image: mysql:8.0
environment:
MYSQL_ROOT_PASSWORD: secret
MYSQL_DATABASE: myapp
MYSQL_USER: app
MYSQL_PASSWORD: app_secret
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- app
redis:
image: redis:7-alpine
ports:
- "6379:6379"
networks:
- app
queue:
build:
context: .
dockerfile: Dockerfile
command: php artisan queue:work --sleep=3 --tries=3
depends_on:
- app
- redis
networks:
- app
volumes:
mysql_data:
networks:
app:
25.3 多阶段构建优化
# 阶段 1:Composer 依赖
FROM composer:2 AS deps
WORKDIR /app
COPY composer.json composer.lock ./
RUN composer install --no-dev --optimize-autoloader
# 阶段 2:前端资源(如有)
FROM node:20-alpine AS frontend
WORKDIR /app
COPY package.json package-lock.json ./
RUN npm ci
COPY . .
RUN npm run build
# 阶段 3:PHP 应用
FROM php:8.3-fpm-alpine
COPY --from=deps /app/vendor /app/vendor
COPY --from=frontend /app/public/build /app/public/build
COPY . /app
WORKDIR /app
25.4 Docker 环境变量
<?php
// .env
// APP_ENV=production
// APP_DEBUG=false
// DB_HOST=mysql
// DB_PORT=3306
// DB_DATABASE=myapp
// DB_USERNAME=app
// DB_PASSWORD=app_secret
// REDIS_HOST=redis
// 使用 vlucas/phpdotenv
$dotenv = Dotenv\Dotenv::createImmutable('/app');
$dotenv->load();
25.5 生产检查清单
# 构建优化
composer install --no-dev --optimize-autoloader
php artisan config:cache
php artisan route:cache
php artisan view:cache
# 安全检查
composer audit
php artisan key:generate
chmod -R 755 storage
25.6 扩展阅读
上一章:第 24 章 — 框架概览 下一章:第 26 章 — CI/CD