Podman 简介
什么是Podman?
Podman 是一个开源的容器运行时项目,可在大多数 Linux 平台上使用。Podman 提供与 Docker 非常相似的功能。正如前面提到的那样,它不需要在你的系统上运行任何守护进程,并且它也可以在没有 root 权限的情况下运行。
Podman 可以管理和运行任何符合 OCI(Open Container Initiative)规范的容器和容器镜像。Podman 提供了一个与 Docker 兼容的命令行前端来管理 Docker 镜像。
Podman 官网地址:https://podman.io/
Podman和Docker的主要区别是什么?
- dockers在实现CRI的时候,它需要一个守护进程,其次需要以root运行,因此这也带来了安全隐患。
- podman不需要守护程序,也不需要root用户运行,从逻辑架构上,比docker更加合理。
- 在docker的运行体系中,需要多个daemon才能调用到OCI的实现RunC。
- 在容器管理的链路中,Docker Engine的实现就是dockerd
- daemon,它在linux中需要以root运行,dockerd调用containerd,containerd调用containerd-shim,然后才能调用runC。顾名思义shim起的作用也就是“垫片”,避免父进程退出影响容器的运训
- podman直接调用OCI,runtime(runC),通过common作为容器进程的管理工具,但不需要dockerd这种以root身份运行的守护进程。
- 在podman体系中,有个称之为common的守护进程,其运行路径通常是/usr/libexec/podman/conmon,它是各个容器进程的父进程,每个容器各有一个,common的父则通常是1号进程。podman中的common其实相当于docker体系中的containerd-shim。
图中所体现的事情是,podman不需要守护进程,而dorker需要守护进程。在这个图的示意中,dorcker的containerd-shim与podman的common被归在Container一层。
Podman的使用与docker有什么区别?
podman的定位也是与docker兼容,因此在使用上面尽量靠近docker。在使用方面,可以分成两个方面来说,一是系统构建者的角度,二是使用者的角度。
在系统构建者方面,用podman的默认软件,与docker的区别不大,只是在进程模型、进程关系方面有所区别。如果习惯了docker几个关联进程的调试方法,在podman中则需要适应。可以通过pstree命令查看进程的树状结构。总体来看,podman比docker要简单。由于podman比docker少了一层daemon,因此重启的机制也就不同了。
在使用者方面,podman与docker的命令基本兼容,都包括容器运行时(run/start/kill/ps/inspect),本地镜像(images/rmi/build)、镜像仓库(login/pull/push)等几个方面。因此podman的命令行工具与docker类似,比如构建镜像、启停容器等。甚至可以通过alias docker=podman
可以进行替换。因此,即便使用了podman,仍然可以使用docker.io作为镜像仓库,这也是兼容性最关键的部分。
Podman 常用命令
容器
podman run 创建并启动容器
podman start #启动容器
podman ps #查看容器
podman stop #终止容器
podman restart #重启容器
podman attach #进入容器
podman exec #进入容器
podman export #导出容器
podman import #导入容器快照
podman rm #删除容器
podman logs #查看日志
镜像
podman search #检索镜像
docke pull #获取镜像
podman images #列出镜像
podman image Is #列出镜像
podman rmi #删除镜像
podman image rm #删除镜像
podman save #导出镜像
podman load #导入镜像
podmanfile #定制镜像(三个)
podman build #构建镜像
podman run #运行镜像
podmanfile #常用指令(四个)
COPY #复制文件
ADD #高级复制
CMD #容器启动命令
ENV #环境变量
EXPOSE #暴露端口
除了首字命令是podman 后面基础语法跟docker一样
安装podman
//安装podman
[root@localhost ~]# yum -y install podman
[root@localhost ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
[root@localhost ~]# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
配上加速器
vim /etc/containers/registries.conf
#unqualified-search-registries = ["registry.fedoraproject.org", "registry.access.redhat.com", "registry.centos.org", "docker.io"]
unqualified-search-registries = ["docker.io"]
[[registry]]
prefix = "docker.io"
location = "ay24c8ru.mirror.aliyuncs.com"
创建镜像容器
[root@localhost containers]# podman run -d --name web -p 8080:80 httpd
[root@localhost containers]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d92bc2ac42cd docker.io/library/httpd:latest httpd-foreground 11 seconds ago Up 10 seconds ago 0.0.0.0:8080->80/tcp web
检查正在运行的容器
您可以“检查”正在运行的容器的元数据和有关其自身的详细信息。我们甚至可以使用 inspect 子命令查看分配给容器的 IP 地址。由于容器以无根模式运行,因此未分配 IP 地址,并且该值将在检查的输出中列为“无”。
[root@localhost ~]# podman inspect -l | grep IPAddress\":
"IPAddress": "10.88.0.2",
"IPAddress": "10.88.0.2",
[root@localhost containers]# curl 10.88.0.2
<html><body><h1>It works!</h1></body></html>
注意:-l 是最新容器的便利参数。您还可以使用容器的 ID 代替 -l
查看一个运行中容器的日志
[root@localhost ~]# podman logs -l
10.88.0.1 - - [09/May/2022:06:30:11 +0000] "GET / HTTP/1.1" 200 45
192.168.80.1 - - [09/May/2022:06:31:18 +0000] "GET / HTTP/1.1" 200 45
192.168.80.1 - - [09/May/2022:06:31:18 +0000] "GET /favicon.ico HTTP/1.1" 404 196
192.168.80.1 - - [09/May/2022:06:32:10 +0000] "-" 408 -
192.168.80.1 - - [09/May/2022:06:35:56 +0000] "GET / HTTP/1.1" 304 -
192.168.80.1 - - [09/May/2022:06:36:48 +0000] "-" 408 -
//-l看最近的
删除容器
[root@localhost ~]# podman rm -f -l
d92bc2ac42cdb59528e6dd406d9c7036edbf90f05c6d8c37f7ffd6e85522d43c
[root@localhost ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
//-l删除最近的
查看一个运行容器中的进程资源使用情况
可以使用top观察容器中的 nginx pid
语法:
[root@localhost ~]# podman run -d httpd
10906a9bc0cbb97fac29dc428f7a3348f7cc88a528cbda8f041807b3583c4d22
[root@localhost ~]# podman top -l
USER PID PPID %CPU ELAPSED TTY TIME COMMAND
root 1 0 0.000 18.884993458s ? 0s httpd -DFOREGROUND
www-data 7 1 0.000 18.885149751s ? 0s httpd -DFOREGROUND
www-data 8 1 0.000 18.885214332s ? 0s httpd -DFOREGROUND
www-data 9 1 0.000 18.885253876s ? 0s httpd -DFOREGROUND
//没有名称就加上-l
停止一个运行中的容器
[root@localhost ~]# podman stop --latest
10906a9bc0cbb97fac29dc428f7a3348f7cc88a528cbda8f041807b3583c4d22
[root@localhost ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
上传镜像
[root@localhost ~]# mkdir test
[root@localhost ~]# cd test/
[root@localhost test]# vim Podmanfile
[root@localhost test]# podman build -f Podmanfile -t test:v0.1 .
[root@localhost test]# podman run -it test:v0.1 /bin/sh
/ # echo $a
10
//如果指定名称的话加上-f
[root@localhost ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/test v0.1 93401fffb1a9 3 minutes ago 1.46 MB
docker.io/library/busybox latest beae173ccac6 4 months ago 1.46 MB
docker.io/library/httpd latest dabbfbe0c57b 4 months ago 148 MB
//前面是localhost必须改名上传镜像
[root@localhost ~]# podman tag localhost/test:v0.1 docker.io/mingzi540/busybox:xiaoxin
[root@localhost ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/test v0.1 93401fffb1a9 6 minutes ago 1.46 MB
docker.io/mingzi540/busybox xiaoxin 93401fffb1a9 6 minutes ago 1.46 MB
docker.io/library/busybox latest beae173ccac6 4 months ago 1.46 MB
docker.io/library/httpd latest dabbfbe0c57b 4 months ago 148 MB
[root@localhost ~]# podman login docker.io
Username: mingzi540
Password:
Login Succeeded!
//登录的时候要加上docker.io选择docker官方仓库
[root@localhost ~]# podman push docker.io/mingzi540/busybox:xiaoxin
Getting image source signatures
Copying blob 01fd6df81c8e done
Copying config 93401fffb1 done
Writing manifest to image destination
Storing signatures
总而言之,Podman 使查找、运行、构建和共享容器变得容易。
配置别名
如果习惯了使用 Docker 命令,可以直接给 Podman 配置一个别名来实现无缝转移。你只需要在 .bashrc 下加入以下行内容即可
[root@localhost ~]# alias docker="podman"
[root@localhost ~]# docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@localhost ~]# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
用户操作
在允许没有root特权的用户运行Podman之前,管理员必须安装或构建Podman并完成以下配置。
cgroup V2Linux内核功能允许用户限制普通用户容器可以使用的资源,如果使用cgroupV2启用了运行Podman的Linux发行版,则可能需要更改默认的OCI运行时。某些较旧的版本runc不适用于cgroupV2,必须切换到备用OCI运行时crun。
[root@localhost ~]# yum -y install crun //centos8系统自带
[root@localhost ~]# cd /usr/share/containers/
[root@localhost containers]# ls
containers.conf mounts.conf seccomp.json selinux
[root@localhost containers]# vim containers.conf
runtime = "crun"
#runtime = "runc"
//取消注释并将runc改为crun
[root@localhost ~]# podman inspect -l|grep -i runtime
"OCIRuntime": "crun",
"--runtime",
"Runtime": "oci",
"CpuRealtimeRuntime": 0,
//已经生效
安装slirp4netns和fuse-overlayfs
在普通用户环境中使用Podman时,建议使用fuse-overlayfs而不是VFS文件系统,至少需要版本0.7.6。现在新版本默认就是了。
[root@localhost ~]# yum -y install slirp4netns
[root@localhost ~]# yum -y install fuse-overlayfs
[root@localhost ~]# vi /etc/containers/storage.conf
77 mount_program = "/usr/bin/fuse-overlayfs" //取消注释
/etc/subuid和/etc/subgid配置
Podman要求运行它的用户在/etc/subuid
和/etc/subgid
文件中列出一系列UID,shadow-utils或newuid包提供这些文件
[root@localhost ~]# yum -y install shadow-utils
可以在/etc/subuid和/etc/subgid查看,每个用户的值必须唯一且没有任何重叠。
[root@localhost ~]# useradd xiaoxin
[root@localhost ~]# useradd xiaoying
[root@localhost ~]# cat /etc/subuid
xiaoxin:100000:65536
xiaoying:165536:65536
// 启动非特权ping
[root@localhost ~]# vim /etc/sysctl.conf
net.ipv4.ping_group_range=0 200000
[root@localhost ~]# sysctl -p
net.ipv4.ping_group_range = 0 200000
//重启生效
这个文件的格式是 USERNAME:UID:RANGE
- 中/etc/passwd或输出中列出的用户名getpwent。
- 为用户分配的初始 UID。
- 为用户分配的 UID 范围的大小。
该usermod程序可用于为用户分配 UID 和 GID,而不是直接更新文件。
[root@localhost ~]# usermod --add-subuids 200000-201000 --add-subgids 200000-201000 hh
grep hh /etc/subuid /etc/subgid
/etc/subuid:hh:200000:1001
/etc/subgid:hh:200000:1001
用户配置文件
三个主要的配置文件是container.conf、storage.conf
和registries.conf
。用户可以根据需要修改这些文件。
- container.conf
// 用户配置文件
[root@localhost ~]# cat /usr/share/containers/containers.conf
[root@localhost ~]# cat /etc/containers/containers.conf
[root@localhost ~]# cat ~/.config/containers/containers.conf //优先级最高
如果它们以该顺序存在。每个文件都可以覆盖特定字段的前一个文件。
- 配置storage.conf文件
1./etc/containers/storage.conf
2.$HOME/.config/containers/storage.conf
在普通用户中/etc/containers/storage.conf的一些字段将被忽略
[root@localhost ~]# vi /etc/containers/storage.conf
[storage]
# Default Storage Driver, Must be set for proper operation.
driver = "overlay" #此处改为overlay
.......
mount_program = "/usr/bin/fuse-overlayfs" #取消注释
[root@localhost ~]# sysctl user.max_user_namespaces=15000 #如果版本为8以下,则需要做以下操作:
[root@localhost containers]# sysctl -p
net.ipv4.ping_group_range = 0 200000
user.max_user_namespaces = 15000
在普通用户中这些字段默认
graphroot="$HOME/.local/share/containers/storage"
runroot="$XDG_RUNTIME_DIR/containers"
- registries.conf
配置按此顺序读入,这些文件不是默认创建的,可以从/usr/share/containers或复制文件/etc/containers并进行修改。
1./etc/containers/registries.conf
2./etc/containers/registries.d/*
3.HOME/.config/containers/registries.conf
授权
文件
此文件里面写了docker账号的密码,以加密方式显示
此文件里面写了docker账号的密码,以加密方式显示
[root@localhost ~]# podman login
Username: 1314444
Password:
Login Succeeded!
[root@localhost ~]# cat /run/user/0/containers/auth.json
{
"auths": {
"registry.fedoraproject.org": {
"auth": "MTMxNDQ0NDpIMjAxNy0xOA=="
}
}
}
普通用户是无法看见root用户的镜像的
[xiaoying@localhost ~]$ podman pull busybox
Resolved "busybox" as an alias (/etc/containers/registries.conf.d/000-shortnames.conf)
Trying to pull docker.io/library/busybox:latest...
Getting image source signatures
Copying blob 5cc84ad355aa done
Copying config beae173cca done
Writing manifest to image destination
Storing signatures
beae173ccac6ad749f76713cf4440fe3d21d1043fe616dfbe30775815d1d0f6a
[xiaoying@localhost ~]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/busybox latest beae173ccac6 4 months ago 1.46 MB
[xiaoying@localhost ~]$ podman run -it --rm busybox /bin/sh
/ #
//xiaoying用户创建镜像容器
[root@localhost ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3014a85ad421 docker.io/library/httpd:latest httpd-foreground 32 minutes ago Up 32 minutes ago great_mahavira
//切换到root用户查不出xioaying用户创建的容器
卷
- 容器与root用户一起运行,则root容器中的用户实际上就是主机上的用户。
- UID GID是在/etc/subuid和/etc/subgid等中用户映射中指定的第一个UID GID。
- 如果普通用户的身份从主机目录挂载到容器中,并在该目录中以根用户身份创建文件,则会看到它实际上是你的用户在主机上拥有的。
使用卷
[xiaoying@localhost ~]$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[xiaoying@localhost ~]$ ls
[xiaoying@localhost ~]$ mkdir data
[xiaoying@localhost ~]$ ls
data
[xiaoying@localhost ~]$ ll
total 0
drwxrwxr-x. 2 xiaoying xiaoying 6 May 9 17:55 data
[xiaoying@localhost ~]$ pwd
/home/xiaoying
[xiaoying@localhost ~]$ podman run -it --rm -v "$(pwd)"/data:/data:Z busybox /bin/sh
/ # ls
bin data dev etc home proc root run sys tmp usr var
/ # cd data/
/data # ls
/data #
//加上-Z就可以有权限查看
[xiaoying@localhost ~]$ echo 'hello world' > data/abc
//容器外创建文件内容
/data # cat abc
hello world
//去容器里查看
普通用户可以映射>= 1024的端口
[xiaoying@localhost ~]$ podman run -d --name web1 -p 80:80 httpd
eaca84d0e2cc21634d5b28e81f5fe25efbbeeb89c74e1ed05fd0645a8d1c8236
[xiaoying@localhost ~]$ podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
eaca84d0e2cc docker.io/library/httpd:latest httpd-foreground 2 minutes ago Up 2 minutes ago 0.0.0.0:80->80/tcp web1
配置echo ‘net.ipv4.ip_unprivileged_port_start=80’ >> /etc/sysctl.conf
后可以映射大于等于80的端口
[xiaoxin@localhost ~]$ podman run -d -p 1024:80 httpd
[root@localhost ~]# echo 'net.ipv4.ip_unprivileged_port_start=80' >> /etc/sysctl.conf
[root@localhost ~]# sysctl -p
net.ipv4.ping_group_range = 0 200000
user.max_user_namespaces = 15000
net.ipv4.ip_unprivileged_port_start = 80
[xiaoxin@localhost ~]$ podman run -d -p 80:80 httpd
4c327d55182ef362547f7baa87449822d98a95013442aa9e107c577250e8e460
[xiaoxin@localhost ~]$ 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 *:1024 *:*
LISTEN 0 128 *:80 *:*
LISTEN 0 128 [::]:22 [::]:*