Laravel 12 部署最佳实践:从容器化到监控

摘要

本文详解 Laravel 12 的部署最佳实践,包括环境配置、容器化部署、CI/CD 集成、负载均衡和监控系统。提供完整的部署方案,从开发环境到生产环境,帮助开发者构建高可用、高性能的 Laravel 应用。

1. 部署环境准备

1.1 服务器要求

组件版本要求推荐版本
PHP>= 8.18.2+
Composer>= 2.02.2+
Web 服务器Nginx/ApacheNginx 1.20+
数据库MySQL/PostgreSQL/SQLiteMySQL 8.0+
缓存Redis/MemcachedRedis 7.0+
队列Redis/Beanstalkd/SQSRedis 7.0+

1.2 环境配置

生产环境配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# .env.production
APP_NAME=Laravel
APP_ENV=production
APP_KEY=base64:your-app-key
APP_DEBUG=false
APP_URL=https://your-domain.com

LOG_CHANNEL=stack
LOG_LEVEL=error

DB_CONNECTION=mysql
DB_HOST=db
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel
DB_PASSWORD=your-db-password

REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379

CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=120

MAIL_MAILER=smtp
MAIL_HOST=smtp.mailgun.org
MAIL_PORT=587
MAIL_USERNAME=postmaster@your-domain.com
MAIL_PASSWORD=your-mailgun-password
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=no-reply@your-domain.com
MAIL_FROM_NAME="${APP_NAME}"

AWS_ACCESS_KEY_ID=
AWS_SECRET_ACCESS_KEY=
AWS_DEFAULT_REGION=us-east-1
AWS_BUCKET=

PUSHER_APP_ID=
PUSHER_APP_KEY=
PUSHER_APP_SECRET=
PUSHER_APP_CLUSTER=mt1

MIX_PUSHER_APP_KEY="${PUSHER_APP_KEY}"
MIX_PUSHER_APP_CLUSTER="${PUSHER_APP_CLUSTER}"

性能优化配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// config/opcache.php
return [
'enabled' => env('OPCACHE_ENABLED', true),
'validate_timestamps' => env('OPCACHE_VALIDATE_TIMESTAMPS', false),
'max_accelerated_files' => env('OPCACHE_MAX_ACCELERATED_FILES', 10000),
'memory_consumption' => env('OPCACHE_MEMORY_CONSUMPTION', 128),
'interned_strings_buffer' => env('OPCACHE_INTERNED_STRINGS_BUFFER', 16),
];

// config/database.php
return [
// ...
'connections' => [
'mysql' => [
// ...
'options' => extension_loaded('pdo_mysql') ? array_filter([
PDO::MYSQL_ATTR_SSL_CA => env('MYSQL_ATTR_SSL_CA'),
PDO::ATTR_EMULATE_PREPARES => false,
PDO::ATTR_STRINGIFY_FETCHES => false,
]) : [],
],
],
];

2. 容器化部署

2.1 Docker 配置

Dockerfile

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# Dockerfile
FROM php:8.2-fpm-alpine

# 安装依赖
RUN apk add --no-cache \
libpng-dev \
libjpeg-turbo-dev \
freetype-dev \
libzip-dev \
zlib-dev \
curl \
git \
unzip \
nginx \
supervisor \
&& docker-php-ext-configure gd --with-freetype --with-jpeg \
&& docker-php-ext-install -j$(nproc) gd pdo_mysql zip opcache \
&& pecl install redis \
&& docker-php-ext-enable redis \
&& rm -rf /var/cache/apk/*

# 安装 Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer

# 设置工作目录
WORKDIR /var/www/html

# 复制应用代码
COPY . .

# 安装依赖
RUN composer install --optimize-autoloader --no-dev

# 生成应用密钥
RUN php artisan key:generate

# 设置权限
RUN chown -R www-data:www-data /var/www/html/storage /var/www/html/bootstrap/cache

# 复制配置文件
COPY docker/nginx.conf /etc/nginx/nginx.conf
COPY docker/supervisord.conf /etc/supervisor/conf.d/supervisord.conf

# 暴露端口
EXPOSE 80

# 启动服务
CMD ["/usr/bin/supervisord", "-n"]

Docker Compose

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
# docker-compose.yml
version: '3.8'

services:
app:
build: .
ports:
- "8000:80"
volumes:
- .:/var/www/html
- ./docker/php.ini:/usr/local/etc/php/conf.d/php.ini
environment:
- APP_ENV=production
- DB_HOST=db
- REDIS_HOST=redis
depends_on:
- db
- redis

db:
image: mysql:8.0
ports:
- "3306:3306"
volumes:
- mysql-data:/var/lib/mysql
- ./docker/mysql.cnf:/etc/mysql/conf.d/mysql.cnf
environment:
- MYSQL_ROOT_PASSWORD=root
- MYSQL_DATABASE=laravel
- MYSQL_USER=laravel
- MYSQL_PASSWORD=laravel

redis:
image: redis:7.0-alpine
ports:
- "6379:6379"
volumes:
- redis-data:/data

volumes:
mysql-data:
redis-data:

配置文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# docker/nginx.conf
events {
worker_connections 1024;
}

http {
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" "$http_x_forwarded_for"';

access_log /var/log/nginx/access.log main;
error_log /var/log/nginx/error.log error;

sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;

gzip on;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

server {
listen 80;
server_name localhost;
root /var/www/html/public;

index index.php index.html;

location / {
try_files $uri $uri/ /index.php?$query_string;
}

location ~ \.php$ {
fastcgi_pass unix:/var/run/php-fpm.sock;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}

location ~ /\.(?!well-known).* {
deny all;
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# docker/supervisord.conf
[supervisord]
nodaemon=true

[program:php-fpm]
command=/usr/local/sbin/php-fpm
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

[program:nginx]
command=/usr/sbin/nginx -g 'daemon off;'
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0

2.2 部署流程

1. 构建镜像

1
docker-compose build

2. 启动服务

1
docker-compose up -d

3. 运行迁移

1
docker-compose exec app php artisan migrate --force

4. 缓存配置

1
2
3
docker-compose exec app php artisan config:cache
docker-compose exec app php artisan route:cache
docker-compose exec app php artisan view:cache

5. 优化自动加载

1
docker-compose exec app composer dump-autoload --optimize

3. CI/CD 集成

3.1 GitHub Actions

基本配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
# .github/workflows/deploy.yml
name: Deploy

on:
push:
branches:
- main

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
php-version: '8.2'
extensions: mbstring, dom, curl, sqlite3, pdo_mysql, zip, gd, redis
- name: Install dependencies
run: composer install --prefer-dist --no-progress
- name: Run tests
run: vendor/bin/pest

deploy:
needs: test
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v2
- name: Login to Docker Hub
uses: docker/login-action@v2
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_PASSWORD }}
- name: Build and push
uses: docker/build-push-action@v4
with:
context: .
push: true
tags: yourusername/laravel-app:latest
- name: Deploy to server
uses: appleboy/ssh-action@v0.1.4
with:
host: ${{ secrets.SERVER_HOST }}
username: ${{ secrets.SERVER_USERNAME }}
password: ${{ secrets.SERVER_PASSWORD }}
script: |
cd /var/www/laravel-app
docker-compose pull
docker-compose up -d
docker-compose exec app php artisan migrate --force
docker-compose exec app php artisan config:cache
docker-compose exec app php artisan route:cache
docker-compose exec app php artisan view:cache

3.2 GitLab CI

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# .gitlab-ci.yml
stages:
- test
- build
- deploy

test:
stage: test
image: php:8.2
script:
- apt-get update && apt-get install -y git unzip
- curl -sS https://getcomposer.org/installer | php -- --install-dir=/usr/local/bin --filename=composer
- composer install --prefer-dist --no-progress
- vendor/bin/pest

build:
stage: build
image: docker:latest
services:
- docker:dind
script:
- docker build -t registry.gitlab.com/yourusername/laravel-app:latest .
- docker login -u $CI_REGISTRY_USER -p $CI_REGISTRY_PASSWORD $CI_REGISTRY
- docker push registry.gitlab.com/yourusername/laravel-app:latest

deploy:
stage: deploy
image: alpine:latest
script:
- apk add --no-cache openssh-client
- ssh-keyscan -H $SERVER_HOST >> ~/.ssh/known_hosts
- ssh $SERVER_USERNAME@$SERVER_HOST "cd /var/www/laravel-app && docker-compose pull && docker-compose up -d && docker-compose exec app php artisan migrate --force && docker-compose exec app php artisan config:cache && docker-compose exec app php artisan route:cache && docker-compose exec app php artisan view:cache"
environment:
name: production
only:
- main

4. 负载均衡与高可用

4.1 Nginx 负载均衡

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
# nginx.conf
upstream laravel_app {
server app1:8000;
server app2:8000;
server app3:8000;
least_conn;
}

server {
listen 80;
server_name your-domain.com;

location / {
proxy_pass http://laravel_app;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}

# SSL 配置
listen 443 ssl;
ssl_certificate /etc/letsencrypt/live/your-domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your-domain.com/privkey.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_ciphers ECDHE-RSA-AES256-GCM-SHA512:DHE-RSA-AES256-GCM-SHA512:ECDHE-RSA-AES256-GCM-SHA384:DHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-SHA384;
ssl_prefer_server_ciphers off;
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
}

4.2 数据库高可用

MySQL 主从复制

1
2
3
4
5
6
7
8
9
10
11
12
13
# 主服务器配置
# /etc/mysql/my.cnf
[mysqld]
server-id = 1
log-bin = mysql-bin
binlog-format = ROW

# 从服务器配置
# /etc/mysql/my.cnf
[mysqld]
server-id = 2
relay-log = relay-bin
read-only = 1

Redis 集群

1
2
3
4
5
6
7
# 创建 Redis 集群
docker run -d --name redis-1 -p 7001:6379 redis:7.0-alpine redis-server --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
docker run -d --name redis-2 -p 7002:6379 redis:7.0-alpine redis-server --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes
docker run -d --name redis-3 -p 7003:6379 redis:7.0-alpine redis-server --cluster-enabled yes --cluster-config-file nodes.conf --cluster-node-timeout 5000 --appendonly yes

# 初始化集群
docker exec -it redis-1 redis-cli --cluster create 127.0.0.1:7001 127.0.0.1:7002 127.0.0.1:7003 --cluster-replicas 0

5. 监控系统

5.1 应用监控

Laravel Telescope

1
2
3
composer require laravel/telescope --dev
php artisan telescope:install
php artisan migrate

Laravel Horizon

1
2
3
composer require laravel/horizon
php artisan horizon:install
php artisan migrate

5.2 服务器监控

Prometheus + Grafana

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# docker-compose.monitoring.yml
version: '3.8'

services:
prometheus:
image: prom/prometheus:latest
ports:
- "9090:9090"
volumes:
- ./prometheus.yml:/etc/prometheus/prometheus.yml
- prometheus-data:/prometheus

grafana:
image: grafana/grafana:latest
ports:
- "3000:3000"
volumes:
- grafana-data:/var/lib/grafana
environment:
- GF_SECURITY_ADMIN_USER=admin
- GF_SECURITY_ADMIN_PASSWORD=admin

node_exporter:
image: prom/node-exporter:latest
ports:
- "9100:9100"

redis_exporter:
image: oliver006/redis_exporter:latest
ports:
- "9121:9121"
environment:
- REDIS_ADDR=redis:6379

volumes:
prometheus-data:
grafana-data:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# prometheus.yml
global:
scrape_interval: 15s

scrape_configs:
- job_name: 'prometheus'
static_configs:
- targets: ['localhost:9090']

- job_name: 'node'
static_configs:
- targets: ['node_exporter:9100']

- job_name: 'redis'
static_configs:
- targets: ['redis_exporter:9121']

- job_name: 'laravel'
static_configs:
- targets: ['app:8000']
metrics_path: '/metrics'

5.3 日志管理

ELK Stack

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
# docker-compose.elk.yml
version: '3.8'

services:
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:8.8.0
ports:
- "9200:9200"
volumes:
- es-data:/usr/share/elasticsearch/data
environment:
- discovery.type=single-node
- ES_JAVA_OPTS=-Xms1g -Xmx1g

logstash:
image: docker.elastic.co/logstash/logstash:8.8.0
ports:
- "5044:5044"
volumes:
- ./logstash.conf:/usr/share/logstash/pipeline/logstash.conf
depends_on:
- elasticsearch

kibana:
image: docker.elastic.co/kibana/kibana:8.8.0
ports:
- "5601:5601"
depends_on:
- elasticsearch

filebeat:
image: docker.elastic.co/beats/filebeat:8.8.0
volumes:
- ./filebeat.yml:/usr/share/filebeat/filebeat.yml
- /var/log/nginx:/var/log/nginx
- /var/www/html/storage/logs:/var/www/html/storage/logs
depends_on:
- logstash

volumes:
es-data:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# logstash.conf
input {
beats {
port => 5044
}
}

filter {
if [fileset][module] == "nginx" {
if [fileset][name] == "access" {
grok {
match => { "message" => "%{NGINXACCESS}" }
}
date {
match => [ "timestamp", "dd/MMM/yyyy:HH:mm:ss Z" ]
target => "@timestamp"
}
}
}

if [source] == "/var/www/html/storage/logs/laravel.log" {
grok {
match => { "message" => "\[%{TIMESTAMP_ISO8601:timestamp}\] %{DATA:environment}\.%{LOGLEVEL:level}: %{GREEDYDATA:message}" }
}
date {
match => [ "timestamp", "yyyy-MM-dd HH:mm:ss" ]
target => "@timestamp"
}
}
}

output {
elasticsearch {
hosts => ["elasticsearch:9200"]
index => "logs-%{+YYYY.MM.dd}"
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
# filebeat.yml
filebeat.inputs:
- type: log
enabled: true
paths:
- /var/log/nginx/access.log
- /var/log/nginx/error.log
fields:
fileset.module: nginx

- type: log
enabled: true
paths:
- /var/www/html/storage/logs/laravel.log
fields:
fileset.module: laravel

output.logstash:
hosts: ["logstash:5044"]

6. 自动化运维

6.1 定时任务

Laravel Scheduler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
// app/Console/Kernel.php
protected function schedule(Schedule $schedule)
{
// 清理日志
$schedule->command('log:clean')->daily();

// 优化数据库
$schedule->command('db:optimize')->weekly();

// 备份数据库
$schedule->command('backup:run')->dailyAt('02:00');

// 清理缓存
$schedule->command('cache:clear')->daily();

// 发送报告
$schedule->command('report:send')->weeklyOn(1, '09:00');
}

Supervisor 配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# /etc/supervisor/conf.d/laravel-worker.conf
[program:laravel-worker]
process_name=%(program_name)s_%(process_num)02d
command=php /var/www/html/artisan queue:work --sleep=3 --tries=3 --max-time=3600
autostart=true
autorestart=true
user=www-data
numprocs=8
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/worker.log
stopwaitsecs=3600

[program:laravel-scheduler]
process_name=%(program_name)s
command=php /var/www/html/artisan schedule:run --sleep=60
autostart=true
autorestart=true
user=www-data
numprocs=1
redirect_stderr=true
stdout_logfile=/var/www/html/storage/logs/scheduler.log

6.2 自动化备份

Laravel Backup

1
2
composer require spatie/laravel-backup
php artisan vendor:publish --provider="Spatie\Backup\BackupServiceProvider"
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// config/backup.php
return [
'backup' => [
'destination' => [
'disks' => ['local', 's3'],
],
'monitorBackups' => [
'enabled' => true,
'targets' => [
[
'name' => env('APP_NAME'),
'disk' => 'local',
'newestBackupsShouldNotBeOlderThanDays' => 1,
'storageUsedMayNotBeHigherThanMegabytes' => 5000,
],
],
],
],
];

备份命令

1
2
3
4
5
6
7
8
9
10
11
# 手动备份
php artisan backup:run

# 查看备份状态
php artisan backup:list

# 清理旧备份
php artisan backup:clean

# 监控备份
php artisan backup:monitor

7. 安全加固

7.1 服务器安全

SSH 配置

1
2
3
4
5
6
# /etc/ssh/sshd_config
Port 2222
PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AllowUsers deploy

防火墙配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
# 安装 UFW
apt install ufw

# 配置防火墙
ufw default deny incoming
ufw default allow outgoing
ufw allow 2222/tcp
ufw allow 80/tcp
ufw allow 443/tcp
ufw allow 3306/tcp
ufw allow 6379/tcp
ufw enable

# 查看状态
ufw status

7.2 应用安全

HTTPS 配置

1
2
3
4
5
6
7
8
# 安装 Certbot
apt install certbot python3-certbot-nginx

# 申请证书
certbot --nginx -d your-domain.com -d www.your-domain.com

# 自动续期
certbot renew --dry-run

安全头

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# nginx.conf
server {
# ...

# 安全头
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-XSS-Protection "1; mode=block" always;
add_header X-Content-Type-Options "nosniff" always;
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https://cdnjs.cloudflare.com; style-src 'self' 'unsafe-inline' https://fonts.googleapis.com; img-src 'self' data: https://*.googleusercontent.com; font-src 'self' https://fonts.gstatic.com" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Permissions-Policy "accelerometer=(), camera=(), geolocation=(), gyroscope=(), magnetometer=(), microphone=(), payment=(), usb=()" always;

# ...
}

速率限制

1
2
3
4
5
6
7
8
9
10
11
12
// app/Http/Kernel.php
protected $middlewareGroups = [
'api' => [
// ...
\Illuminate\Routing\Middleware\ThrottleRequests::class . ':api',
],
];

// 自定义速率限制
Route::middleware('throttle:60,1')->group(function () {
Route::get('/api/users', [UserController::class, 'index']);
});

8. 性能优化

8.1 应用级优化

代码优化

  • 使用类型声明:添加函数参数和返回类型
  • 避免 N+1 查询:使用 eager loading
  • 使用缓存:缓存频繁访问的数据
  • 优化路由:使用路由缓存
  • 优化视图:使用视图缓存
  • 优化配置:使用配置缓存

数据库优化

  • 添加索引:为频繁查询的列添加索引
  • 使用查询构建器:避免原始 SQL
  • 批量操作:使用批量插入和更新
  • 分页优化:使用游标分页
  • 连接池:配置数据库连接池

8.2 服务器级优化

PHP 优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# php.ini
opcache.enable=1
opcache.memory_consumption=256
opcache.interned_strings_buffer=16
opcache.max_accelerated_files=10000
opcache.validate_timestamps=0
opcache.revalidate_freq=0
opcache.save_comments=1
opcache.fast_shutdown=1

zend_extension=opcache
zend_extension=redis

memory_limit=512M
max_execution_time=30
max_input_time=60
post_max_size=100M
upload_max_filesize=100M

Nginx 优化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
# nginx.conf
worker_processes auto;
worker_connections 1024;
events {
use epoll;
multi_accept on;
}

http {
sendfile on;
tcp_nopush on;
tcp_nodelay on;
keepalive_timeout 65;
keepalive_requests 100;

gzip on;
gzip_comp_level 6;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml application/xml+rss text/javascript;

open_file_cache max=10000 inactive=20s;
open_file_cache_valid 30s;
open_file_cache_min_uses 2;
open_file_cache_errors on;
}

9. 实战案例:完整部署方案

9.1 项目背景

  • 规模:中型电商应用
  • 流量:1000-5000 QPS
  • 架构:微服务架构
  • 技术栈:Laravel 12、Vue 3、Redis、MySQL、Docker
  • 要求:高可用、高性能、安全

9.2 部署架构

1. 基础设施

  • 云服务:AWS EC2 + RDS + ElastiCache
  • 容器编排:Kubernetes
  • 负载均衡:AWS ALB
  • CDN:CloudFront
  • 监控:CloudWatch + Prometheus + Grafana

2. 服务架构

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
┌─────────────┐     ┌─────────────┐     ┌─────────────┐
│ 客户端 │ → → │ CloudFront │ → → │ ALB │
└─────────────┘ └─────────────┘ └─────────────┘
↑ ↑
│ │
↓ ↓
┌─────────────┬─────────────┐
↓ ↓ ↓
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ 前端服务 │ │ API 服务 │ │ 后台服务 │
└─────────────┘ └─────────────┘ └─────────────┘
↑ ↑ ↑
│ │ │
↓ ↓ ↓
┌─────────────┬─────────────┐
↓ ↓ ↓
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ Redis │ │ MySQL │ │ S3 │
└─────────────┘ └─────────────┘ └─────────────┘

3. CI/CD 流程

  1. 代码提交:开发者提交代码到 GitHub
  2. 自动化测试:GitHub Actions 运行测试
  3. 构建镜像:构建 Docker 镜像并推送到 ECR
  4. 部署应用:Kubernetes 部署新版本
  5. 健康检查:检查应用健康状态
  6. 回滚机制:失败时自动回滚

9.3 实施效果

指标实施前实施后提升
响应时间500ms100ms80%
QPS10005000400%
可用性99.5%99.99%显著
部署时间30分钟5分钟83%
维护成本60%

10. 部署最佳实践总结

10.1 环境配置

  • 使用环境变量:避免硬编码配置
  • 分离环境:开发、测试、生产环境分离
  • 版本控制:配置文件纳入版本控制
  • 自动化配置:使用配置管理工具

10.2 容器化部署

  • 使用 Docker:容器化应用
  • 使用 Docker Compose:本地开发环境
  • 使用 Kubernetes:生产环境编排
  • 多阶段构建:减小镜像大小
  • 镜像分层:优化镜像构建

10.3 CI/CD 集成

  • 自动化测试:每次提交运行测试
  • 自动化构建:构建镜像并推送
  • 自动化部署:部署到生产环境
  • 自动化回滚:失败时自动回滚
  • 自动化监控:监控部署状态

10.4 高可用设计

  • 负载均衡:分发流量到多个实例
  • 数据库复制:主从复制保证数据安全
  • Redis 集群:提高缓存可用性
  • 自动缩放:根据流量自动缩放
  • 多可用区:跨可用区部署

10.5 监控与告警

  • 应用监控:监控应用状态和性能
  • 服务器监控:监控服务器资源使用
  • 数据库监控:监控数据库性能
  • 缓存监控:监控缓存命中率
  • 日志管理:集中管理和分析日志
  • 告警机制:异常时及时告警

10.6 安全加固

  • HTTPS:启用 HTTPS 加密
  • 防火墙:配置防火墙规则
  • SSH 加固:禁用密码登录
  • 速率限制:防止暴力攻击
  • 安全头:添加安全 HTTP 头
  • 定期扫描:扫描安全漏洞

10.7 性能优化

  • 代码优化:优化代码结构和算法
  • 数据库优化:添加索引和优化查询
  • 缓存策略:合理使用缓存
  • 服务器优化:优化服务器配置
  • CDN:使用 CDN 加速静态资源

11. 总结

Laravel 12 的部署是一个系统工程,涉及环境配置、容器化、CI/CD、负载均衡、监控和安全等多个方面。通过本文的介绍,开发者可以掌握 Laravel 12 部署的最佳实践,构建高可用、高性能、安全的 Laravel 应用。

在实际项目中,开发者应该根据项目的规模和需求,选择合适的部署方案。对于小型项目,可以使用简单的 Nginx + PHP-FPM 部署;对于中型项目,可以使用 Docker Compose 部署;对于大型项目,应该使用 Kubernetes 等容器编排工具。

同时,开发者应该注重自动化运维,通过 CI/CD 流程自动化测试、构建和部署,减少人工操作的错误。此外,应该建立完善的监控系统,及时发现和解决问题,保证应用的稳定运行。

随着云计算和容器技术的不断发展,Laravel 的部署方案也在不断演进。开发者应该保持学习的态度,关注最新的部署技术和工具,为构建更好的 Laravel 应用而努力。

Laravel 12 的部署最佳实践不仅是一套技术方案,更是一种工程化的思维方式:通过标准化的流程和工具,提高开发效率,保证代码质量,确保系统稳定。这种思维方式已经被越来越多的开发者所接受,成为现代 PHP 开发的主流选择。

在未来,随着 Laravel 生态系统的不断完善和云服务的不断发展,Laravel 的部署将会变得更加简单、高效和可靠。让我们一起期待 Laravel 的未来,为 PHP 生态系统的繁荣做出贡献。