Laravel 在 Docker 环境下访问 storage 静态资源 404 问题解决
最近在学习使用docker编排laravel运行环境,遇到了在容器部署项目无法访问静态资源的问题,最终得以解决,在这里记录一下
问题复现
在项目storage/app/public
目录下有一张图片img.png
:
并且已经在容器中执行php artisan storage:link
来创建了软链接:
然后打开浏览器,访问localhost/storage/img.png
,结果返回404…
在这里贴一下我的docker-compose.yml
文件内容:
version: '3.7'
services:
app:
build:
context: ./docker
dockerfile: app.dockerfile
working_dir: /var/www
volumes:
- ./:/var/www:cached
environment:
- DB_CONNECTION=mysql
- DB_HOST=database
- DB_PORT=3306
- DB_DATABASE=iartisan
- DB_USERNAME=root
- DB_PASSWORD=123456
- REDIS_HOST=redis
- REDIS_PORT=6379
database:
build:
context: ./docker
dockerfile: database.dockerfile
restart: always
volumes:
- mysql_data:/var/lib/mysql:rw
- mysql_log:/var/log/mysql:rw
- mysql_config:/etc/mysql:rw
environment:
- MYSQL_ROOT_PASSWORD=$DB_PASSWORD
redis:
image: redis:5
proxy:
build:
context: ./docker
dockerfile: nginx.dockerfile
working_dir: /var/www
volumes:
- nginx_conf:/etc/nginx/conf.d:cached
- ./public:/var/www/public:cached
ports:
- 80:80
volumes:
mysql_data:
mysql_log:
mysql_config:
nginx_conf:
name: nginx_conf
networks:
default:
driver: bridge
app.dockerfile
文件:
FROM php:7.4-fpm
COPY ./composer-setup.sh /
RUN apt-get clean \
&& cd /var/lib/apt \
&& mv lists lists.old \
&& mkdir -p lists/partial \
&& apt-get clean \
&& echo "deb http://mirrors.aliyun.com/debian/ buster main non-free contrib \n \
deb-src http://mirrors.aliyun.com/debian/ buster main non-free contrib \n \
deb http://mirrors.aliyun.com/debian-security buster/updates main \n \
deb-src http://mirrors.aliyun.com/debian-security buster/updates main \n \
deb http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib \n \
deb-src http://mirrors.aliyun.com/debian/ buster-updates main non-free contrib" > /etc/apt/sources.list \
# 更新及安装库
&& apt-get update \
&& apt-get install -y libmagickwand-dev libmcrypt-dev libpq-dev libzip-dev zip \
# PHP扩展安装
&& docker-php-ext-install -j$(nproc) pdo_mysql bcmath \
&& pecl install redis imagick mcrypt zip \
&& docker-php-ext-enable redis imagick mcrypt zip
nginx.dockerfile
和vhost.conf
文件内容:
FROM nginx
COPY ./vhost.conf /etc/nginx/conf.d/default.conf
server {
listen 80;
server_name 127.0.0.1;
index index.php index.html;
root /var/www/public;
error_log /var/log/nginx/error.log notice;
access_log /var/log/nginx/access.log main;
location / {
try_files $uri /index.php?$args;
}
location ~ \.php$ {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass app:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
解决流程
起初尝试了docker 部署 Laravel,无法访问 storage 目录中的 文件这个帖子中评论的解决方案,以为是目录权限问题,尝试了给public/storage
切换到www-data
用户或者权限0777,结果都不行。
然后以为是路径问题,尝试了使用相对路径的软链接,结果不出意料,还是不行😄
然而在容器外使用valet
或者php artisan serve
都是可以成功请求图片的?
我还以为是nginx的问题,最后搞得我想用OSS来替代本地存储了,最后看到了这篇问题:
Dockerized Laravel App, always 404 on assets
发现可能是数据卷的映射问题,然后修改了docker-compose.yml
的数据卷映射配置为映射项目根目录:
volumes:
- nginx_conf:/etc/nginx/conf.d:cached
# - ./public:/var/www/public:cached
- ./:/var/www:cached
重新构建,然后访问
真是太感动了😭原来就是数据卷映射的问题
不过还有个值得注意的点,现在是可以访问了,但是此时在
public
目录下的storage
软链接是相对路径../storage/app/public
。经过测试,相对路径的软链接在容器内外都生效,而使用php artisan storage:link
所创建的软链接是绝对路径,而docker容器内的目录是和宿主机不同的,这就导致了在哪种环境下执行的storage:link
命令,就只能在哪种环境下生效
本作品采用《CC 协议》,转载必须注明作者和本文链接
推荐文章: