使用EB CLI部署Laravel时如何避免public/storage被清空
解决EB CLI部署Laravel时public/storage文件被清除的问题
我之前用EB CLI部署Laravel到AWS Elastic Beanstalk的时候,也踩过这个一模一样的坑!每次部署都会打包新代码替换实例上的版本,用户上传到public/storage的文件直接就没了,折腾了好一阵才整理出几个靠谱的解决办法,分享给你:
方案1:改用AWS S3存储用户上传文件(推荐)
Elastic Beanstalk的EC2实例本身就是临时资源,每次部署或者实例扩容/替换都会重置实例存储,所以根本不适合存放用户上传的持久化文件。把文件存到S3才是AWS生态下的最佳实践,步骤也很简单:
- 在AWS控制台创建一个S3桶,配置好合适的权限(比如允许你的EB实例访问)
- 在Laravel项目的
.env文件里添加S3相关配置:AWS_ACCESS_KEY_ID=你的访问密钥ID AWS_SECRET_ACCESS_KEY=你的访问密钥 AWS_DEFAULT_REGION=你的桶所在区域(比如us-east-1) AWS_BUCKET=你的S3桶名称 - 修改Laravel的文件系统配置,在
config/filesystems.php里把默认磁盘改成s3,或者在上传逻辑里指定用S3磁盘:// 示例:上传文件到S3的uploads目录 $path = $request->file('avatar')->store('uploads', 's3'); // 或者如果把默认磁盘设为s3,直接用 $path = $request->file('avatar')->store('uploads'); - 后续访问文件可以用Laravel的
Storage::url($path)生成S3的公开访问链接,或者配置CloudFront做CDN加速。
这个方案一劳永逸,完全避免了部署时丢失文件的问题,还能利用S3的高可用性和扩展性。
方案2:挂载EFS到public/storage目录
如果不想修改代码切换到S3,或者你的业务逻辑依赖本地文件系统访问,可以用AWS EFS(弹性文件系统)做持久化存储,挂载到实例的public/storage目录:
- 在AWS控制台创建一个EFS,确保和你的EB环境在同一个VPC下
- 在Laravel项目根目录创建
.ebextensions/efs-mount.config文件,添加以下配置(替换成你的EFS文件系统ID和区域):commands: 01_create_mount_point: command: "mkdir -p /var/app/current/public/storage" 02_mount_efs: command: "mount -t nfs4 -o nfsvers=4.1,rsize=1048576,wsize=1048576,hard,timeo=600,retrans=2,noresvport fs-xxxxxx.efs.us-east-1.amazonaws.com:/ /var/app/current/public/storage" container_commands: 01_set_permissions: command: "chown -R webapp:webapp /var/app/current/public/storage" - 部署的时候EB会自动执行这些命令,把EFS挂载到
public/storage目录,这样所有实例都会共享这个持久化存储,部署时文件也不会丢失。
注意:EFS的延迟比本地存储高一些,适合文件读写频率不是特别高的场景。
方案3:部署前后备份恢复存储目录(临时应急方案)
这个方案不推荐长期使用,因为如果是多实例环境会有同步问题,但应急的时候可以用:
在.ebextensions里添加部署钩子,在部署前把public/storage的文件备份到EB的临时存储,部署完成后再恢复:
files: "/opt/elasticbeanstalk/hooks/predeploy/01_backup_storage.sh": mode: "000755" owner: root group: root content: | #!/bin/bash mkdir -p /tmp/storage_backup cp -r /var/app/current/public/storage/* /tmp/storage_backup/ "/opt/elasticbeanstalk/hooks/postdeploy/01_restore_storage.sh": mode: "000755" owner: root group: root content: | #!/bin/bash cp -r /tmp/storage_backup/* /var/app/current/public/storage/ chown -R webapp:webapp /var/app/current/public/storage
这个方法的问题在于,如果部署过程中实例被替换,临时存储的备份也会丢失,而且多实例环境下各个实例的备份和恢复会不一致,所以只适合单实例的测试环境应急。
内容的提问来源于stack exchange,提问作者Chinh Le
相关产品推荐
相关产品推荐

