podman基础设置与使用

发布于:2023-01-16 ⋅ 阅读:(549) ⋅ 点赞:(0)

podman基础用法

Podman的基础设置和使用

熟悉Podman

运行示例容器
此示例容器将运行一个非常基本的 httpd 服务器,该服务器仅为其索引页提供服务

[root@podman ~]# 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 7692efc5f81c done  
Copying blob aaf5ad2e1aa3 done  
Copying blob d77ff9f653ce done  
Copying config 25c76f9dcd done  
Writing manifest to image destination
Storing signatures
62b51b4ca194a6d180b85588f7772a515037209834fef81551227b70cf22d128

由于容器在分离模式下运行(在命令中由 -d 表示),因此 Podman 将在运行后打印容器 ID。请注意,我们使用端口转发来访问 HTTP 服务器。要成功运行,至少需要 slirp4netns v0.3.0。

[root@podman ~]# rpm -qa|grep slirp4netns
slirp4netns-1.1.8-1.module_el8.5.0+890+6b136101.x86_64

列出正在运行的容器

[root@podman ~]# podman ps
CONTAINER ID  IMAGE                                        COMMAND               CREATED        STATUS            PORTS                   NAMES
62b51b4ca194  registry.fedoraproject.org/f29/httpd:latest  /usr/bin/run-http...  8 minutes ago  Up 8 minutes ago  0.0.0.0:8080->8080/tcp  optimistic_shtern
[root@podman ~]# 

注意:如果将 -a 添加到 ps 命令中,Podman 将显示所有容器。

检查正在运行的容器
检查正在运行的容器您可以“检查”正在运行的容器,以获取有关其自身的元数据和详细信息。我们甚至可以使用 inspect 子命令来查看分配给容器的 IP 地址。由于容器在无根模式下运行,因此不会分配 IP 地址,并且该值将在检查的输出中列为“无”。

[root@podman ~]# podman inspect -l|grep -i ipaddress
            "IPAddress": "10.88.0.2",
                    "IPAddress": "10.88.0.2",
[root@podman ~]# 

注意:-l 是最新容器的便利参数。还可以使用容器的 ID 而不是 -l
测试 httpd 服务器

[root@podman ~]# curl 10.88.0.2: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">
			/*<![CDATA[*/
			body {
				background-color: #fff;
				color: #000;

web页面查看结果
通过宿主机加上映射出来的端口进行访问

查看容器的日志

[root@podman ~]# 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

查看容器的进程
您可以使用top观察容器中的 httpd pid 。

[root@podman ~]# podman top -l
USER        PID         PPID        %CPU        ELAPSED           TTY         TIME        COMMAND
default     1           0           0.000       15m48.990690757s  pts/0       0s          httpd -D FOREGROUND 
default     23          1           0.000       15m48.990838468s  pts/0       0s          /usr/bin/coreutils --coreutils-prog-shebang=cat /usr/bin/cat

检查点容器
检查点容器会停止容器,同时将容器中所有进程的状态写入磁盘。有了这个,容器可以稍后恢复并在与检查点完全相同的时间点继续运行。此功能需要在系统上安装 CRIU 3.11 或更高版本。此功能不支持为无根;因此,如果您想尝试它,您需要以 root 身份重新创建您的容器,使用相同的命令但使用 sudo。

[root@podman ~]# podman container checkpoint -l
62b51b4ca194a6d180b85588f7772a515037209834fef81551227b70cf22d128
[root@podman ~]# podman ps -a
CONTAINER ID  IMAGE                                        COMMAND               CREATED         STATUS                         PORTS                   NAMES
62b51b4ca194  registry.fedoraproject.org/f29/httpd:latest  /usr/bin/run-http...  18 minutes ago  Exited (0) About a minute ago  0.0.0.0:8080->8080/tcp  optimistic_shtern

恢复容器
仅对以前设置检查点的容器才能恢复容器。恢复的容器将继续在与检查点完全相同的时间点运行。就相当于恢复到检查点当时的状态

[root@podman ~]# podman container restore -l
62b51b4ca194a6d180b85588f7772a515037209834fef81551227b70cf22d128
[root@podman ~]# podman ps -a
CONTAINER ID  IMAGE                                        COMMAND               CREATED         STATUS             PORTS                   NAMES
62b51b4ca194  registry.fedoraproject.org/f29/httpd:latest  /usr/bin/run-http...  20 minutes ago  Up 20 minutes ago  0.0.0.0:8080->8080/tcp  optimistic_shtern

恢复后,容器将像检查点之前一样再次响应请求。

[root@podman ~]# curl 10.88.0.2: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">
			/*<![CDATA[*/

迁移容器
要将容器从一台主机实时迁移到另一台主机,容器会在迁移的源系统上设置检查点,转移到目标系统,然后在目标系统上恢复。传输检查点时,可以指定输出文件
在源系统上:

[root@podman ~]# sudo podman container checkpoint 62b51b4ca194 -e /tmp/checkpoint.tar.gz
62b51b4ca194a6d180b85588f7772a515037209834fef81551227b70cf22d128
[root@podman ~]# scp /tmp/checkpoint.tar.gz 192.168.174.168:/tmp
The authenticity of host '192.168.174.168 (192.168.174.168)' can't be established.
ECDSA key fingerprint is SHA256:sfUIHR7r4pLw+1JpJPet9brqYcJdceEQPBZhtYpej4I.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '192.168.174.168' (ECDSA) to the list of known hosts.
root@192.168.174.168's password: 
checkpoint.tar.gz                                                      100% 5313KB 124.0MB/s   00:00    

在目标系统上:

[root@podman ~]# podman rm -f 62b51b4ca194   //这里用的源系统下删除容器模拟没有容器
62b51b4ca194a6d180b85588f7772a515037209834fef81551227b70cf22d128
[root@podman ~]# podman container restore -i /tmp/checkpoint.tar.gz 
62b51b4ca194a6d180b85588f7772a515037209834fef81551227b70cf22d128

还原后,容器将像检查点之前一样再次应答请求。这一次,容器将继续在目标系统上运行。

[root@podman ~]# curl 192.168.174.168: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">
			/*<![CDATA[*/
			body {

停止容器
要停止 httpd 容器,请执行以下操作:

[root@podman ~]# podman stop --latest
62b51b4ca194a6d180b85588f7772a515037209834fef81551227b70cf22d128

您还可以使用 ps 子命令检查一个或多个容器的状态。在这种情况下,我们应该使用 -a 参数列出所有容器。

[root@podman ~]# podman ps -a
CONTAINER ID  IMAGE                                        COMMAND               CREATED        STATUS                     PORTS                   NAMES
62b51b4ca194  registry.fedoraproject.org/f29/httpd:latest  /usr/bin/run-http...  5 minutes ago  Exited (0) 28 seconds ago  0.0.0.0:8080->8080/tcp  optimistic_shtern

移除容器
删除 httpd 容器:

[root@podman ~]# podman rm --latest
62b51b4ca194a6d180b85588f7772a515037209834fef81551227b70cf22d128
[root@podman ~]# podman ps
CONTAINER ID  IMAGE       COMMAND     CREATED     STATUS      PORTS       NAMES

您可以通过运行 podman ps -a 来验证容器的删除。

使用 Podman 签署和分发容器镜像

签署容器镜像的动机是只信任专门的镜像提供者以减轻中间人 (MITM) 攻击或对容器注册表的攻击。签署图像的一种方法是使用 GNU Privacy Guard ( GPG ) 密钥。这种技术通常与任何符合 OCI 的容器注册表兼容,例如:Quay.io。值得一提的是,OpenShift 集成容器注册表开箱即用地支持这种签名机制,这使得单独的签名存储变得不必要。

从技术角度来看,我们可以利用 Podman 对镜像进行签名,然后再将其推送到远程注册表。之后,所有运行 Podman 的系统都必须配置为从远程服务器检索签名,远程服务器可以是任何简单的 Web 服务器。这意味着在图像拉取操作期间,每个未签名的图像都将被拒绝。但这是如何工作的?

首先,我们必须创建一个 GPG 密钥对或选择一个已经在本地可用的密钥对。要生成新的 GPG 密钥,只需运行gpg --full-gen-key并按照交互式对话框操作。现在我们应该能够验证密钥在本地是否存在:

[root@podman ~]# 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.
What keysize do you want? (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: runtime
Email address: runtime@redhat.com
Comment: runtime
You selected this USER-ID:
    "runtime (runtime) <runtime@redhat.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 FCF730B828483388 marked as ultimately trusted
gpg: directory '/root/.gnupg/openpgp-revocs.d' created
gpg: revocation certificate stored as '/root/.gnupg/openpgp-revocs.d/1531D8341DD83E105452399AFCF730B828483388.rev'
public and secret key created and signed.

pub   rsa2048 2022-08-16 [SC]
      1531D8341DD83E105452399AFCF730B828483388
uid                      runtime (runtime) <runtime@redhat.com>
sub   rsa2048 2022-08-16 [E]

查看生成的密钥

[root@podman ~]# gpg --list-keys runtime@redhat.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]
      1531D8341DD83E105452399AFCF730B828483388
uid           [ultimate] runtime (runtime) <runtime@redhat.com>
sub   rsa2048 2022-08-16 [E]

现在,让我们假设我们运行一个容器注册表。例如,我们可以简单地在本地机器上启动一个:

[root@podman ~]# podman run -d -p 5000:5000 docker.io/registry
Trying to pull docker.io/library/registry:latest...
WARN[0037] failed, retrying in 1s ... (1/3). Error: parsing image configuration: Get "https://kb52svac.mirror.aliyuncs.com/v2/library/registry/blobs/sha256:b8604a3fe8543c9e6afc29550de05b36cd162a97aa9b2833864ea8a5be11f3e2": read tcp 192.168.174.168:59712->116.62.81.173:443: read: connection reset by peer 
Getting image source signatures
Copying blob 79e9f2f55bf5 done  
Copying blob 3790aef225b9 done  
Copying blob 5b27040df4a2 done  
Copying blob e2ead8259a04 done  
Copying blob 0d96da54f60b done  
Copying config b8604a3fe8 done  
Writing manifest to image destination
Storing signatures
54d1ddd2ce5efceaa7f419c154455754a6b3cfe2e368db69aff025645f5f4fd0

[root@podman ~]# ss -anlt
State       Recv-Q      Send-Q           Local Address:Port           Peer Address:Port     Process      
LISTEN      0           128                    0.0.0.0:22                  0.0.0.0:*                     
LISTEN      0           128                    0.0.0.0:5000                0.0.0.0:*                     
LISTEN      0           128                       [::]:22                     [::]:*   

注册表对映像签名一无所知,它只是为容器映像提供远程存储。这意味着,如果我们要对图像进行签名,则必须注意如何分发签名。

让我们为签名实验选择一个标准映像:alpine

[root@podman ~]# 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@podman ~]# podman images alpine
REPOSITORY                TAG         IMAGE ID      CREATED       SIZE
docker.io/library/alpine  latest      c059bfaa849c  8 months ago  5.87 MB

现在,我们可以重新标记映像以将其指向本地注册表:

[root@podman ~]# podman tag alpine localhost:5000/alpine
[root@podman ~]# podman images alpine
REPOSITORY                TAG         IMAGE ID      CREATED       SIZE
docker.io/library/alpine  latest      c059bfaa849c  8 months ago  5.87 MB
localhost:5000/alpine     latest      c059bfaa849c  8 months ago  5.87 MB

Podman现在能够推送图像并在一个命令中签名。但是要让它工作,我们必须修改系统范围的注册表配置,网址为:/etc/containers/registries.d/default.yaml

[root@podman ~]# vim /etc/containers/registries.d/default.yaml 
default-docker:
  sigstore: http://localhost:8000
  sigstore-staging: file:///var/lib/containers/sigstore

我们可以看到,我们配置了两个签名存储:

  • sigstore:引用 Web 服务器进行签名读取
  • sigstore-staging:引用文件路径以进行签名写入
    现在,让我们推送并签署映像:
[root@podman ~]# GNUPGHOME=$HOME/.gnupg
[root@podman ~]# podman push --tls-verify=false --sign-by runtime@redhat.com localhost:5000/alpine
Getting image source signatures
Copying blob 8d3ac3489996 done  
Copying config c059bfaa84 done  
Writing manifest to image destination
Signing manifest
Storing signatures

如果我们现在看一下系统签名存储,那么我们看到有一个新的签名可用,这是由映像推送引起的:

[root@podman ~]# ls /var/lib/containers/sigstore
'alpine@sha256=964248be4bb8e3052c8b411271126f70c5c5015df31e014bfc41fad50edf78d8'
[root@podman ~]# 

前面编辑的默认签名存储 /etc/containers/registries.d/default.yaml引用了一个正在监听的 Web 服务器 http://localhost:8000。我们只需在本地临时签名存储中启动一个新服务器:

//下载python3,下面的命令会需要此依赖关系
[root@podman ~]# dnf -y install python36

//启动用来读取签名的web服务器
[root@podman ~]# bash -c 'cd /var/lib/containers/sigstore && python3 -m http.server'
Serving HTTP on 0.0.0.0 port 8000 (http://0.0.0.0:8000/) ...
192.168.174.1 - - [16/Aug/2022 12:17:03] "GET / HTTP/1.1" 200 -
192.168.174.1 - - [16/Aug/2022 12:17:03] code 404, message File not found
192.168.174.1 - - [16/Aug/2022 12:17:03] "GET /favicon.ico HTTP/1.1" 404 -


删除本地镜像用来进行拉取镜像验证

[root@podman ~]# podman rmi docker.io/alpine localhost:5000/alpine
Untagged: docker.io/library/alpine:latest
Untagged: localhost:5000/alpine:latest
Deleted: c059bfaa849c4d8e4aecaeb3a10c2d9b3d85f5165c66ad3a4d937758128c4d18

我们必须编写一个策略来强制签名必须是有效的。这可以通过在 中添加新规则来完成/etc/containers/policy.json。

[root@podman ~]# vim /etc/containers/policy.json 
    "transports": {
        "docker": {
            "localhost:5000":  [
                {
                    "type": "signedBy",
                    "keyType": "GPGKeys",
                    "keyPath": "/tmp/key.gpg"
                }
            ],

这个/tmp/key.gpg位置的密钥不存在,因此我们必须将GPG密钥放在那里

[root@podman ~]#  gpg --output /tmp/key.gpg --armor --export runtime@redhat.com

拉取本地私有仓库中的alpine镜像,目前也只有这一个镜像,因为我们创建这个私有仓库后只上传了这个镜像

[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 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

网站公告

今日签到

点亮在社区的每一天
去签到