前置条件
- Windows 11 专业版 24H2
- podman desktop 1.17.2 x64
- Gitea 1.23.6
动手实践
Windows 的本质是是安装一个 Linux 虚拟机,然后在虚拟机中安装 Gitea ,所以会出现后面需要进行端口数据转发。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 |
# 禁用 Hyper-V 功能 $ DISM /Online /Disable-Feature /FeatureName:Microsoft-Hyper-V # 启用 VirtualMachinePlatform 功能 $ DISM /Online /Enable-Feature /All /FeatureName:VirtualMachinePlatform # 启用 Microsoft-Windows-Subsystem-Linux 功能 $ DISM /Online /Enable-Feature /All /FeatureName:Microsoft-Windows-Subsystem-Linux $ wsl --update # 使用 WSL 2.0 或者 Hyper-V 版本,但是不要通过 -v 参数进行目录映射。目录映射使用9P协议,该协议性能低下,造成严重性能问题,并且高负载,高并发下文件系统不稳定。 # 但是 WSL 1.0 文件权限不正确,默认创建的文件权限都是 777,导致权限问题。 # 建议优先使用 WSL 2.0。 # Windows 11 默认就是 WSL 2.0 但是 Windows 10 默认是 WSL 1.0 需要手工设置成 WSL 2.0。 $ wsl --set-default-version 2 $ wsl --install --no-distribution # 由于我们的磁盘 E: 是主要的数据磁盘,因此通过软链接的方式,把 Podman 虚拟机的目录链接到E盘 $ mkdir 'E://.containers' # 软链接到 Podman 容器目录 $ New-Item -ItemType SymbolicLink -Path ~/.local/share/containers -Target 'E://.containers' # 指定给出 12个CPU核心 内存 50GB,磁盘2TB 此处如果不指定,默认是核心数/内存的一半,磁盘默认100GB # 不要通过 -v 参数进行 Windows 目录映射,两者文件系统格式不同,需要通过9p协议转换,性能损失巨大,不如直接给出足够大的磁盘空间,文件直接存储在虚拟机内部 $ podman machine init --cpus 12 -m 51200 --disk-size 2000 $ podman machine start # 配置开机自启动 # 进入容器虚拟机 $ podman machine ssh # If your VM is rootful, run `sudo systemctl enable podman-restart.service`; if it's rootless, run `sudo systemctl --global enable podman-restart.service`; if in doubt, do both $ sudo systemctl enable podman-restart.service $ sudo systemctl --global enable podman-restart.service # 创建容器目录 $ mkdir .containers $ mkdir .containers/gitea # 退出容器虚拟机 $ exit $ podman pull docker.gitea.com/gitea:latest # 此处我们 默认不导出 ssh 访问,只允许 http 访问 # 不要通过 -v 参数进行 Windows 目录映射,两者文件系统格式不同,需要通过9p协议转换,性能损失巨大,还不如直接给出足够大的磁盘空间,文件直接存储在虚拟机内部 $ podman run -d --restart always --name gitea -p 10890:3000 -v /home/user/.containers/gitea:/data gitea # 端口转发 # 参数说明 # v4tov4 : IPV4协议转发到IPV4协议 # listenport : 对外暴露的端口,其他设备访问本机的端口 # listenaddress : 监听地址,一般都是设置成 0.0.0.0 允许任何服务器访问服务 # connectport : podman提供的Docker容器的对外暴露端口 # connectaddress : podman提供的Docker容器的IP地址,由于podman每次重启都可能改变容器IP,但是本机都可以通过 127.0.0.1(localhost) 访问,所以干脆直接写成 127.0.0.1 # 特别注意的是,两个端口号不要写成一样的,否则会进入转发死循环 $ netsh interface portproxy add v4tov4 listenport=10880 listenaddress=0.0.0.0 connectport=10890 connectaddress=127.0.0.1 # 防火墙放行端口,只需要允许外部访问进入即可 $ netsh advfirewall firewall add rule name="Gitea Port 10880" dir=in action=allow protocol=TCP localport=10880 |
后续如果想修改配置文件,那么需要通过 podman machine ssh 进入容器进行修改。
另外虚拟机整个被默认WSL2 挂载到 \\\\wsl.localhost\ 目录下,可以直接在 Windows 系统下访问,但是修改的时候可能会没有权限,还是需要通过命令行修改。
如果 Podman Desktop 没有开机自启动,确认如下如下配置是否已经勾选:
注意:如果对大型项目进行镜像部署,比如 chromium 。登录之前可以正常使用,登录特别慢,注意观察 Podman 的 Logs 项,如果观察到如下内容,特别是 [Slow SQL Query] 相关的日志输出:
1 2 3 4 5 6 7 |
2025/04/04 12:36:38 ...eb/routing/logger.go:102:func1() [I] router: completed GET /mirrors/v8/commit/bf6a80f34c17cad8f648c1305fe774d64f149b52 for 111.225.148.57:0, 404 Not Found in 2.9ms @ context/repo.go:401(context.RepoAssignment) 2025/04/04 12:41:50 ...s/repository/push.go:96:pushUpdates() [W] [Slow SQL Query] UPDATE `repository` SET `size` = ?, `git_size` = ?, `lfs_size` = ? WHERE `id`=? [1510601333 1510601333 0 9] - 26m4.248004645s 2025/04/04 12:41:50 ...ron/tasks_actions.go:51:func1() [W] [Slow SQL Query] BEGIN TRANSACTION [] - 26m22.525253949s 2025/04/04 12:41:50 ...ces/feed/notifier.go:340:PushCommits() [W] [Slow SQL Query] INSERT INTO `action` (`user_id`,`op_type`,`act_user_id`,`repo_id`,`comment_id`,`is_deleted`,`ref_name`,`is_private`,`content`,`created_unix`) VALUES (?,?,?,?,?,?,?,?,?,?) [1 push_tag 1 9 0 false refs/tags/5.4.499 false {"Commits":null,"HeadCommit":{"Sha1":"352c9d652b5920e568c8cc8298e6f786aef20653","Message":"Version 5.4.499\n\nPerformance and stability improvements on all platforms.\n\nCr-Commit-Position: refs/heads/5.4.499@{#1}\nCr-Branched-From: 6fe0b39b0167a71a1d9265c035c245c30b71b573-refs/heads/master@{#38837}\n","AuthorEmail":"v8-autoroll@chromium.org","AuthorName":"v8-autoroll@chromium.org","CommitterEmail":"v8-autoroll@chromium.org","CommitterName":"v8-autoroll@chromium.org","Timestamp":"2016-08-23T10:40:26-07:00"},"CompareURL":"v8/v8/compare/0000000000000000000000000000000000000000...352c9d652b5920e568c8cc8298e6f786aef20653","Len":0} 1743768927] - 26m22.760161949s 2025/04/04 12:41:50 ...ces/feed/notifier.go:340:PushCommits() [W] [Slow SQL Query] INSERT INTO `action` (`user_id`,`op_type`,`act_user_id`,`repo_id`,`comment_id`,`is_deleted`,`ref_name`,`is_private`,`content`,`created_unix`) VALUES (?,?,?,?,?,?,?,?,?,?) [1 push_tag 1 9 0 false refs/tags/5.6.129 false {"Commits":null,"HeadCommit":{"Sha1":"7d2ac2e7f629d23f3c775764e0ff6fdf586a25fc","Message":"Version 5.6.129\n\nPerformance and stability improvements on all platforms.\n\nCr-Commit-Position: refs/heads/5.6.129@{#1}\nCr-Branched-From: 14be3846bd12c3930027af2fe1192fe301806ef9-refs/heads/master@{#40497}\n","AuthorEmail":"hablich@chromium.org","AuthorName":"Michael Hablich","CommitterEmail":"hablich@chromium.org","CommitterName":"Michael Hablich","Timestamp":"2016-10-21T14:56:50+02:00"},"CompareURL":"v8/v8/compare/0000000000000000000000000000000000000000...7d2ac2e7f629d23f3c775764e0ff6fdf586a25fc","Len":0} 1743768927] - 26m22.814803949s 2025/04/04 12:41:50 ...ces/feed/notifier.go:340:PushCommits() [W] [Slow SQL Query] INSERT INTO `action` (`user_id`,`op_type`,`act_user_id`,`repo_id`,`comment_id`,`is_deleted`,`ref_name`,`is_private`,`content`,`created_unix`) VALUES (?,?,?,?,?,?,?,?,?,?) [1 push_tag 1 9 0 false refs/tags/5.7.324.2 false {"Commits":null,"HeadCommit":{"Sha1":"65e3722a1995fbbdb266d19e717d65749c9444e5","Message":"Version 5.7.324.2 (cherry-pick)\n\nMerged aa8a208a473af43e7aa97626d8d2a4a81667850c\n\nRevert of [TypeFeedbackVector] Root literal arrays in function literals slots (patchset #11 id:370001 of https://codereview.chromium.org/2504153002/ )\n\nTBR=jgruber@chromium.org\n\nReview-Url: https://codereview.chromium.org/2592393002 .\nCr-Commit-Position: refs/heads/5.7.324@{#3}\nCr-Branched-From: 2041c504025d706041e50e52d9e8c7221667492d-refs/heads/master@{#41902}\n","AuthorEmail":"hablich@chromium.org","AuthorName":"Michael Hablich","CommitterEmail":"hablich@chromium.org","CommitterName":"Michael Hablich","Timestamp":"2016-12-22T11:31:14+01:00"},"CompareURL":"v8/v8/compare/0000000000000000000000000000000000000000...65e3722a1995fbbdb266d19e717d65749c9444e5","Len":0} 1743768928] - 26m22.019961149s 2025/04/04 12:41:50 ...ces/feed/notifier.go:340:PushCommits() [W] [Slow SQL Query] INSERT INTO `action` (`user_id`,`op_type`,`act_user_id`,`repo_id`,`comment_id`,`is_deleted`,`ref_name`,`is_private`,`content`,`created_unix`) VALUES (?,?,?,?,?,?,?,?,?,?) [1 push_tag 1 9 0 false refs/tags/5.8.294 false {"Commits":null,"HeadCommit":{"Sha1":"376fd4b2eb6a1ff398d4a8b58ce1ce9feb5273db","Message":"Version 5.8.294\n\nPerformance and stability improvements on all platforms.\n\nCr-Commit-Position: refs/heads/5.8.294@{#1}\nCr-Branched-From: d747855e23c28d74593bb272cd629aaab4c379ca-refs/heads/master@{#43469}\n","AuthorEmail":"v8-autoroll@chromium.org","AuthorName":"v8-autoroll","CommitterEmail |
上述的输出非常的不合理,简单的 SQL 语句执行耗时高达 26分钟,这个结果是非常不合理的。SQLite 的性能不可能这么差劲。
导出数据库文件,通过 SQLiteStudio 执行相同的 SQL 语句,在 0.1 毫秒执行结束。
并且 Docker 多次重启之后,高概率发生文件损坏。另一个常见现象是处理器占用长时间处于高位,某几个核心长时间满负荷,但是 DUMP 堆栈调用又一切正常,看不到用户态的高占用函数。
这个原因是由于 Windows 和 Linux 的跨系统文件兼容性问题无法得到很好的解决,WSL 2 下访问 Windows 文件性能会非常差。
具体解释参考 [wsl2] filesystem performance is much slower than wsl1 in /mnt #4197 。
1 2 3 |
$ podman machine ls NAME VM TYPE CREATED LAST UP CPUS MEMORY DISK SIZE podman-machine-default* wsl 21 minutes ago Currently running 12 50GiB 1.953TiB |
解决这个问题的方法就是不要进行映射,直接在存储在虚拟机的磁盘里。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
# 禁用 Hyper-V 功能 $ DISM /Online /Disable-Feature /FeatureName:Microsoft-Hyper-V # 启用 VirtualMachinePlatform 功能 $ DISM /Online /Enable-Feature /All /FeatureName:VirtualMachinePlatform # 启用 Microsoft-Windows-Subsystem-Linux 功能 $ DISM /Online /Enable-Feature /All /FeatureName:Microsoft-Windows-Subsystem-Linux # 删除之前创建的虚拟机 $ podman machine stop podman-machine-default $ podman machine rm -f podman-machine-default $ podman system connection rm podman-machine-default $ podman system connection rm podman-machine-default-root $ wsl --uninstall podman-machine-default $ wsl --update # 使用 WSL 2.0 或者 Hyper-V 版本,但是不要通过 -v 参数进行目录映射。目录映射使用9P协议,该协议性能低下,造成严重性能问题,并且高负载,高并发下文件系统不稳定。 # 但是 WSL 1.0 文件权限不正确,默认创建的文件权限都是 777,导致权限问题。 # 建议优先使用 WSL 2.0。 # Windows 11 默认就是 WSL 2.0 但是 Windows 10 默认是 WSL 1.0 需要手工设置成 WSL 2.0。 $ wsl --set-default-version 2 $ wsl --install --no-distribution # 指定给出 12个CPU核心 内存 50GB,磁盘2TB 此处如果不指定,默认是核心数/内存的一半,磁盘默认100GB # 不要通过 -v 参数进行 Windows 目录映射,两者文件系统格式不同,需要通过9p协议转换,性能损失巨大,不如直接给出足够大的磁盘空间,文件直接存储在虚拟机内部 $ podman machine init --cpus 12 -m 51200 --disk-size 2000 # 上述的配置不一定能生效,最终还是需要 .wslconfig 指定内存大小 $ podman machine start |
同时,建议内存不低于 32GB ,大型项目,如果内存不足的话,也可能诱发此类问题。
参考链接
- 【windows】查看和开放特定的端口
- 使用命令行管理 Windows 防火墙
- Accessing network applications with WSL
- Netsh interface portproxy commands
- GitLab的替代者-轻量级Gitea安装与配置
- 记录一次 Windows 端的 podman 启动的容器应用外部引用无法访问的问题处理
- Podman: Networking in WSL
- windows上使用netsh映射端口至Hyper-v虚拟机
- Podman container on Windows cannot access host by ip or dns. Linux and Mac OS do not have this issue.#13966
- windows下安装podman ,无法通过本机ipv4地址访问容器,但是127.0.0.1可以访问
- Podman for Windows
- How to Autostart Podman Containers on Windows ?
- Slow browsing on http2 enabled reverse proxy (apache2), long-polling /user/events blocks other requests #19265
- Very slow to load pages
- gitea Reverse Proxies
- Apache Module mod_proxy
- LANDING_PAGE=login leads to endless redirects if you're logged in #28231
- Using Apache HTTPD with a sub-path as a reverse proxy
- Option to show login page instead of home page #9597
- WSL 中的高级设置配置
- 只给对象实现功能所需的最小权限和可见性
- Windows 10 Docker 基于 WSL 2 时读写性能的坑
- WSL2文件系统处理速度较慢
- [wsl2] filesystem performance is much slower than wsl1 in /mnt #4197
- 在 Windows 上安装 Podman 桌面和 Podman
- Hyper-V: How to Enable It and Fix Its Assembly Not Found Error
- 已解决 WSL / WSL2 请启用虚拟机平台 Windows 功能并确保在 BIOS 中启用虚拟化问题
- 如何在Windows 10中彻底卸载并移除Ubuntu WSL子系统及其配置文件
- Podman desktop setup - WSL import of guest OS failed: exit status 0xffffffff #8233
- Permission denied is returned when trying to access some host folders mounted in Hyper-V machines #25686
- 如何在Win11下安装linux子系统(WSL1),并配置anaconda+pytorch深度学习环境的完整教程(30系列显卡包括RTX3090也适用)
- 全网最全Win10/11系统下WSL2+Ubuntu20.04的全流程安装指南(两种支持安装至 D 盘方式)
- WSL 使用中遇到的问题及解决方案 #2 - DrvFs 文件系统权限问题
- WSL 使用中遇到的问题及解决方案 #3 - SSH 密钥权限问题
- 在 WSL 2 中装载 Linux 磁盘
- windows wsl挂载本地vhdx、扩展vdhx磁盘与wsl常见问题
- Windows下Podman Desktop容器目录迁移至其他硬盘的详细步骤
- 解决WSL2占用内存过多问题(Docker on WSL2: VmmemWSL)