说到部署Laravel项目,很多人第一反应还是老老实实在服务器上手工装PHP、装Nginx、装MySQL,然后各种配置文件写半天。环境稍有问题,排查起来更是头疼。
其实这套流程可以完全简化——用Docker Compose,一套docker-compose.yml文件,把Nginx、PHP、MySQL、Redis全部定义进去,一个docker-compose up -d就能把整套生产环境跑起来。今天就手把手讲清楚这个流程。
一、为什么推荐用Docker Compose部署Laravel
先说几个实际好处:
- 环境一致:本地什么环境,生产就什么环境,不存在"本地能跑服务器挂了"的经典问题。
- 部署快:一个新服务器,Docker装好,文件拷进去,两分钟上线。
- 迁移方便:整个项目目录拷贝到新机器,docker-compose up就能跑,数据还能通过volumes持久化。
- 版本隔离:不同项目PHP版本不同?互不干扰,各自独立容器。
我自己维护博客也是用的Docker方案,实战下来确实稳定省心。
二、整体架构规划
Laravel的标准Web架构通常需要这几个组件:
- nginx:Web服务器,处理HTTP请求,充当反向代理
- php:PHP-FPM容器,运行Laravel应用代码
- mysql:数据库
- redis:缓存和Session存储(可选但推荐)
四者通过Docker内部网络互通,对外只暴露nginx的80和443端口。
三、目录结构
先规划好项目目录,这是很多新手忽略但非常重要的一步:
laravel-docker/
├── docker/
│ ├── nginx/
│ │ └── default.conf
│ └── php/
│ └── Dockerfile
├── src/ # Laravel项目代码放这里
├── .env # 环境变量
├── docker-compose.yml
└── init.sql # 数据库初始化脚本(可选)
关键点:Laravel代码放在宿主机src目录,通过volumes挂载到PHP容器内,而不是打包进镜像。这样代码更新不需要重新构建镜像。
四、编写docker-compose.yml
version: '3.8'
services:
nginx:
image: nginx:alpine
container_name: laravel_nginx
ports:
- "80:80"
- "443:443"
volumes:
- ./src:/var/www/html
- ./docker/nginx/default.conf:/etc/nginx/conf.d/default.conf
depends_on:
- php
networks:
- laravel_net
php:
build:
context: ./docker/php
dockerfile: Dockerfile
container_name: laravel_php
volumes:
- ./src:/var/www/html
- ./storage:/var/www/html/storage:delegated
environment:
- DB_HOST=mysql
- DB_PORT=3306
- DB_DATABASE=laravel
- DB_USERNAME=laravel_user
- DB_PASSWORD=your_secure_password
- REDIS_HOST=redis
- REDIS_PORT=6379
depends_on:
- mysql
- redis
networks:
- laravel_net
mysql:
image: mysql:8.0
container_name: laravel_mysql
environment:
MYSQL_DATABASE: laravel
MYSQL_USER: laravel_user
MYSQL_PASSWORD: your_secure_password
MYSQL_ROOT_PASSWORD: root_secure_password
volumes:
- mysql_data:/var/lib/mysql
ports:
- "3306:3306"
networks:
- laravel_net
redis:
image: redis:alpine
container_name: laravel_redis
networks:
- laravel_net
networks:
laravel_net:
driver: bridge
volumes:
mysql_data:
几点说明:
- PHP用自定义Dockerfile构建,方便安装扩展和配置。
- MySQL数据用volumes持久化,容器删除不会丢数据。
- Redis使用alpine镜像,体积小资源占用低。
- 所有容器加入同一网络,彼此通过服务名互相访问。
五、PHP Dockerfile配置
FROM php:8.2-fpm-alpine
# 安装系统依赖和PHP扩展
RUN apk add --no-cache \
nginx \
supervisor \
bash \
oniguruma-dev \
libzip-dev \
&& docker-php-ext-install \
pdo \
pdo_mysql \
mbstring \
zip \
exif \
pcntl \
bcmath \
&& pecl install redis \
&& docker-php-ext-enable redis
# 安装Composer
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
# 配置Nginx
COPY nginx.conf /etc/nginx/http.d/default.conf
# 配置Supervisor(守护PHP-FPM)
COPY supervisord.conf /etc/supervisord.conf
# 工作目录
WORKDIR /var/www/html
EXPOSE 9000
CMD ["/usr/bin/supervisord", "-c", "/etc/supervisord.conf"]
对应的nginx.conf:
server {
listen 9000;
root /var/www/html/public;
index index.php index.html;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
}
Supervisor配置文件确保PHP-FPM进程稳定运行:
[supervisord]
nodaemon=true
[program:php-fpm]
command=php-fpm -F
autostart=true
autorestart=true
stdout_logfile=/dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0
六、Nginx配置
server {
listen 80;
server_name localhost;
root /var/www/html/public;
index index.php index.html;
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
fastcgi_pass php:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
fastcgi_buffer_size 32k;
fastcgi_buffers 4 32k;
}
location ~ /\.(?!well-known).* {
deny all;
}
access_log /var/log/nginx/laravel_access.log;
error_log /var/log/nginx/laravel_error.log;
}
七、Laravel .env文件配置
APP_NAME=LaravelApp
APP_ENV=production
APP_KEY=base64:your_generated_app_key_here
APP_DEBUG=false
APP_URL=https://yourdomain.com
LOG_CHANNEL=stack
DB_CONNECTION=mysql
DB_HOST=mysql
DB_PORT=3306
DB_DATABASE=laravel
DB_USERNAME=laravel_user
DB_PASSWORD=your_secure_password
BROADCAST_DRIVER=redis
CACHE_DRIVER=redis
QUEUE_CONNECTION=redis
SESSION_DRIVER=redis
SESSION_LIFETIME=120
REDIS_HOST=redis
REDIS_PASSWORD=null
REDIS_PORT=6379
生成APP_KEY的方法:进入容器执行php artisan key:generate,或者用在线工具生成后填入。
八、部署步骤
整个部署流程如下:
# 1. 准备好Laravel项目代码,放入src目录
# 确保src目录下有完整的Laravel项目(含vendor目录,或稍后容器内composer install)
# 2. 修改文件权限(Laravel storage目录需要写权限)
chmod -R 775 src/storage src/bootstrap/cache
# 3. 构建并启动所有容器
docker-compose up -d --build
# 4. 进入PHP容器,执行初始化
docker exec -it laravel_php bash
# 容器内执行:
composer install --no-dev --optimize-autoloader
php artisan key:generate
php artisan migrate --force
php artisan config:cache
php artisan route:cache
exit
# 5. 验证
curl http://localhost
如果能看到Laravel默认页面,说明部署成功。
九、常用运维命令
# 查看容器状态
docker-compose ps
# 查看日志
docker-compose logs -f
# 重启某个服务
docker-compose restart php
# 进入容器
docker exec -it laravel_php bash
# 重新构建(代码更新后)
docker-compose up -d --build
# 停止所有容器
docker-compose down
十、常见问题排查
502 Bad Gateway
大概率是PHP-FPM没起来或者Nginx连接PHP配置错误。先docker-compose logs nginx看日志,确认php容器状态正常。
数据库连接失败
检查.env里DB_HOST是否写的是mysql(服务名),不是localhost。确认MySQL容器已完全启动(初次启动MySQL需要10-30秒初始化)。
权限错误
storage和bootstrap/cache目录777权限不够,用775并确保属主正确:chown -R 1000:1000 src/storage src/bootstrap/cache
502 on file upload
Nginx默认client_max_body_size是1M,大文件上传需要调整nginx配置。
总结
用Docker Compose部署Laravel,核心就三件事:docker-compose.yml定义服务、Dockerfile构建PHP镜像、Nginx配置文件路由规则。把这三块搞定,后续新项目直接复制改配置就行。
相比传统部署方式,Docker方案的环境一致性、稳定性和迁移便捷性都强很多。刚开始会多花点时间搭框架,但长期维护成本大幅降低。
相关推荐:
版权声明
本文仅代表个人观点。
本文系AI辅助作者原创,未经许可,转载请保留原文链接。

发表评论