---
title: "Laravel Sail: troubleshooting WSL2, permissions, ports, rebuilds, OPcache & Vite | DevSense"
description: "Fix common Laravel Sail pain points: WSL2 file sync, UID/GID and storage permissions, FORWARD_* port clashes, stale Docker layers, OPcache and Xdebug in dev, npm/Vite split host vs container, and safe volume resets."
faq:
  - question: "Why is Vite asset compilation extremely slow on Windows with WSL2?"
    answer: "This is usually caused by keeping your project files on the Windows filesystem (/mnt/c/...). To fix this, move your project folder to the Linux native filesystem (e.g. ~/projects/) inside WSL2."
  - question: "How do I fix permission denied errors on the storage directory?"
    answer: "Run 'sail artisan cache:clear' and configure the WWWUSER and WWWGROUP environment variables in your .env file to match your host machine's user ID so files generated by containerized CLI tools maintain correct ownership."
  - question: "Why does my code change not update inside the running container?"
    answer: "If it is a web change, OPcache might be enabled in PHP configuration. If it is a queue worker, it has cached the bootstrap. If it is a Dockerfile configuration change, you must run 'sail build --no-cache' and restart containers."
  - question: "How do I check what extensions are loaded in my Sail PHP environment?"
    answer: "Run the command 'sail exec laravel.test php -m' to list all active PHP modules running inside the container runtime, as this will differ from your host environment."
---

# Sail: troubleshooting & performance

Your application was running perfectly yesterday, but today `sail up` throws a port allocation conflict, assets fail to compile via Vite, and database writes crash with permission errors. When Sail fails, it is rarely a Laravel bug; it is almost always a friction point between the virtualized container environment and your host machine's filesystem, network, or process state.

Virtualization layers (especially WSL2 on Windows) and container network namespaces introduce unique quirks. Understanding how to diagnose and bypass these roadblocks is essential for maintaining a fast, seamless development workflow.

In this guide, we collect the most frequent Sail symptoms, explain why they happen, and provide direct commands to resolve them.

**Navigation:** [All tools](../) · [Sail overview](sail#what-sail-is) · [Databases](sail-databases#networking) · [Queues](sail-queues#connections) · [Env & deploy](sail-env-deploy#forward-ports)

## Table of contents

* [WSL2, Docker Desktop, and file sync](#wsl-filesync)
* [Permissions, `storage`, and `vendor`](#permissions)
* [Port already allocated / `FORWARD_*`](#ports)
* [Host vs. container mismatches](#host-vs-container)
* [Stale code: rebuilds and layers](#rebuild)
* [OPcache and autoload in local dev](#opcache)
* [Xdebug feels slow](#xdebug)
* [Vite, npm, and Node inside vs. outside Sail](#frontend)
* [Logs and quick diagnostics](#logs)
* [When to reset volumes (data loss)](#volumes)
* [Common Mistakes](#common-mistakes)
* [Self-Check Questions](#self-check)

---

<a id="wsl-filesync"></a>
## WSL2, Docker Desktop, and file sync

On Windows + WSL2, mounting files from the Windows partition (`/mnt/c/...`) into Linux containers causes massive disk I/O bottlenecks. Vite and webpack hot-module replacement (HMR) file watchers will also fail to receive change notifications.

Keep your project folders entirely **inside the native WSL filesystem** (e.g., `~/projects/...`). Open them in VS Code using the **WSL extension** to ensure file sync and compiling events take milliseconds instead of seconds.

---

<a id="permissions"></a>
## Permissions, `storage`, and `vendor`

Laravel requires write permissions for `storage/` and `bootstrap/cache/`. If Docker runs as the root user, files created inside containers will become read-only on your host machine.

Verify permissions inside the container:

```bash
# Terminal
sail exec laravel.test ls -la storage bootstrap/cache
```

> [!NOTE]
> **UID and GID mapping**
> In Linux hosts, match your host UID and GID by defining `WWWUSER` and `WWWGROUP` variables in your environment:
> ```dotenv
> # .env
> WWWUSER=1000
> WWWGROUP=1000
> ```
> Restart Sail after changes.

---

<a id="ports"></a>
## Port already allocated / `FORWARD_*`

If another service (like a local database or another running Sail instance) is already using ports like `3306` or `80`, you will see an `address already in use` error.

Define alternative ports in `.env`:

```dotenv
# .env
APP_PORT=8081
FORWARD_DB_PORT=3307
FORWARD_REDIS_PORT=6380
```

Run `sail down && sail up -d` to apply.

---

<a id="host-vs-container"></a>
## Host vs. container mismatches

A common mistake is running commands like `php artisan migrate` or `composer install` directly on the host machine. If your host has a different PHP version or lacks extensions (like `redis` or `mongodb`), the command will fail or corrupt your lockfile.

- **Host (Bad):** `composer install`
- **Sail (Good):** `sail composer install`

---

<a id="rebuild"></a>
## Stale code: rebuilds and layers

When you modify dependencies, PHP runtimes, or custom packages in your published Dockerfiles, Docker does not rebuild your images automatically.

Force a complete image rebuild without using cached layers:

```bash
# Terminal
sail build --no-cache
sail up -d
```

---

<a id="opcache"></a>
## OPcache and autoload in local dev

If code changes do not appear in your browser, check if OPcache is active inside the container. In development, OPcache should validate timestamps on every request.

Ensure the following is set in your container's PHP configuration:

```ini
# php.ini
opcache.validate_timestamps=1
opcache.revalidate_freq=0
```

If you add new classes and get namespace errors, run `sail composer dump-autoload`.

---

<a id="xdebug"></a>
## Xdebug feels slow

Xdebug adds execution overhead to every request. Turn it off when you are not actively debugging by setting:

```dotenv
# .env
SAIL_XDEBUG_MODE=off
```

Restart Sail using `sail down && sail up -d`.

---

<a id="frontend"></a>
## Vite, npm, and Node inside vs. outside Sail

You can compile frontend assets either on the host machine or inside Sail.

- **Host compilation (Fastest):** Run `npm run dev` in your local terminal.
- **Container compilation (Zero setup):** Run `sail npm run dev`.

Ensure your `APP_URL` and Vite ports match, otherwise you will encounter HMR connection failures in your console.

---

<a id="logs"></a>
## Logs and quick diagnostics

Run these commands to inspect container health and PHP states:

```bash
# Terminal
sail logs -f laravel.test
docker compose ps
sail exec laravel.test php -v
sail exec laravel.test php -m
```

---

<a id="volumes"></a>
## When to reset volumes (data loss)

If your local database gets corrupted or schema updates break, reset the volume. Remember: **`sail down -v` deletes all database tables and Redis cache keys.**

To safely reset only one database volume:
1. List volumes: `docker volume ls`
2. Remove target volume: `docker volume rm <volume_name>`

---

## ⚠️ Common Mistakes

**1. Mounting files across Windows partition boundaries**
Keeping your project folder in `C:/Users/...` and using WSL2 to run Sail. This degrades I/O speeds up to 10x.
*Reality:* Move the files to the Linux native directory, such as `\\wsl$\Ubuntu\home\ubuntu\projects\`.

**2. Missing PHP extensions in containers**
Running a database migration that uses PostgreSQL, while your container runtime has not been compiled with the PostgreSQL driver.
*Reality:* Verify running modules using `sail exec laravel.test php -m`. Publish the Dockerfiles and rebuild if an extension is missing.

**3. Port collision on localhost**
Running two Sail applications at once without changing the APP_PORT in one of the `.env` configurations.
*Reality:* Adjust `APP_PORT` and `FORWARD_*` port variables in `.env` for the second project.

---

## 🧠 Self-Check Questions

1. **Why should project files in WSL2 not be stored in the `/mnt/c/` path?**
2. **What command do you run to rebuild your Sail images after modifying a published Dockerfile?**
3. **True or False? Running `composer install` on your host terminal is always safe if you have the same PHP version as Sail.**
4. **How do you disable Xdebug in Sail when you are not using it to prevent slowdowns?**

<details>
<summary><b>Reveal Answers</b></summary>

1. Accessing files across the Windows filesystem boundary (`/mnt/c/`) introduces heavy virtualization translation layers, slowing down disk operations and breaking file change listeners.
2. Run `sail build --no-cache` followed by `sail up -d`.
3. **False.** Even if the PHP minor version matches, your host OS may lack required compilation libraries or PHP extensions that the container PHP has. Always run commands through Sail.
4. Set `SAIL_XDEBUG_MODE=off` in your `.env` file and restart the Sail containers.
</details>
