强曰为道

与天地相似,故不违。知周乎万物,而道济天下,故不过。旁行而不流,乐天知命,故不忧.
文档目录

第 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