适用于 Windows 的 Podman
虽然“容器是 Linux”,但 Podman 也可以在 Mac 和 Windows 上运行,它提供原生 CLI 并嵌入来宾 Linux 系统来启动您的容器。此 guest 称为 Podman 计算机,并使用命令进行管理。在 Windows 上,每台 Podman 计算机都由适用于 Linux 的虚拟化 Windows 子系统 (WSLv2) 发行版提供支持。podman 命令可以直接从 Windows PowerShell(或 CMD)提示符运行,它与在 WSL 环境中运行的 podman 服务远程通信。或者,如果您更喜欢 Linux 提示符和 Linux 工具,则可以直接从 WSL 实例访问 Podman。除了命令行访问之外,Podman 还侦听 Docker API 客户端,支持直接使用基于 Docker 的工具,以及从您选择的语言进行编程访问。podman machine
先决条件
由于 Podman 使用 WSL,因此您需要最新版本的 Windows 10 或 Windows 11。在 x64 上,WSL 需要内部版本 18362 或更高版本,arm64 系统需要 19041 或更高版本。在内部,WSL 使用虚拟化,因此您的系统必须支持并启用硬件虚拟化。如果您在 VM 上运行 Windows,则必须具有支持嵌套虚拟化的 VM。
还建议安装现代的“Windows 终端”,如果您需要,它可以提供比标准 PowerShell 和 CMD 提示以及 WSL 提示更出色的用户体验。
您可以通过搜索 Windows 应用商店或运行以下命令来安装它:winget
winget install Microsoft.WindowsTerminal
安装 Podman
安装 Windows Podman 客户端时,首先要下载 Podman Windows 安装程序。Windows 安装程序随每个 Podman 版本一起构建,可以从官方 GitHub 发布页面下载。请务必下载 4.1 或更高版本,才能使用本指南中讨论的功能。
安装 Podman 4.1.0
下载后,只需运行 EXE 文件,然后重新启动新终端即可。在此之后,podman.exe将出现在您的 PATH 上,您将能够运行命令来创建您的第一台计算机。podman machine init
PS C:\Users\User> podman machine init
自动 WSL 安装
如果您的系统上尚未安装 WSL,则第一个 machine init 命令将提示一个对话框以开始自动安装。如果接受,此过程将安装必要的 Windows 组件,重新启动系统,并在登录后在终端窗口中重新启动计算机创建过程。请务必等待一两分钟以重新启动,因为 Windows 在执行启动项之前会有延迟。或者,您可以拒绝自动安装并手动安装 WSL。但是,这将需要额外的下载和设置时间。
Machine Init 进程
安装 WSL 后,init 命令将安装 Fedora 的最小安装,并对其进行自定义以运行 podman。
PS C:\Users\User> podman machine init
Extracting compressed file
Importing operating system into WSL (this may take 5+ minutes on a new WSL install)...
Installing packages (this will take a while)...
Complete!
Configuring system...
Generating public/private ed25519 key pair.
Your identification has been saved in podman-machine-default
Your public key has been saved in podman-machine-default.pub
The key fingerprint is:
SHA256:RGTGg2Q/LX7ijN+mzu8+BzcS3cEWP6Hir6pYllJtceA root@WINPC
Machine init complete
To start your machine run:podman machine start
启动机
机器初始化进程完成后,可以根据需要启动和停止它:
PS C:\Users\User> podman machine startStarting machine "podman-machine-default"This machine is currently configured in rootless mode. If your containers
require root permissions (e.g. ports < 1024), or if you run into compatibility
issues with non-podman clients, you can switch using the following command:podman machine set --rootfulAPI forwarding listening on: npipe:./pipe/docker_engineDocker API clients default to this address. You do not need to set DOCKER_HOST.
Machine "podman-machine-default" started successfully
第一个 Podman 命令
从这一点开始,podman 命令的操作方式与它们在 Linux 上的操作方式类似。
有关小映像的快速工作示例,您可以在 PowerShell 上运行 Linux date 命令。
PS C:\Users\User> podman run ubi8-micro date
Thu May 5 21:56:42 UTC 2022
端口转发
端口转发也按预期工作;端口将绑定到 localhost (127.0.0.1)。注意:当以无根方式运行时(默认),您必须使用大于 1023 的端口。有关更多详细信息,请参阅 Rootful 和 Rootless 部分。
要启动 httpd,您可以运行:
PS C:\Users\User> podman run --rm -d -p 8080:80 --name httpd docker.io/library/httpd
f708641300564a6caf90c145e64cd852e76f77f6a41699478bb83a162dceada9
在 PowerShell 提示符上针对 localhost 的 curl 命令将返回成功的 HTTP 响应:
PS C:\Users\User> curl http://localhost:8080/ -UseBasicParsingStatusCode : 200
StatusDescription : OK
Content : <html><body><h1>It works!</h1></body></html>
与 Linux 一样,要停止,请运行:
podman stop httpd
使用 API 转发
API 转发允许 Docker API 工具和客户端像使用 Docker 一样使用 podman。前提是没有其他服务侦听 Docker API 管道;不需要特殊设置。
PS C:\Users\User> .\docker.exe run -it fedora echo "Hello Podman!"
Hello Podman!
否则,在启动计算机后,系统会通知您一个环境变量,您可以为工具设置以指向 podman。或者,您可以同时关闭冲突的服务和 podman,然后最后运行以重新启动,这应该会获取 Docker API 地址。podman machine start
Another process was listening on the default Docker API pipe address.
You can still connect Docker API clients by setting DOCKER HOST using the
following PowerShell command in your terminal session:$Env:DOCKER_HOST = 'npipe:./pipe/podman-machine-default'Or in a classic CMD prompt:set DOCKER_HOST=npipe:./pipe/podman-machine-defaultAlternatively, terminate the other process and restart podman machine.
Machine "podman-machine-default" started successfullyPS C:\Users\User> $Env:DOCKER_HOST = 'npipe:./pipe/podman-machine-default'
PS C:\Users\User>.\docker.exe version --format '{{(index .Server.Components 0).Name}}'
Podman Engine
Rootful & Rootless
在嵌入式 WSL Linux 发行版上,podman 可以在 root 用户 (rootful) 或非特权用户 (rootless) 下运行。为了与 Linux 上的 Podman 的行为保持一致,无根是默认设置。注意:Rootful 和 Rootless 容器是不同的,并且彼此隔离。针对一个命令(例如 podman ps)的 Podman 命令不会表示另一个命令的结果/状态。
虽然大多数容器在无根设置中运行良好,但您可能会发现容器仅以 root 权限运行的情况。如果是这种情况,您可以通过停止机器并使用 set 命令将机器切换到 rootful:
podman machine stop
podman machine set --rootful
要恢复无根执行,请将 rootful 设置为 false:
podman machine stop
podman machine set --rootful=false
您可能希望使用 root 执行的另一种情况是绑定小于 1024 的端口。但是,podman 的未来版本可能会将其降低到较低的数字,以提高与系统端口服务(例如 MySQL)上默认值的兼容性
卷挂载
Podman v4.1 的新功能是能够从 Windows 路径执行卷挂载到 Linux 容器中。这支持多种表示法方案,包括:
Windows 样式路径:
podman run --rm -v c:\Users\User\myfolder:/myfolder ubi8-micro ls /myfolder
Unixy Windows 路径:
podman run --rm -v /c/Users/User/myfolder:/myfolder ubi8-micro ls /myfolder
WSL 文件系统的本地 Linux 路径:
podman run --rm -v /var/myfolder:/myfolder ubi-micro ls /myfolder
上述所有约定都有效,无论是在 Windows 提示符上运行还是在 WSL Linux shell 上运行。尽管在 Linux 上使用 Windows 路径时,请适当地引用或转义参数的 Windows 路径部分。
列出 Podman 计算机
要列出可用的 podman 计算机实例及其当前资源使用情况,请使用以下命令:podman machine ls
PS C:\Users\User> podman machine lsNAME VM TYPE CREATED LAST UP CPUS MEMORY DISK SIZE
podman-machine-default wsl 2 hours ago Currently running 4 331.1MB 768MB
由于 WSL 在多个发行版中共享相同的虚拟机和 Linux 内核,因此 CPU 和 Memory 值表示在正在运行的系统之间共享的总资源。这与 Disk 值相反。它是独立的,表示每个单独分配的存储量。
访问 Podman Linux 环境
虽然在 Windows 环境中使用 podman.exe 客户端提供了支持使用本地桌面工具和 API 的无缝本机体验,但在某些情况下,您可能希望访问 Linux 环境:
- 在嵌入式 Fedora 实例上更新到最新的稳定软件包
- 直接使用 Linux 开发工具
- 使用依赖于 EXT4 文件系统性能或行为语义的工作流
有三种机制可以访问嵌入式 WSL 分发:1. SSH 使用 2.Windows PowerShell 提示符上的 WSL 命令 3.Windows 终端集成podman machine ssh
使用 SSH
SSH 访问提供与 Mac 上的 Podman 类似的体验。它会根据计算机的 rootful/non-less 配置(前者为 root,后者为 'user')立即将您放入适当的用户。--username 选项可用于覆盖特定用户。
使用 SSH 的一个示例任务是更新 Linux 环境以提取最新的操作系统错误修复:
podman machine ssh sudo dnf upgrade -y
使用 WSL 命令
该命令提供对 Linux 系统的直接访问,但首先以 root 身份进入 shell。这是由于 WSL 的设计限制,其中运行 systemd(Linux 的系统服务)需要使用特权进程命名空间。wsl
除非未安装其他 WSL 发行版,否则建议将选项与 podman 计算机的名称一起使用(podman-machine-default 是默认值)-d
PS C:\Users\User> wsl -d podman-machine-default
您将自动进入运行 systemd 的嵌套进程命名空间。如果需要访问父命名空间,请点击或键入 exit。这也意味着要注销,您需要退出两次。ctrl-d
[root@WINPC /]# podman --version
podman version 4.1.0
要以非特权用户(无根 podman)身份访问命令,必须首先键入 。或者,您也可以在命令前加上前缀以使用特殊的 :su user
wsl
enterns
wsl -d podman-machine-default enterns su user
[user@WINPC /]$ id
uid=1000(user) gid=1000(user) groups=1000(user),10(wheel)
同样,在不输入提示符的情况下以 root 身份运行命令也应以 .enterns
wsl -d podman-machine-default enterns systemctl status
不建议以特定用户身份使用或使用内联命令访问 WSL 实例,因为命令将针对不正确的命名空间执行。wsl -u
enterns
使用 Windows 终端集成
以 root 身份输入 WSL 只需 2 次单击操作。只需单击下拉标签,然后选择“podman-machine-default”,您将直接以 root 身份输入。
在 Windows 终端中使用 WSL
与以前一样,要切换到无根 podman 命令的非特权用户,请键入 。su user
[root@WINPC /]# su user
[user@WINPC /]$ podman info --format '{{.Store.RunRoot}}'
/run/user/1000/containers
停止 Podman 计算机
要停止正在运行的 podman 计算机,请使用以下命令:podman machine stop
PS C:\Users\User> podman machine stop
Machine "podman-machine-default" stopped successfully
删除 Podman 计算机
要删除计算机,请使用以下命令:podman machine rm
PS C:\Users\User> podman machine rmThe following files will be deleted:C:\Users\User\.ssh\podman-machine-default
C:\Users\User\.ssh\podman-machine-default.pub
C:\Users\User\.local\share\containers\podman\machine\wsl\podman-machine-default_fedora-35-x86_64.tar
C:\Users\User\.config\containers\podman\machine\wsl\podman-machine-default.json
C:\Users\User\.local\share\containers\podman\machine\wsl\wsldist\podman-machine-defaultAre you sure you want to continue? [y/N] y
故障 排除
从 WSL 自动安装失败中恢复
如果自动安装失败且重试不成功,您可以尝试重置 WSL 系统状态并使用命令执行手动 WSL 安装。为此,请执行以下步骤:wsl --install
-
以管理员身份启动 PowerShell
Start-Process powershell -Verb RunAs
-
禁用 WSL 功能
dism.exe /online /disable-feature /featurename:Microsoft-Windows-Subsystem-Linux /norestart dism.exe /online /disable-feature /featurename:VirtualMachinePlatform /norestart
-
重新启动
-
运行手动 WSL 安装
wsl --install
-
继续使用 podman machine init
安装 Certificate Authority
有关安装 CA 证书的说明,请参阅此处。
实践操作
podman machine init
Downloading VM image: v20241215061152-5.2-rootfs-amd64.tar.zst [===========>--------------------------------------------Downloading
Downloading VM image: v20241215061152-5.2-rootfs-amd64.tar.zst: done
Extracting compressed file: podman-machine-default-amd64: done
Importing operating system into WSL (this may take a few minutes on a new WSL install)...
正在导入,这可能需要几分钟时间。
操作成功完成。
Configuring system...
Machine init complete
To start your machine run:podman machine startwsl -l
适用于 Linux 的 Windows 子系统分发:
podman-machine-default (默认)
Netdatawsl --set-default podman-machine-defaultPS C:\WINDOWS\system32> wslYou will be automatically entered into a nested process namespace where
systemd is running. If you need to access the parent namespace, hit ctrl-d
or type exit. This also means to log out you need to exit twice.[user@DESKTOP-Q8IT0HS ~]$
PS C:\WINDOWS\system32> wslYou will be automatically entered into a nested process namespace where
systemd is running. If you need to access the parent namespace, hit ctrl-d
or type exit. This also means to log out you need to exit twice.[user@DESKTOP-Q8IT0HS ~]$ cat /etc/os-release
NAME="Fedora Linux"
VERSION="40 (Container Image)"
ID=fedora
VERSION_ID=40
VERSION_CODENAME=""
PLATFORM_ID="platform:f40"
PRETTY_NAME="Fedora Linux 40 (Container Image)"
ANSI_COLOR="0;38;2;60;110;180"
LOGO=fedora-logo-icon
CPE_NAME="cpe:/o:fedoraproject:fedora:40"
DEFAULT_HOSTNAME="fedora"
HOME_URL="https://fedoraproject.org/"
DOCUMENTATION_URL="https://docs.fedoraproject.org/en-US/fedora/f40/system-administrators-guide/"
SUPPORT_URL="https://ask.fedoraproject.org/"
BUG_REPORT_URL="https://bugzilla.redhat.com/"
REDHAT_BUGZILLA_PRODUCT="Fedora"
REDHAT_BUGZILLA_PRODUCT_VERSION=40
REDHAT_SUPPORT_PRODUCT="Fedora"
REDHAT_SUPPORT_PRODUCT_VERSION=40
SUPPORT_END=2025-05-13
VARIANT="Container Image"
VARIANT_ID=container[user@DESKTOP-Q8IT0HS ~]$ podman -v
podman version 5.3.1
[user@DESKTOP-Q8IT0HS ~]$ podman pull hello-world
WARN[0000] Using cgroups-v1 which is deprecated in favor of cgroups-v2 with Podman v5 and will be removed in a future version. Set environment variable `PODMAN_IGNORE_CGROUPSV1_WARNING` to hide this warning.
Resolved "hello-world" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull quay.io/podman/hello:latest...
Getting image source signatures
Copying blob 81df7ff16254 done |
Copying config 5dd467fce5 done |
Writing manifest to image destination
5dd467fce50b56951185da365b5feee75409968cbab5767b9b59e325fb2ecbc0
[user@DESKTOP-Q8IT0HS ~]$ podman run hello-world
WARN[0000] Using cgroups-v1 which is deprecated in favor of cgroups-v2 with Podman v5 and will be removed in a future version. Set environment variable `PODMAN_IGNORE_CGROUPSV1_WARNING` to hide this warning.
!... Hello Podman World ...!.--"--./ - - \/ (O) (O) \~~~| -=(,Y,)=- |.---. /` \ |~~~/ o o \~~~~.----. ~~| =(X)= |~ / (O (O) \~~~~~~~ ~| =(Y_)=- |~~~~ ~~~| U |~~Project: https://github.com/containers/podman
Website: https://podman.io
Desktop: https://podman-desktop.io
Documents: https://docs.podman.io
YouTube: https://youtube.com/@Podman
X/Twitter: @Podman_io
Mastodon: @Podman_io@fosstodon.org
sudo vi /etc/containers/registries.conf
[user@DESKTOP-Q8IT0HS ~]$ cp /etc/containers/registries.conf /etc/containers/registries.conf.bak
cp: cannot create regular file '/etc/containers/registries.conf.bak': Permission denied
[user@DESKTOP-Q8IT0HS ~]$ sudo cp /etc/containers/registries.conf /etc/containers/registries.conf.bak
unqualified-search-registries = ["docker.io"][[registry]]
prefix = "docker.io"
location="你自己的阿里云加速器地址.mirror.aliyuncs.com" #如xx.mirror.aliyuncs.com,不要加https、http之类的东西
cat /etc/containers/registries.conf
# For more information on this configuration file, see containers-registries.conf(5).
#
# NOTE: RISK OF USING UNQUALIFIED IMAGE NAMES
# We recommend always using fully qualified image names including the registry
# server (full dns name), namespace, image name, and tag
# (e.g., registry.redhat.io/ubi8/ubi:latest). Pulling by digest (i.e.,
# quay.io/repository/name@digest) further eliminates the ambiguity of tags.
# When using short names, there is always an inherent risk that the image being
# pulled could be spoofed. For example, a user wants to pull an image named
# `foobar` from a registry and expects it to come from myregistry.com. If
# myregistry.com is not first in the search list, an attacker could place a
# different `foobar` image at a registry earlier in the search list. The user
# would accidentally pull and run the attacker's image and code rather than the
# intended content. We recommend only adding registries which are completely
# trusted (i.e., registries which don't allow unknown or anonymous users to
# create accounts with arbitrary names). This will prevent an image from being
# spoofed, squatted or otherwise made insecure. If it is necessary to use one
# of these registries, it should be added at the end of the list.
#
# # An array of host[:port] registries to try when pulling an unqualified image, in order.
# unqualified-search-registries = ["example.com"]
unqualified-search-registries = ["registry.fedoraproject.org", "registry.access.redhat.com", "docker.io"]
#
# [[registry]]
# # The "prefix" field is used to choose the relevant [[registry]] TOML table;
# # (only) the TOML table with the longest match for the input image name
# # (taking into account namespace/repo/tag/digest separators) is used.
# #
# # The prefix can also be of the form: *.example.com for wildcard subdomain
# # matching.
# #
# # If the prefix field is missing, it defaults to be the same as the "location" field.
# prefix = "example.com/foo"
#
# # If true, unencrypted HTTP as well as TLS connections with untrusted
# # certificates are allowed.
# insecure = false
#
# # If true, pulling images with matching names is forbidden.
# blocked = false
#
# # The physical location of the "prefix"-rooted namespace.
# #
# # By default, this is equal to "prefix" (in which case "prefix" can be omitted
# # and the [[registry]] TOML table can only specify "location").
# #
# # Example: Given
# # prefix = "example.com/foo"
# # location = "internal-registry-for-example.com/bar"
# # requests for the image example.com/foo/myimage:latest will actually work with the
# # internal-registry-for-example.com/bar/myimage:latest image.
#
# # The location can be empty if prefix is in a
# # wildcarded format: "*.example.com". In this case, the input reference will
# # be used as-is without any rewrite.
# location = internal-registry-for-example.com/bar"
#
# # (Possibly-partial) mirrors for the "prefix"-rooted namespace.
# #
# # The mirrors are attempted in the specified order; the first one that can be
# # contacted and contains the image will be used (and if none of the mirrors contains the image,
# # the primary location specified by the "registry.location" field, or using the unmodified
# # user-specified reference, is tried last).
# #
# # Each TOML table in the "mirror" array can contain the following fields, with the same semantics
# # as if specified in the [[registry]] TOML table directly:
# # - location
# # - insecure
# [[registry.mirror]]
# location = "example-mirror-0.local/mirror-for-foo"
# [[registry.mirror]]
# location = "example-mirror-1.local/mirrors/foo"
# insecure = true
# # Given the above, a pull of example.com/foo/image:latest will try:
# # 1. example-mirror-0.local/mirror-for-foo/image:latest
# # 2. example-mirror-1.local/mirrors/foo/image:latest
# # 3. internal-registry-for-example.com/bar/image:latest
# # in order, and use the first one that exists.
short-name-mode = "enforcing"
[user@DESKTOP-Q8IT0HS ~]$