podman的基本用法
podman的基本设置和使用
运行示例容器
这个示例容器将运行一个非常基本的 httpd 服务器,它只服务于它的索引页面
[root@localhost ~]# podman run -dt -p 8080:8080/tcp -e HTTPD_VAR_RUN=/run/httpd -e HTTPD_MAIN_CONF_D_PATH=/etc/httpd/conf.d -e HTTPD_MAIN_CONF_PATH=/etc/httpd/conf -e HTTPD_CONTAINER_SCRIPTS_PATH=/usr/share/container-scripts/httpd/ registry.fedoraproject.org/f29/httpd /usr/bin/run-httpd
Trying to pull registry.fedoraproject.org/f29/httpd:latest...
Getting image source signatures
Copying blob aaf5ad2e1aa3 done
Copying blob 7692efc5f81c done
Copying blob d77ff9f653ce done
Copying config 25c76f9dcd done
Writing manifest to image destination
Storing signatures
a3f78ef2a19886d6f78e1bd85476c055002c693a34c6ccac3799c8181b0b2590
因为容器在分离模式下运行,由命令中的-dpodman run表示,所以 Podman 将在运行后打印容器 ID。请注意,我们使用端口转发来访问 HTTP 服务器。为了成功运行,至少需要 slirp4netns v0.3.0。
列出正在运行的容器
[root@localhost ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a3f78ef2a198 registry.fedoraproject.org/f29/httpd:latest /usr/bin/run-http... 31 seconds ago Up 31 seconds ago 0.0.0.0:8080->8080/tcp practical_banach
如果在ps命令中添加-a,Podman 将显示所有容器。
检查正在运行的容器
您可以“检查”正在运行的容器以获取有关其自身的元数据和详细信息。我们甚至可以使用 inspect 子命令来查看分配给容器的 IP 地址。如果容器在无根模式下运行,就不会分配 IP 地址,并且该值将在 inspect 的输出中列为“无”。
[root@localhost ~]# podman inspect -l | grep -i ipaddress
"IPAddress": "10.88.0.2",
"IPAddress": "10.88.0.2",
-l 是最新容器的方便参数。您也可以使用容器的 ID 代替 -l。
测试 httpd 服务器
//访问刚才查找到的IP地址
[root@localhost ~]# curl 10.88.0.2:8080
由于和主机做了端口映射,所以可以访问主机的8080端口
查看容器的日志
[root@localhost ~]# podman logs -l
=> sourcing 10-set-mpm.sh ...
=> sourcing 20-copy-config.sh ...
=> sourcing 40-ssl-certs.sh ...
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.88.0.2. Set the 'ServerName' directive globally to suppress this message
[Mon Aug 15 14:28:00.747895 2022] [ssl:warn] [pid 1:tid 140508146597248] AH01882: Init: this version of mod_ssl was compiled against a newer library (OpenSSL 1.1.1b FIPS 26 Feb 2019, version currently loaded is OpenSSL 1.1.1 FIPS 11 Sep 2018) - may result in undefined or erroneous behavior
[Mon Aug 15 14:28:00.753234 2022] [ssl:warn] [pid 1:tid 140508146597248] AH01909: 10.88.0.2:8443:0 server certificate does NOT include an ID which matches the server name
AH00558: httpd: Could not reliably determine the server's fully qualified domain name, using 10.88.0.2. Set the 'ServerName' directive globally to suppress this message
[Mon Aug 15 14:28:00.812665 2022] [ssl:warn] [pid 1:tid 140508146597248] AH01882: Init: this version of mod_ssl was compiled against a newer library (OpenSSL 1.1.1b FIPS 26 Feb 2019, version currently loaded is OpenSSL 1.1.1 FIPS 11 Sep 2018) - may result in undefined or erroneous behavior
[Mon Aug 15 14:28:00.813228 2022] [ssl:warn] [pid 1:tid 140508146597248] AH01909: 10.88.0.2:8443:0 server certificate does NOT include an ID which matches the server name
[Mon Aug 15 14:28:00.813352 2022] [lbmethod_heartbeat:notice] [pid 1:tid 140508146597248] AH02282: No slotmem from mod_heartmonitor
[Mon Aug 15 14:28:00.815031 2022] [mpm_event:notice] [pid 1:tid 140508146597248] AH00489: Apache/2.4.39 (Fedora) OpenSSL/1.1.1 configured -- resuming normal operations
[Mon Aug 15 14:28:00.815046 2022] [core:notice] [pid 1:tid 140508146597248] AH00094: Command line: 'httpd -D FOREGROUND'
[Mon Aug 15 14:30:28.568636 2022] [autoindex:error] [pid 27:tid 140507573319424] [client 10.88.0.1:54390] AH01276: Cannot serve directory /var/www/html/: No matching DirectoryIndex (index.html) found, and server-generated directory index forbidden by Options directive
10.88.0.1 - - [15/Aug/2022:14:30:28 +0000] "GET / HTTP/1.1" 403 4650 "-" "curl/7.61.1"
查看容器的 pid
[root@localhost ~]# podman top -l
USER PID PPID %CPU ELAPSED TTY TIME COMMAND
default 1 0 0.000 3m14.450346931s pts/0 0s httpd -D FOREGROUND
default 22 1 0.000 3m13.450524524s pts/0 0s /usr/bin/coreutils --coreutils-prog-shebang=cat /usr/bin/cat
default 23 1 0.000 3m13.450566843s pts/0 0s /usr/bin/coreutils --coreutils-prog-shebang=cat /usr/bin/cat
default 24 1 0.000 3m13.450659603s pts/0 0s /usr/bin/coreutils --coreutils-prog-shebang=cat /usr/bin/cat
default 25 1 0.000 3m13.450718705s pts/0 0s /usr/bin/coreutils --coreutils-prog-shebang=cat /usr/bin/cat
default 26 1 0.000 3m13.450813498s pts/0 0s httpd -D FOREGROUND
default 27 1 0.000 3m13.450850054s pts/0 0s httpd -D FOREGROUND
default 28 1 0.000 3m13.450946174s pts/0 0s httpd -D FOREGROUND
default 29 1 0.000 3m13.450980525s pts/0 0s httpd -D FOREGROUND
检查点容器
检查点容器会停止容器,同时将容器中所有进程的状态写入磁盘。有了这个,容器可以稍后恢复并在与检查点完全相同的时间点继续运行。此功能需要在系统上安装 CRIU 3.11 或更高版本。此功能不支持为无根;因此,如果您想尝试它,您需要以 root 身份重新创建您的容器
要检查点容器使用:
[root@localhost ~]# podman container checkpoint practical_banach
a3f78ef2a19886d6f78e1bd85476c055002c693a34c6ccac3799c8181b0b2590
[root@localhost ~]# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a3f78ef2a198 registry.fedoraproject.org/f29/httpd:latest /usr/bin/run-http... 3 minutes ago Exited (0) 5 seconds ago 0.0.0.0:8080->8080/tcp practical_banach
恢复容器
仅对以前设置检查点的容器才能恢复容器。恢复的容器将继续在与检查点完全相同的时间点运行。要恢复容器,请使用:
[root@localhost ~]# podman container restore practical_banach
a3f78ef2a19886d6f78e1bd85476c055002c693a34c6ccac3799c8181b0b2590
[root@localhost ~]# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a3f78ef2a198 registry.fedoraproject.org/f29/httpd:latest /usr/bin/run-http... 4 minutes ago Up 4 minutes ago 0.0.0.0:8080->8080/tcp practical_banach
恢复后,容器将像检查点之前一样再次响应请求。
[root@localhost ~]# curl 10.88.0.2:8080
迁移容器
要将容器从一台主机实时迁移到另一台主机,容器会在迁移的源系统上设置检查点,转移到目标系统,然后在目标系统上恢复。传输检查点时,可以指定输出文件。
在源系统上:
[root@localhost ~]# podman container checkpoint practical_banach -e /tmp/zzd.tar.gz
a3f78ef2a19886d6f78e1bd85476c055002c693a34c6ccac3799c8181b0b2590
[root@localhost ~]# scp /tmp/zzd.tar.gz root@192.168.169.141:/tmp
root@192.168.169.141's password:
zzd.tar.gz 100% 2817KB 26.7MB/s 00:00
在目标系统上:
[root@localhost ~]# podman container restore -i /tmp/zzd.tar.gz
a3f78ef2a19886d6f78e1bd85476c055002c693a34c6ccac3799c8181b0b2590
恢复后,容器将像检查点之前一样再次响应请求。这次容器将继续在目标系统上运行。
[root@localhost ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
a3f78ef2a198 registry.fedoraproject.org/f29/httpd:latest /usr/bin/run-http... About a minute ago Up About a minute ago 0.0.0.0:8080->8080/tcp practical_banach
[root@localhost ~]# curl 192.168.169.141:8080
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Test Page for the Apache HTTP Server on Fedora</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<style type="text/css">
………………
停止容器
[root@localhost ~]# podman stop -l
a3f78ef2a19886d6f78e1bd85476c055002c693a34c6ccac3799c8181b0b2590
删除容器:
[root@localhost ~]# podman rm -fl
a3f78ef2a19886d6f78e1bd85476c055002c693a34c6ccac3799c8181b0b2590
如何使用 Podman 签署和分发容器镜像
签署容器镜像的动机是只信任专门的镜像提供者以减轻中间人 (MITM) 攻击或对容器注册表的攻击。签署图像的一种方法是使用 GNU Privacy Guard ( GPG ) 密钥。这种技术通常与任何符合 OCI 的容器注册表兼容,例如:Quay.io。值得一提的是,OpenShift 集成容器注册表开箱即用地支持这种签名机制,这使得单独的签名存储变得不必要。
从技术角度来看,我们可以利用 Podman 对镜像进行签名,然后再将其推送到远程注册表。之后,所有运行 Podman 的系统都必须配置为从远程服务器检索签名,远程服务器可以是任何简单的 Web 服务器。这意味着在图像拉取操作期间,每个未签名的图像都将被拒绝。但这是如何工作的?
首先,我们必须创建一个 GPG 密钥对或选择一个已经在本地可用的密钥对。要生成新的 GPG 密钥,只需运行gpg --full-gen-key
并按照交互式对话框操作。现在我们应该能够验证密钥在本地是否存在:
[root@localhost ~]# gpg --full-gen-key
gpg (GnuPG) 2.2.20; Copyright (C) 2020 Free Software Foundation, Inc.
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
gpg: directory '/root/.gnupg' created
gpg: keybox '/root/.gnupg/pubring.kbx' created
Please select what kind of key you want:
(1) RSA and RSA (default)
(2) DSA and Elgamal
(3) DSA (sign only)
(4) RSA (sign only)
(14) Existing key from card
Your selection?
RSA keys may be between 1024 and 4096 bits long. #RSA密钥长度可能在1024到4096位之间
What keysize do you want? (2048) #你想要多大的钥匙?(2048)
Requested keysize is 2048 bits
Please specify how long the key should be valid. #请指定密钥的有效时间
0 = key does not expire
<n> = key expires in n days
<n>w = key expires in n weeks
<n>m = key expires in n months
<n>y = key expires in n years
Key is valid for? (0)
Key does not expire at all
Is this correct? (y/N) y
GnuPG needs to construct a user ID to identify your key.
Real name: zic@123.com
Email address: zic@123.com
Comment: zic
You selected this USER-ID:
"zic@123.com (zic) <zic@123.com>"
Change (N)ame, (C)omment, (E)mail or (O)kay/(Q)uit? O
┌──────────────────────────────────────────────────────
│ Please enter the passphrase to
│ protect your new key
│
│ Passphrase: *********_______________________________
│
│ <OK> <Cancel>
└──────────────────────────────────────────────────────
┌──────────────────────────────────────────────────────
│ Please re-enter this passphrase
│
│ Passphrase: *********_______________________________
│
│ <OK> <Cancel>
└──────────────────────────────────────────────────────
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
We need to generate a lot of random bytes. It is a good idea to perform
some other action (type on the keyboard, move the mouse, utilize the
disks) during the prime generation; this gives the random number
generator a better chance to gain enough entropy.
gpg: /root/.gnupg/trustdb.gpg: trustdb created
gpg: key 2DDFD8C82786D12D marked as ultimately trusted
gpg: directory '/root/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/F10A8DBB2458B0C794C29B772DDFD8C82786D12D.rev'
public and secret key created and signed.
pub rsa2048 2022-08-16 [SC]
F10A8DBB2458B0C794C29B772DDFD8C82786D12D
uid zic@123.com (zic) <zic@123.com>
sub rsa2048 2022-08-16 [E]
查看秘钥
[root@localhost ~]# gpg --list-key zic@123.com
gpg: checking the trustdb
gpg: marginals needed: 3 completes needed: 1 trust model: pgp
gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
pub rsa2048 2022-08-16 [SC]
F10A8DBB2458B0C794C29B772DDFD8C82786D12D
uid [ultimate] zic@123.com (zic) <zic@123.com>
sub rsa2048 2022-08-16 [E]
接下来我们可以部署一个harbor仓库,详细可见《harbor》
//部署完仓库后想要在podman上面使用,需要编辑/etc/containers/registries.conf文件
[root@localhost ~]# vim /etc/containers/registries.conf
[[registry]]
location = "harbor.example.com"
insecure = true
//编辑/etc/hosts文件
[root@localhost ~]# vim /etc/hosts
192.168.169.140 harbor.example.com
//登录到harbor仓库
[root@localhost ~]# podman login harbor.example.com
Username: admin
Password:
Login Succeeded!
让我们为我们的签名实验选择一个标准镜像:
[root@localhost ~]# podman pull docker://docker.io/alpine:latest
Trying to pull docker.io/library/alpine:latest...
Getting image source signatures
Copying blob 59bf1c3509f3 done
Copying config c059bfaa84 done
Writing manifest to image destination
Storing signatures
c059bfaa849c4d8e4aecaeb3a10c2d9b3d85f5165c66ad3a4d937758128c4d18
[root@localhost ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/httpd latest dabbfbe0c57b 7 months ago 148 MB
docker.io/library/alpine latest c059bfaa849c 8 months ago 5.87 MB
registry.fedoraproject.org/f29/httpd latest 25c76f9dcdb5 3 years ago 482 MB
现在我们可以重新标记图像以将其指向我们的本地注册表:
[root@localhost ~]# podman tag docker.io/library/alpine harbor.example.com/library/alpine
[root@localhost ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/httpd latest dabbfbe0c57b 7 months ago 148 MB
docker.io/library/alpine latest c059bfaa849c 8 months ago 5.87 MB
harbor.example.com/library/alpine latest c059bfaa849c 8 months ago 5.87 MB
registry.fedoraproject.org/f29/httpd latest 25c76f9dcdb5 3 years ago 482 MB
Podman 现在可以通过一个命令推送图像并对其进行签名。但是要让它工作,我们必须在以下位置修改我们的系统范围的注册表配置 /etc/containers/registries.d/default.yaml
:
[root@localhost ~]# vim /etc/containers/registries.d/default.yaml
default-docker:
sigstore: http://harbor.example.com
sigstore-staging: file:///var/lib/containers/sigstore
推送并签署镜像
[root@localhost ~]# podman push --tls-verify=false --sign-by zic@123.com harbor.example.com/library/alpine
Getting image source signatures
Copying blob 8d3ac3489996 done
Copying config c059bfaa84 done
Writing manifest to image destination
Signing manifest
Storing signatures
┌────────────────────────────────────────────────────────────────
│ Please enter the passphrase to unlock the OpenPGP secret key:
│ "zic@123.com (zic) <zic@123.com>"
│ 2048-bit RSA key, ID 2DDFD8C82786D12D,
│ created 2022-08-16.
│
│
│ Passphrase: *********_________________________________________
│
│ <OK> <Cancel>
└────────────────────────────────────────────────────────────────
如果我们现在看一下系统签名存储,我们会看到有一个新的签名可用,这是由镜像推送引起的:
[root@localhost ~]# ll /var/lib/containers/sigstore/library/
total 0
drwxr-xr-x. 2 root root 25 Aug 16 10:56 'alpine@sha256=964248be4bb8e3052c8b411271126f70c5c5015df31e014bfc41fad50edf78d8'