我已将Windows 10更新到2004最新版本,安装了wsl2并进行了更新,安装了docker和ubuntu。
当我使用“ Hello World”创建一个简单的 index.php 文件时,它运行良好(响应:100-400ms),但是当我添加我的 Laravel 项目时,它将变为即使在 PHPMyAdmin 运行非常平稳的情况下,它在执行请求之前加载 7sec 的时间很惨,并且响应为 4-7秒? :1-2秒)。
我的 docker-compose.yml 文件:
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
我已经尝试修复此问题2天了,但是找不到答案。
谢谢
答案 0 :(得分:6)
看起来您正在将Laravel项目安装在容器中。如果将这些文件从Windows环境挂载到WSL 2,则可能导致很差的文件I / O,因为WSL 2当前在访问Windows环境中的文件时遇到很多问题。该I / O问题截至2020年7月存在,您可以在Github here上找到该问题的持续状态。
我可以想到三种可能的解决方案,它们现在可以解决此问题。
为Docker禁用基于WSL 2的引擎,直到问题解决
由于仅当WSL 2尝试访问Windows文件系统时才会出现此问题,因此您可以选择禁用WSL 2泊坞窗集成,而是在Windows环境中运行容器。您可以在Docker桌面的用户界面中找到禁用它的选项:
将项目存储在WSL 2的Linux文件系统中
同样,由于当WSL 2尝试访问/mnt
下的Windows文件系统的安装点时会发生此问题,因此您可以选择将项目存储到WSL 2的Linux文件系统上。
构建自己的Dockerfile
您可以选择创建自己的Dockerfile,而不是装载项目,而可以COPY
将所需目录插入Docker映像。由于WSL 2仍必须访问Windows文件系统以构建这些docker映像,因此这将导致构建性能不佳,但是运行时性能会好得多,因为它不必从Windows环境中检索这些文件。每次。
答案 1 :(得分:2)
好的,所以我得到了一个有趣的事实:))
在没有WSL2的Windows上运行docker。
一个请求具有TTFB 5.41s。这是index.php文件。我使用die()检查时间在哪里更大,我发现如果终止后使用die(),则TTFB变为〜2.5s。
<?php
/**
* Laravel - A PHP Framework For Web Artisans
*
* @package Laravel
* @author Taylor Otwell <taylor@laravel.com>
*/
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
答案 2 :(得分:1)
您正在/mnt/xxx
文件夹中运行项目,不是吗?
这是因为wsl2 filesystem performance is much slower than wsl1 in /mnt.
如果您想要一个非常短的解决方案,请在这里。可从Windows应用商店在Ubuntu 18.04和Debian上运行:
Expose daemon on tcp://localhost:2375 without TLS
,然后关闭Use the WSL 2 based engine
。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
我编写了有关如何将Docker桌面与WSL集成的说明: https://github.com/CaliforniaMountainSnake/wsl-1-docker-integration
答案 3 :(得分:0)
这确实是提高速度的粗略方法,但实际上是这样:
从vendor
目录中加载作曲家依赖项的速度目前确实很慢,该目录从Windows上的项目根目录通过WSL 2映射到Docker容器。
将供应商目录复制到docker映像,并使用它,而不是在项目根目录中映射的目录。
使用MySQL数据库和Apache PHP 7.4以及composer自动加载功能的项目结构如下:
db
- init.sql
dev
- db
- Dockerfile
- data.sql
- www
- Dockerfile
- vendor-override.php
- docker-compose.yaml
src
- ...
vendor
- ...
composer.json
index.php
...
这里的想法是使开发人员资料与主根目录分开。
version: '3.8'
services:
test-db:
build:
context: ../
dockerfile: dev/db/Dockerfile
test-www:
build:
context: ../
dockerfile: dev/www/Dockerfile
ports:
- {insert_random_port_here}:80
volumes:
- ../:/var/www/html
这里,我们有两项服务,一项用于MySQL数据库,另一项用于带有PHP的Apache,它们将Web根/var/www/html
映射到我们的项目根。这使Apache可以查看项目源文件(src
和index.php
)。
FROM mysql:5.7.24
# Add initialize script (adding 0 in front of it, makes sure it is executed first as the scripts are loaded alphabetically)
ADD db/init.sql /docker-entrypoint-initdb.d/0init.sql
# Add test data (adding 99 infront of it, makes sure it is executed last)
ADD dev/db/data.sql /docker-entrypoint-initdb.d/99data.sql
FROM php:7.4.0-apache-buster
# Install PHP extensions and dependencies required by them
RUN apt-get update -y & \
apt-get install -y libzip-dev libpng-dev libssl-dev libxml2-dev libcurl4-openssl-dev & \
docker-php-ext-install gd json pdo pdo_mysql mysqli ftp simplexml curl
# Enable apache mods and .htaccess files
RUN a2enmod rewrite & \
sed -e '/<Directory \/var\/www\/>/,/<\/Directory>/s/AllowOverride None/AllowOverride All/' -i /etc/apache2/apache2.conf
# Add composer to improve loading speed since its located inside linux
ADD vendor /var/www/vendor
ADD dev/www/vendor-override.php /var/www/
RUN chmod -R 777 /var/www & \
mkdir /var/www/html/src & \
ln -s /var/www/html/src /var/www/src
# Expose html dir for easier deployments
VOLUME /var/www/html
我在PHP 7.4上使用了官方的Apache Buster映像。
vendor
目录和vendor-override.php
复制到Webroot(/var/www
)上方的目录,以免干扰项目根目录。ADD vendor /var/www/vendor
ADD dev/www/vendor-override.php /var/www/
chmod -R 777 /var/www
src
目录中自动加载类。这可以通过在项目根目录中创建从/var/www/src/
到/var/www/html/src
的链接来解决。mkdir /var/www/html/src
ln -s /var/www/html/src /var/www/src
# Override default composer dependencies to be loaded from inside docker. This is used because
# loading files over mapped volumes is really slow on WSL 2.
require_once "/var/www/vendor/autoload.php";
只需在docker映像中使用vendor
目录。
$fixFile = "../vendor-override.php";
if (file_exists($fixFile))
require_once $fixFile;
else
require_once "vendor/autoload.php";
...
如果检测到vendor-override.php
文件,则使用该文件,而不使用项目根目录下的文件。这样可以确保index.php
将dir加载到docker映像内部,速度更快。
{
"autoload": {
"psr-4": {
"Namespace\\": ["src"]
}
},
...
}
简单的自动加载设置将“名称空间”映射到项目根目录中的src
目录。
vendor-override.php
而不是供应商</ li>
缺点是每次更新依赖项时都必须构建docker映像。
答案 4 :(得分:0)
您可以从撰写文件中排除 vendor
文件夹
喜欢
volumes:
- ./www:/var/www
- vendor:/var/www/vendor
答案 5 :(得分:0)