Laravel 11 生产级容器化部署基于 tangramor/nginx-php8-fpm 镜像的完整实践指南1. 为什么选择定制化镜像在 Laravel 项目的容器化部署中开发环境与生产环境的需求差异显著。官方 Sail 虽然提供了开箱即用的开发体验但其默认配置并不适合直接用于生产环境。tangramor/nginx-php8-fpm 镜像针对生产场景做了多项优化轻量化基础基于 Alpine Linux 构建镜像体积仅 400MB压缩后不到 200MB相比标准开发环境节省 40% 以上空间性能优化预配置 OPcache、JIT 编译等 PHP 8 性能增强特性安全加固默认禁用危险函数、配置合理的文件权限、包含基础安全头设置多服务集成单镜像集成 Nginx 1.23 PHP 8.2 FPM Node.js 20避免多容器通信开销# 基础镜像选择示例 FROM php:8.2-fpm-alpine AS base FROM node:20-alpine AS node FROM nginx:1.23-alpine AS nginx2. 生产级 Dockerfile 构建2.1 基础配置创建以下 Dockerfile 作为项目根目录的构建模板FROM tangramor/nginx-php8-fpm # 设置中国区镜像源可选 ARG APKMIRRORmirrors.ustc.edu.cn ARG COMPOSERMIRRORhttps://mirrors.cloud.tencent.com/composer/ ARG NPMMIRRORhttps://registry.npmmirror.com # 时区与目录配置 ENV TZAsia/Shanghai \ WEBROOT/var/www/html/public \ PHP_REDIS_SESSION_HOSTredis \ CREATE_LARAVEL_STORAGE1 # 复制项目文件 COPY . /var/www/html # 构建阶段 RUN set -eux; \ # 配置镜像源 [ -n $APKMIRROR ] sed -i s/dl-cdn.alpinelinux.org/${APKMIRROR}/g /etc/apk/repositories; \ # 安装构建依赖 apk add --no-cache --virtual .build-deps \ gcc \ g \ libc-dev \ make; \ # 配置 npm 镜像 npm config set registry ${NPMMIRROR}; \ # 安装前端依赖 npm install npm run prod; \ # 安装 PHP 依赖 composer config -g repos.packagist composer ${COMPOSERMIRROR}; \ composer install --no-dev --optimize-autoloader; \ # 清理 apk del .build-deps; \ # 权限设置 chown -R nginx:nginx /var/www/html2.2 关键优化点依赖管理使用--no-dev避免安装开发依赖--optimize-autoloader优化自动加载性能构建缓存# 单独复制依赖描述文件以利用缓存 COPY composer.json composer.lock package.json package-lock.json /var/www/html/ RUN composer install --no-dev --optimize-autoloader \ npm install npm run prod COPY . .多阶段构建可选FROM tangramor/nginx-php8-fpm AS final COPY --frombuilder /var/www/html /var/www/html3. Docker Compose 生产配置3.1 完整服务编排创建docker-compose.prod.yml文件version: 3.8 services: app: build: . image: your-registry/laravel-app:${TAG:-latest} restart: unless-stopped env_file: .env.prod environment: - APP_ENVproduction - APP_DEBUGfalse volumes: - storage:/var/www/html/storage - logs:/var/log/nginx depends_on: - redis - db db: image: mysql:8.0 restart: unless-stopped command: --default-authentication-pluginmysql_native_password volumes: - mysql_data:/var/lib/mysql environment: MYSQL_ROOT_PASSWORD: ${DB_ROOT_PASSWORD} MYSQL_DATABASE: ${DB_DATABASE} MYSQL_USER: ${DB_USERNAME} MYSQL_PASSWORD: ${DB_PASSWORD} redis: image: redis:7-alpine restart: unless-stopped volumes: - redis_data:/data scheduler: image: your-registry/laravel-app:${TAG:-latest} restart: unless-stopped command: | bash -c while true; do php /var/www/html/artisan schedule:run --verbose --no-interaction; sleep 60; done depends_on: - app - db - redis volumes: mysql_data: redis_data: storage: logs:3.2 关键配置说明配置项生产环境建议说明restartunless-stopped确保服务异常退出后自动重启APP_DEBUGfalse必须关闭调试模式数据库认证mysql_native_password兼容性更好的认证方式计划任务独立容器避免影响 Web 服务稳定性提示通过docker-compose -f docker-compose.prod.yml up -d启动生产环境4. 性能调优实战4.1 PHP-FPM 配置优化在项目根目录创建docker/php/php-fpm.conf[www] pm dynamic pm.max_children 50 pm.start_servers 5 pm.min_spare_servers 5 pm.max_spare_servers 35 pm.max_requests 500 ; 针对 Laravel 的优化 php_admin_value[memory_limit] 256M php_admin_value[opcache.memory_consumption] 128 php_admin_value[opcache.interned_strings_buffer] 16 php_admin_value[opcache.max_accelerated_files] 200004.2 Nginx 优化配置创建docker/nginx/nginx.confworker_processes auto; events { worker_connections 1024; multi_accept on; } http { # 基础优化 sendfile on; tcp_nopush on; tcp_nodelay on; keepalive_timeout 65; types_hash_max_size 2048; server_tokens off; # Laravel 特定配置 fastcgi_read_timeout 300; client_max_body_size 100m; include /etc/nginx/mime.types; default_type application/octet-stream; # 日志格式 log_format main $remote_addr - $remote_user [$time_local] $request $status $body_bytes_sent $http_referer $http_user_agent; # Gzip 压缩 gzip on; gzip_disable msie6; gzip_vary on; gzip_proxied any; gzip_comp_level 6; gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xmlrss text/javascript; include /etc/nginx/conf.d/*.conf; }5. 安全加固措施5.1 镜像安全扫描# 使用 Trivy 扫描镜像漏洞 docker build -t your-app . trivy image your-app # 使用 Dive 分析镜像层 dive your-app5.2 关键安全配置文件权限RUN chown -R nginx:nginx /var/www/html \ find /var/www/html -type f -exec chmod 644 {} \; \ find /var/www/html -type d -exec chmod 755 {} \; \ chmod -R 775 storage bootstrap/cache环境变量保护# 生成应用密钥 openssl rand -base64 32 | head -c 32 | base64CSP 头设置在 Nginx 配置中add_header Content-Security-Policy default-src self; script-src self unsafe-inline cdn.jsdelivr.net; style-src self unsafe-inline cdn.jsdelivr.net; img-src self data:; font-src self cdn.jsdelivr.net;;6. 部署流程与 CI/CD 集成6.1 标准部署流程# 1. 构建镜像 docker build -t your-registry/laravel-app:$(git rev-parse --short HEAD) . # 2. 推送镜像 docker push your-registry/laravel-app:$(git rev-parse --short HEAD) # 3. 服务器拉取 docker pull your-registry/laravel-app:$(git rev-parse --short HEAD) # 4. 启动服务 TAG$(git rev-parse --short HEAD) docker-compose -f docker-compose.prod.yml up -d # 5. 执行迁移 docker exec -it app php artisan migrate --force6.2 GitHub Actions 示例创建.github/workflows/deploy.ymlname: Deploy to Production on: push: branches: [main] jobs: build-and-deploy: runs-on: ubuntu-latest steps: - uses: actions/checkoutv3 - name: Login to Docker Hub uses: docker/login-actionv2 with: username: ${{ secrets.DOCKER_HUB_USERNAME }} password: ${{ secrets.DOCKER_HUB_TOKEN }} - name: Build and push uses: docker/build-push-actionv4 with: push: true tags: | your-registry/laravel-app:latest your-registry/laravel-app:${{ github.sha }} - name: Deploy to Server uses: appleboy/ssh-actionmaster with: host: ${{ secrets.PROD_SERVER_IP }} username: ${{ secrets.PROD_SERVER_USER }} key: ${{ secrets.PROD_SERVER_SSH_KEY }} script: | docker pull your-registry/laravel-app:${{ github.sha }} TAG${{ github.sha }} docker-compose -f docker-compose.prod.yml up -d docker exec app php artisan migrate --force