前置条件
- Windows 11 专业版 24H2
- podman desktop 1.18.1 x64
- Gitea 1.23.8
动手实践
Windows 的本质是是安装一个 Linux 虚拟机(当前是 Fedora 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 69 70 71 72 73 74 |
# 禁用 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 interface portproxy delete v4tov4 listenport=10880 listenaddress=0.0.0.0 # 防火墙放行端口,只需要允许外部访问进入即可 $ 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] 相关的日志输出:
1234567 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.248004645s2025/04/04 12:41:50 ...ron/tasks_actions.go:51:func1() [W] [Slow SQL Query] BEGIN TRANSACTION [] - 26m22.525253949s2025/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.760161949s2025/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.814803949s2025/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.019961149s2025/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 。
123 $ podman machine lsNAME VM TYPE CREATED LAST UP CPUS MEMORY DISK SIZEpodman-machine-default* wsl 21 minutes ago Currently running 12 50GiB 1.953TiB解决这个问题的方法就是不要进行映射,直接在存储在虚拟机的磁盘里。
12345678910111213141516171819202122232425262728293031323334353637 # 禁用 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 ,大型项目,如果内存不足的话,也可能诱发此类问题。
磁盘空间
默认情况下 WSL 2 最高分配 1TB 磁盘空间给虚拟机。如果要突破这个限制,需要进行磁盘手工扩容。
执行如下操作:
- 使用 wsl.exe --shutdown 命令终止所有 WSL 实例
- 获取磁盘路径 (PowerShell):
123 (Get-ChildItem -Path HKCU:\Software\Microsoft\Windows\CurrentVersion\Lxss | Where-Object { $_.GetValue("DistributionName") -eq 'podman-machine-default' }).GetValue("BasePath") + "\ext4.vhdx"\\?\E:\.containers\podman\machine\wsl\wsldist\podman-machine-default\ext4.vhdx- 使用管理员权限打开 Windows 命令提示符,然后输入以下命令来打开 diskpart 命令解释器:
1 diskpart- 现在会出现一个 DISKPART> 提示。 输入以下命令:
1 select vdisk file="\\?\E:\.containers\podman\machine\wsl\wsldist\podman-machine-default\ext4.vhdx"- 使用 Windows 命令提示符 DISKPART> 提示输入要分配给此 Linux 发行版的新的大小上限值(单位是 MB ),比如 2TB :
1 expand vdisk maximum=2048000- 退出 DISKPART> 提示:
1 exit- 安装 resize2fs 如下:
1 sudo dnf install resize2fs- 无损扩大分区大小,默认整个虚拟磁盘,命令如下:
1 sudo resize2fs /dev/sdc注意,如果执行 expand vdisk maximum=2048000 命令的时候报错 “虚拟磁盘服务错误”。可能是磁盘当前被挂载,导致无法进行磁盘扩容。此时需要命令行执行 diskmgmt 然后找到这个虚拟磁盘点击卸载之后再进行尝试。
开启两步验证后无法提交代码
如果开启了两步验证,gitea 的 PUSH 会失败,提示密码错误。此时登录需要使用 Access Token 作为密码。启用方式为登录后,前往 个人 -> 设置,选择“应用” ,“管理 Access Token”,增加一个,如下图:
带宽瓶颈
Gitea 服务器默认是不启用 Gzip 压缩的,这样会造成网络流量偏高。解决此问题最简单的方式是在相同的服务器上设置 Nginx/Apache 作为反向代理,然后在反向代理中启用压缩。
123456789 # 进入虚拟机$ podman machine ssh# 创建配置文件$ mkdir .containers/nginx-reverse-proxy$ mkdir .containers/nginx-reverse-proxy/conf.d$ touch .containers/nginx-reverse-proxy/conf.d/default.conf配置文件内容:
12345678910111213141516171819202122232425262728293031323334 server {listen 80;server_name static.example.com;root /var/www/static;# 不显示版本号,减少攻击面server_tokens off;# 配置location / {proxy_pass http://10.10.10.189:10880;# 响应时间 1800秒proxy_read_timeout 1800;# proxy http versionproxy_http_version 1.1;proxy_set_header Connection "";#(启用 gzip 压缩功能)gzip on;# 它的默认值是HTTP/1.1,就是说对HTTP/1.1协议的请求才会进行gzip压缩gzip_http_version 1.1;# 设置是禁用IE1-6版本的gzip压缩gzip_disable "MSIE [1-6].";# nginx做前端代理时启用该选项,表示无论后端服务器的headers头返回什么信息,都无条件启用压缩gzip_proxied any;# 最小压缩的页面,如果页面过于小,可能会越压越大,这里规定大于1K的页面才启用压缩gzip_min_length 1024;# 设置系统获取几个单位的缓存用于存储gzip的压缩结果数据流 按照原始数据大小以8K为单位申请8倍内存空间gzip_buffers 8 8k;# 压缩级别,1压缩比最小处理速度最快,9压缩比最大但处理最慢,同时也最消耗CPU,一般设置为3就可以了gzip_comp_level 5;# 什么类型的页面或文档启用压缩(text/html默认会压缩,所以可省略)gzip_types text/plain text/css application/javascript application/xml application/json;}}创建 Docker 服务:
12345678910111213141516171819202122232425262728 # 退出虚拟机$ exit# 拉取镜像# 外网# podman pull nginx:latest# 内网代理$ podman pull 10.10.10.189:6000/docker.io/library/nginx:latest --tls-verify=false# 启动镜像服务$ podman run -d --restart always --name nginx-reverse-proxy -p 10881:80 -v /home/user/.containers/nginx-reverse-proxy/conf.d:/etc/nginx/conf.d nginx# 端口转发# 参数说明# 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=10882 listenaddress=0.0.0.0 connectport=10881 connectaddress=127.0.0.1# 如果需要删除重新配置,则执行如下命令# netsh interface portproxy delete v4tov4 listenport=10882 listenaddress=0.0.0.0# 防火墙放行端口,只需要允许外部访问进入即可$ netsh advfirewall firewall add rule name="Nginx Reverse Proxy 10882" dir=in action=allow protocol=TCP localport=10882后续配置通过 nginx 的 10882 端口访问 Gitea 服务即可实现网络响应数据压缩功能。
参考链接
- 【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)
- 如何扩展 WSL 2 虚拟硬盘的大小
- 如何查找 Linux 发行版的 .vhdx 文件和磁盘路径
- Disk expansion
- Gitea/github等开启两步验证,git的PUSH失败问题
- Nginx反向代理开启gzip压缩

