You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

WSL2 Docker环境下Laravel Sail路径指向异常如何处理

WSL2下Laravel Sail路径助手返回容器路径导致文件上传异常

问题表现

WSL2环境中通过./vendor/bin/sail up启动Laravel项目时,public_path()、storage_path()等路径助手函数返回容器内路径,而非宿主机原始项目目录,导致文件上传功能异常。
路由中打印路径的测试代码:

Route::get('/', function () {
    dump(public_path());
    dump(storage_path());
});

Web访问返回结果:

^ "/var/www/html/public"
^ "/var/www/html/storage"

排查过程

  • 新建全新Laravel项目测试路径返回值
  • 在其他设备复现测试
  • WSL2命令行直接执行php artisan storage:link,软链指向宿主机路径:
$ php artisan storage:link
The [/home/ahming/example-app/public/storage] link has been connected to [/home/ahming/example-app/storage/app/public].
The links have been created.
  • WSL2命令行直接执行php artisan tinker,路径返回宿主机路径:
$ php artisan tinker
Psy Shell v0.11.5 (PHP 8.1.7 - cli) by Justin Hileman
>>> public_path()
=> "/home/ahming/example-app/public"
  • php artisan serve启动服务时路径返回正常,确认问题与Docker环境相关
  • 通过sail执行tinker时路径返回容器内路径,与web访问结果一致:
$ ./vendor/bin/sail artisan tinker
Psy Shell v0.11.5 (PHP 8.1.7 — cli) by Justin Hileman
>>> public_path()
=> "/var/www/html/public"

当前使用的docker-compose.yml配置:

# For more information: https://laravel.com/docs/sail
version: '3'
services:
    laravel.test:
        build:
            context: ./vendor/laravel/sail/runtimes/8.1
            dockerfile: Dockerfile
            args:
                WWWGROUP: '${WWWGROUP}'
        image: sail-8.1/app
        extra_hosts:
            - 'host.docker.internal:host-gateway'
        ports:
            - '${APP_PORT:-80}:80'
            - '${HMR_PORT:-8080}:8080'
        environment:
            WWWUSER: '${WWWUSER}'
            LARAVEL_SAIL: 1
            XDEBUG_MODE: '${SAIL_XDEBUG_MODE:-off}'
            XDEBUG_CONFIG: '${SAIL_XDEBUG_CONFIG:-client_host=host.docker.internal}'
        volumes:
            - '.:/var/www/html'
        networks:
            - sail
        depends_on:
            - mysql
    mysql:
        image: 'mysql/mysql-server:8.0'
        ports:
            - '${FORWARD_DB_PORT:-3306}:3306'
        environment:
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ROOT_HOST: "%"
            MYSQL_DATABASE: '${DB_DATABASE}'
            MYSQL_USER: '${DB_USERNAME}'
            MYSQL_PASSWORD: '${DB_PASSWORD}'
            MYSQL_ALLOW_EMPTY_PASSWORD: 1
        volumes:
            - 'sail-mysql:/var/lib/mysql'
            - './vendor/laravel/sail/database/mysql/create-testing-database.sh:/docker-entrypoint-initdb.d/10-create-testing-database.sh'
        networks:
            - sail
        healthcheck:
            test: ["CMD", "mysqladmin", "ping", "-p${DB_PASSWORD}"]
            retries: 3
            timeout: 5s
    phpmyadmin:
        image: 'phpmyadmin/phpmyadmin'
        links:
            - mysql:mysql
        ports:
            - '8000:80'
        environment:
            MYSQL_USERNAME: "${DB_USERNAME}"
            MYSQL_ROOT_PASSWORD: "${DB_PASSWORD}"
            PMA_HOST: mysql
        networks:
            - sail
networks:
    sail:
        driver: bridge
volumes:
    sail-mysql:
        driver: local

问题根因

路径返回/var/www/html是Sail容器环境的正常表现,不是错误。
Sail的容器通过volume把宿主机项目目录挂载到容器内的/var/www/html路径,容器内运行的PHP(包括web请求、sail执行的artisan命令)识别到的项目根目录自然是容器内的挂载路径。
真正导致功能异常的是操作环境不统一:在WSL宿主机环境执行了storage:link命令,生成的软链指向宿主机的绝对路径,容器内的PHP进程无法识别这个路径对应的真实目录,才会出现文件访问、上传失败的问题。

解决方法

所有项目相关的artisan、composer、npm操作都统一通过sail在容器内执行,不要在WSL宿主机直接执行项目内的脚本命令:

  1. 先删除之前在宿主机生成的无效软链,直接删除项目下public/storage文件即可
  2. 进入WSL的项目根目录,执行容器内的软链生成命令:
./vendor/bin/sail artisan storage:link
  1. 后续所有artisan操作都加sail前缀执行,比如:
# 清除配置缓存
./vendor/bin/sail artisan config:clear
# 执行数据库迁移
./vendor/bin/sail artisan migrate
# 进入tinker
./vendor/bin/sail artisan tinker

补充:容器内的/var/www/html路径和宿主机项目目录是双向绑定的,容器内对文件的修改会实时同步到宿主机,不存在文件隔离的问题。路径助手返回容器内路径不会影响正常的web访问、文件存储逻辑,只要所有操作都在容器环境内执行,就不会出现路径不一致的问题。

内容的提问来源于stack exchange,提问作者AhMing

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.29 06:42:36