Docker is extremely slow when running Laravel on Nginx container wsl2

28,425

Solution 1

It looks like you are mounting your Laravel project in your container. This could result in very poor file I/O if you are mounting these files from your Windows environment to WSL 2, since WSL 2 currently has a lot of problems accessing files that are on the Windows environment. This I/O issue exists as of July 2020, you can find the ongoing status of the issue on Github here.

There are three possible solutions I can think of that will resolve this issue for now.


Disable WSL 2 based engine for docker until the issue is resolved

Since this issue only occurs when WSL 2 tries to access the Windows filesystem, you could choose to disable WSL 2 docker integration and run your containers on your Windows environment instead. You can find the option to disable it in the UI of Docker Desktop here: enter image description here


Store your project in the Linux filesystem of WSL 2

Again, since this issue occurs when WSL 2 tries to access the mount points of the Windows filesystem under /mnt, you could choose to store your project onto the Linux filesystem of WSL 2 instead.


Build your own Dockerfiles

You could choose to create your own Dockerfiles and instead of mounting your project, you can COPY the desired directories into the docker images instead. This would result in poor build performance, since WSL 2 will still have to access your Windows filesystem in order to build these docker images, but the runtime performance will be much better, since it won't have to retrieve these files from the Windows environment everytime.

Solution 2

I experienced the same problem with mysql database requests and responses taking about 8 to 10 seconds for each request/response. The problem definitely relates to the mounting of files between the Windows file system and Windows WSL2. After many days of trying to resolve this issue, I found this post:

https://www.createit.com/blog/slow-docker-on-windows-wsl2-fast-and-easy-fix-to-improve-performance/

After implementing the steps specified in the post, it totally eliminated the problem, reducing database requests/responses to milliseconds. Hopefully this will assist someone experiencing the same issue.

Solution 3

You are running your project on the /mnt/xxx folder, isn't it?

This is because wsl2 filesystem performance is much slower than wsl1 in /mnt.

If your want a very short solution, it is here. Works on Ubuntu 18.04 and Debian from windows store:

  1. Go to the docker settings and turn on Expose daemon on tcp://localhost:2375 without TLS and turn off Use the WSL 2 based engine.
  2. Run this command:
clear && sudo apt-get update && \
sudo curl -fsSL https://get.docker.com -o get-docker.sh && sudo sh get-docker.sh && sudo usermod -aG docker $USER && \
sudo curl -L "https://github.com/docker/compose/releases/download/1.26.2/docker-compose-$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose && sudo chmod +x /usr/local/bin/docker-compose && \
echo "export PATH=\"$PATH:$HOME/.local/bin\"" >> ~/.profile && source ~/.profile && \
echo "export DOCKER_HOST=tcp://localhost:2375" >> ~/.bashrc && source ~/.bashrc && \
printf '[automount]\nroot = /\noptions = metadata' | sudo tee -a /etc/wsl.conf

I wrote the instuction how to integrate the Docker Desktop with WSL 1: https://github.com/CaliforniaMountainSnake/wsl-1-docker-integration

Solution 4

You just move all source project to folder

\\wsl$\Ubuntu-20.04\home\<User Name>\<Project Name>

The speed will be to very fast such run on Linux Native

Before

Before

After

After

Solution 5

Ok, so i got an interesting fact :))

Running docker on windows without WSL2.

A request has TTFB 5.41s. This is the index.php file. I used die() to check where the time is bigger and i found that if i use die() after terminate, the TTFB becomes ~2.5s.

<?php
/**
 * Laravel - A PHP Framework For Web Artisans
 *
 * @package  Laravel
 * @author   Taylor Otwell <[email protected]>
 */

define('LARAVEL_START', microtime(true));

require __DIR__.'/../../application/vendor/autoload.php';

$app = require_once __DIR__.'/../../application/bootstrap/app.php';

#die(); <-- TTFB 1.72s
$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

$response->send();

#die(); <-- TTFB 2.67s

$kernel->terminate($request, $response);

#die(); <-- TTFB 2.74s

#if there is no die in the file then TTFB is ~6s
Share:
28,425
Wail Hayaly
Author by

Wail Hayaly

Updated on January 03, 2022

Comments

  • Wail Hayaly
    Wail Hayaly over 2 years

    I've updated Windows 10 to 2004 latest version, installed wsl2 and updated it, installed docker, and ubuntu.

    When I create a simple index.php file with "Hello World" it's working perfectly ( response: 100-400ms ) but when I added my Laravel project it becomes miserable as it loads for 7sec before performing the request and the response is 4 - 7 seconds😢, even though PHPMyAdmin is running very smoothly ( response: 1 - 2 seconds ).

    my docker-compose.yml file:

    version: '3.8'
    networks:
      laravel:
    
    services:
      nginx:
        image: nginx:stable-alpine
        container_name: nginx
        ports:
          - "8080:80"
        volumes:
          - ./src:/var/www/html
          - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
        depends_on:
          - php
          - mysql
          - phpmyadmin
        networks:
          - laravel
    
      mysql:
        image: mysql:latest
        container_name: mysql
        restart: unless-stopped
        tty: true
        ports:
          - "3306:3306"
        environment:
          MYSQL_ROOT_PASSWORD: secret
          SERVICE_TAGS: dev
          SERVICE_NAME: mysql
        networks:
          - laravel
    
      phpmyadmin:
        image: phpmyadmin/phpmyadmin
        restart: always
        depends_on:
          - mysql
        ports:
          - 8081:80
        environment:
          PMA_HOST: mysql
          PMA_ARBITRARY: 1
    
      php:
        build:
          context: .
          dockerfile: Dockerfile
        container_name: php
        volumes:
          - ./src:/var/www/html
        ports:
          - "9000:9000"
        networks:
          - laravel
    
      composer:
        image: composer:latest
        container_name: composer
        volumes:
          - ./src:/var/www/html
        working_dir: /var/www/html
        depends_on:
          - php
        networks:
          - laravel
    
      npm:
        image: node:latest
        container_name: npm
        volumes:
          - ./src:/var/www/html
        working_dir: /var/www/html
        entrypoint: ['npm']
    
      artisan:
        build:
          context: .
          dockerfile: Dockerfile
        container_name: artisan
        volumes:
          - ./src:/var/www/html
        depends_on:
          - mysql
        working_dir: /var/www/html
        entrypoint: ['php', '/var/www/html/artisan']
        networks:
          - laravel
    

    I've been trying to fix this issue for 2 days but couldn't find the answer.

    Thanks

    • octagon_octopus
      octagon_octopus almost 4 years
      Did this not happen when you weren't using WSL 2? You could try disabling WSL 2 integration in Docker Desktop and check if the issue still persists. That would at least show whether the problem lies with WSL 2 or not.
    • Wail Hayaly
      Wail Hayaly almost 4 years
      I believe it was slightly better with hyper-v (before installing wsl2), but when I run PHPMyAdmin it works perfectly so maybe the problem is within the Laravel files as it asks me for sharing these files every time I build docker-compose.
    • octagon_octopus
      octagon_octopus almost 4 years
      Ahh, I maybe see what could be going wrong. Are you mounting your files from the windows file system? It could result in very poor i/o.
    • Wail Hayaly
      Wail Hayaly almost 4 years
      So what should I do?
    • user3529607
      user3529607 over 3 years
      Same issue here. Have you found an answer?
    • Yszty
      Yszty almost 3 years
      Same issue here. Laravel 14sec (mounted from windows) loading vs 500ms(copied to container). In this case we reinvented the wheel. I mounted network drive as file system 15 years ago and had same performance....
    • Luis Cruz
      Luis Cruz almost 3 years
      Did you fix it? How?, please share it
  • Wail Hayaly
    Wail Hayaly almost 4 years
    Tried to copy project files to mnt/wsl but failed (can't read from the source file or disk) the same thing when I copy to images containers, I ended up disabling wsl2 and removing ubuntu. :(
  • octagon_octopus
    octagon_octopus almost 4 years
    Your WSL filesystem isn't under mnt/WSL. It's that entire filesystem itself.
  • wasabi
    wasabi over 3 years
    I found the same thing in our project. I have no idea why die() does anything but it took our nginx + php stack from 6s per response to 200ms per response.
  • user3529607
    user3529607 over 3 years
    Could you please elaborate on "Store your project in WSL 2" How can I do it?
  • octagon_octopus
    octagon_octopus over 3 years
    @user3529607 Within WSL you have the Linux filesystem (e.g. directory \\wsl$\Ubuntu-18.04) and the Windows filesystem as a mount point (e.g. \\wsl$\Ubuntu-18.04\mnt\c). In a nutshell, place your project files somewhere other than a subdirectory of /mnt/, otherwise there is a good chance you will place your project files within the Windows filesystem, which is what causes the bad IO.
  • xlad
    xlad over 3 years
    nice, but really sketchy, hope there is another way
  • Dmitry
    Dmitry over 3 years
    How this disabled on windows 10 home?
  • Gul Muhammad
    Gul Muhammad about 3 years
    Can some one explain all the above steps in an easy matter/words
  • waterloomatt
    waterloomatt about 3 years
    Points 2 and 3 are fine for running applications but what about developing applications on Windows? Do we have to edit, save, and copy the file into the container each time? Sticking with option 1 until they have this resolved.
  • Bechilled
    Bechilled about 3 years
    Disable WSL 2 based engine works for me, thanks !
  • octagon_octopus
    octagon_octopus about 3 years
    @waterloomatt I'm not following completely. Point 2 and 3 shouldn't require you to edit, save and copy files into a container each time. Point 2 is just as simple as moving your project to a different directory and continuing to develop from there, although you will probably need an editor that supports developing in WSL to continue working (e.g. VSCode). Point 3 uses the COPY instruction in your Dockerfile, so you aren't copying files manually.
  • Andrii Sukhoi
    Andrii Sukhoi over 2 years
    Disabling WSL2 works perfectly! Thank you very much!
  • M P
    M P over 2 years
    Had to downgrade from wsl2 to wsl1 with hyper-v and spent hours trying various fixes. These are the only instructions that worked. Life saving!
  • Ahmed Sayed Sk
    Ahmed Sayed Sk over 2 years
    Thanks, This solution works for me.
  • Matěj Račinský
    Matěj Račinský over 2 years
    I excluded vendor from mounted volumes and it started running fast againg for me. It's a bit pain that I have different vendor in host and inside docker container, but it's good wnough workaround imho.
  • Claudio Ferraro
    Claudio Ferraro over 2 years
    I copied the files and updated my docker-compose in this way /var/www:/var/web/www:rw but they files seems not to be linked between docker windows and ubuntu. the folder in docker looks to be empty
  • Claudio Ferraro
    Claudio Ferraro over 2 years
    I tried point 2 , moved the files but after updating my docker-compose file with the new path the files seems to not be visible anymore by windows docker installation and i get an empty folder and cannot execute the project anymore. any hint ?
  • Aarony
    Aarony over 2 years
    Disabling WSL2 docker engine and enabling Hyper-V in windows 10 pro edition, worked for me, thanks. :-)
  • Krol
    Krol over 2 years
    why minus :( ???
  • mouchin777
    mouchin777 over 2 years
    This has improved the performarnce greatly. But i also have to limit the memory that docker uses otherwise it eats all the ram and the system goes slow
  • zardoz
    zardoz about 2 years
    i disabled WSL2 in Docker for Windows and got the same effect. 7,5s vs 1,7s. Linux Mint native docker time is 0,8s.
  • Thinh Nguyen
    Thinh Nguyen about 2 years
    @zardoz So you don't get a power of wsl