前面一直在考证书,导致一直没有空闲更新帖子哈,各位老爷们,抱歉!
一、podman的自报家门
Podman是一种无守护进程、开源的 Linux 原生工具,旨在使用开放容器倡议 ( OCI ) 容器和 容器映像轻松查找、运行、构建、共享和部署应用程序。Podman 提供了任何使用过 Docker 容器引擎的人都熟悉的命令行界面 (CLI) 。大多数用户可以简单地将 Docker 别名为 Podman(别名 docker=podman),没有任何问题。与其他常见的 容器引擎(Docker、CRI-O、containerd)类似,Podman 依赖于符合 OCI 的 容器运行时(runc、crun、runv 等)与操作系统交互并创建正在运行的容器。这使得 Podman 创建的运行容器与任何其他常见容器引擎创建的容器几乎没有区别。
Podman 控制下的容器可以由 root 或非特权用户运行。Podman 使用 libpod库管理整个容器生态系统,包括 pod、容器、容器镜像和容器卷。Podman 专注于帮助您维护和修改 OCI 容器映像的所有命令和功能,例如拉取和标记。它允许您在生产环境中创建、运行和维护这些容器和容器映像。
有一个 RESTFul API 来管理容器。我们还有一个可以与 RESTFul 服务交互的远程 Podman 客户端。我们目前支持 Linux、Mac 和 Windows 上的客户端。RESTFul 服务仅在 Linux 上受支持。
如果您完全不熟悉容器,我们建议您查看 简介。对于高级用户或来自 Docker 的用户,请查看我们的 教程。对于高级用户和贡献者,您可以通过查看我们的 命令页面来获取有关 Podman CLI 的非常详细的信息。最后,对于寻求如何与 Podman API 交互的开发人员,请参阅我们的 API 文档 参考。
二、podman工作机制
Podman 原来是 CRI-O 项目的一部分,后来被分离成一个单独的项目叫 libpod。Podman 的使用体验和 Docker类似,不同的是 Podman 没有 daemon。以前使用 Docker CLI 的时候,Docker CLI 会通过 gRPC API去跟 Docker Engine 说「我要启动一个容器」,然后 Docker Engine 才会通过 OCI Containerruntime(默认是 runc)来启动一个容器。这就意味着容器的进程不可能是 Docker CLI 的子进程,而是 DockerEngine 的子进程。
Podman 比较简单粗暴,它不使用 Daemon,而是直接通过 OCI runtime(默认也是 runc)来启动容器,所以容器的进程是podman 的子进程,这比较像 Linux 的 fork/exec 模型,而 Docker 采用的是 C/S(客户端/服务器)模型。
和C/S 模型相比,fork/exec 模型有很多优势,比如:
- 系统管理员可以知道某个容器进程到底是谁启动的。
- 如果利用 cgroup 对 podman 做一些限制,那么所有创建的容器都会被限制。
- SD_NOTIFY : 如果将 podman 命令放入 systemd 单元文件中,容器进程可以通过 podman 返回通知,表明服务已准备好接收任务。
- socket 激活 : 可以将连接的 socket 从 systemd 传递到 podman,并传递到容器进程以便使用它们。
三、docker和podman的区别
可能光看文字有那么点枯燥难以理解,下面上一张图帮助我们理解podman与docker的区别;
依照图中podman不需要守护进程,而dorker需要守护进程。在这个图的示意中,dorcker的containerd-shim与podman的common被归在Container一层。
总结:
-
dockers在实现CRI,它需要一个守护进程,其次需要以root运行,因此这也带来了安全隐患;
-
podman不需要守护程序,也不需要root用户运行,从逻辑架构上,比docker更加合理;
-
docker的运行体系中,需要多个daemon才能调用到OCI的实现RunC;
-
容器管理的链路中,Docker Engine的实现就是dockerd;
-
demon,它在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;
四 实例演示
server: CentOS Linux 8 (Core)
Architecutre: x86-64
1. 安装部署podman (Centos 8)
[root@yb ~]# yum module install -y container-tool
container-tools 模块包括安装多个工具的软件包,本次学习中使用的工具是podman和skopeo。
1-2 安装podman(Centos 7)
[root@localhost ~]# sudo subscription-manager repos --enable=rhel-7-server-extras-rpms ##订阅并启用 Extras
[root@localhost ~]# sudo yum install -y podman ##安装podman工具
2. 选择容器镜像和注册表
-
容器注册表是用于存储和检索容器镜像的存储库。开发人员将容器镜像上传或推送到容器注册表中,从注册表中将这些容器镜像下载或提取到本地系统,可用于运行容器。
-
可使用包含第三方镜像的公共注册表,也可以使用自己私有的注册表。容器镜像来源很重要,和任何其他软件包一样,您必须知道是否可以信任容器镜像中的代码。不同的注册表对于是否及如何提供评估和测试提交给它们的容器镜像有不同的策略。
-
官方通过两个主容器注册表分发认证容器镜像,而使用红帽登录凭据可访问这两个注册表。
-- registry.redhat.io:适用于基于官方红帽产品的容器
-- registry.connect.redhat.com: 适用于基于第三方产品的容器
3.相关配置文件
[root@yb ~]# cd /etc/containers/ ##进入容器镜像配置目录
- registries.conf 是重要的镜像选择的配置文件,在这里我们可以使用自定义的镜像来加速镜像拉取
2. 这里我们做出重要修改来加速容器提取
[root@yb containers]# cp registries.conf registries.bak ##备份源文件
[root@yb containers]# vim registries.conf ## 编辑配置
unqualified-search-registries = [ "docker.io"]
[[registry]]
location = "f0pqsi2y.mirror.aliyuncs.com" ## 配置本地阿里源容器地址
insecure = false ## 如果为真,未加密的 HTTP 以及与不受信任的 TLS 连接
blocked = false ## 如果为 true,则禁止拉取具有匹配名称的映像
- 查看配置是否生效
[root@yb ~]# podman info | grep f0pqsi2y.mirror.aliyuncs.com
f0pqsi2y.mirror.aliyuncs.com:
Location: f0pqsi2y.mirror.aliyuncs.com
Prefix: f0pqsi2y.mirror.aliyuncs.com
- 容器命名约定 registry_name/user_name/image_name:tag
- registry_name是存储镜像的注册表的名称。它通常是注册表的完全限定域名;
- User_name表示镜像所属的用户或组织;
- image_name: 在命名空间中必须唯一;
- tag标识镜像版本。如果镜像名称不包含镜像标签,则假定为latest
五、podman常用操作
1、podman --help
[root@103 ~]# podman --help
Manage pods, containers and images
管理豆荚,容器和图像
Usage:
用法:
podman [options] [command]
podman[选项](命令)
Available Commands:
可用命令:
attach Attach to a running container
附加到运行容器
auto-update Auto update containers according to their auto-update policy
Auto -update根据容器的自动更新策略自动更新容器
build Build an image using instructions from Containerfiles
使用容器文件中的指令构建映像
commit Create new image based on the changed container
commit根据更改的容器创建新的映像
container Manage containers
容器管理的容器
cp Copy files/folders between a container and the local filesystem
cp在容器和本地文件系统之间复制文件/文件夹
create Create but do not start a container
create创建但不启动容器
diff Display the changes to the object's file system
diff显示对对象文件系统的更改
events Show podman events
events显示podman事件
exec Run a process in a running container
在运行的容器中运行进程
export Export container's filesystem contents as a tar archive
export将容器的文件系统内容导出为tar存档文件
generate Generate structured data based on containers, pods or volumes.
生成基于容器、荚或卷的结构化数据。
healthcheck Manage health checks on containers
healthcheck管理容器的运行状况检查
help Help about any command
help表示对任何命令的帮助
history Show history of a specified image
history显示指定图像的历史记录
image Manage images
图像处理图像
images List images in local storage
images列出本地存储中的图像
import Import a tarball to create a filesystem image
import通过导入tarball来创建文件系统映像
info Display podman system information
info显示podman系统信息
init Initialize one or more containers
初始化化一个或多个容器
inspect Display the configuration of object denoted by ID
inspect显示ID表示的对象配置信息
kill Kill one or more running containers with a specific signal
kill使用特定信号杀死一个或多个正在运行的容器
load Load image(s) from a tar archive
load从tar存档文件中加载图像
login Login to a container registry
login登录到容器注册表
logout Logout of a container registry
logout容器注册表的注销
logs Fetch the logs of one or more containers
logs获取一个或多个容器的日志
machine Manage a virtual machine
machine管理虚拟机
manifest Manipulate manifest lists and image indexes
操作清单列表和图像索引
mount Mount a working container's root filesystem
挂载一个工作容器的根文件系统
network Manage networks
网络管理网络
pause Pause all the processes in one or more containers
暂停一个或多个容器中的所有进程
play Play containers, pods or volumes from a structured file.
从一个结构化文件中播放容器、豆荚或卷。
pod Manage pods
豆荚管理豆荚
port List port mappings or a specific mapping for the container
port列出容器的端口映射或特定映射
ps List containers
ps 列表容器
pull Pull an image from a registry
pull从注册表中提取一个图像
push Push an image to a specified destination
push将映像推送到指定的目的地
rename Rename an existing container
rename重命名现有容器
restart Restart one or more containers
restart重启一个或多个容器
rm Remove one or more containers
删除一个或多个容器
rmi Removes one or more images from local storage
rmi从本地存储中删除一个或多个映像
run Run a command in a new container
在新容器中运行命令
save Save image(s) to an archive
save将图像保存到存档中
search Search registry for image
search搜索图像注册表
secret Manage secrets
保密管理的秘密
start Start one or more containers
start启动一个或多个容器
stats Display a live stream of container resource usage statistics
stats显示实时的容器资源使用统计信息流
stop Stop one or more containers
stop停止一个或多个容器
system Manage podman
系统管理podman
tag Add an additional name to a local image
tag为本地图像添加额外的名称
top Display the running processes of a container
top显示容器的运行进程
unmount Unmounts working container's root filesystem
卸载工作容器的根文件系统
unpause Unpause the processes in one or more containers
unpause取消一个或多个容器中的进程
unshare Run a command in a modified user namespace
unshare在修改后的用户命名空间中执行命令
untag Remove a name from a local image
untag从本地映像中删除一个名称
version Display the Podman Version Information
version显示Podman版本信息
volume Manage volumes
卷管理卷
wait Block on one or more containers
wait一个或多个容器的Bloc
2、查看podman版本号
[root@yb ~]# podman --version
podman version 3.3.1
这里有个比较重要的点,我提一下(centos的podman版本1.6.4 不支持--new参数),如果是这个版本或者以下,可能导致无根容器开机自启动失败!
3、podman info显示整个系统的信息
[root@yb ~]# podman info
host:
arch: amd64
buildahVersion: 1.22.3
cgroupControllers:
- cpuset
- cpu
- cpuacct
- blkio
- memory
- devices
- freezer
- net_cls
- perf_event
- net_prio
- hugetlb
- pids
- rdma
cgroupManager: systemd
cgroupVersion: v1
conmon:
package: conmon-2.0.29-1.module_el8.5.0+890+6b136101.x86_64
path: /usr/bin/conmon
version: 'conmon version 2.0.29, commit: 84384406047fae626269133e1951c4b92eed7603'
cpus: 1
distribution:
distribution: '"centos"'
version: "8"
eventLogger: file
hostname: yb
idMappings:
gidmap: null
uidmap: null
kernel: 4.18.0-193.28.1.el8_2.x86_64
linkmode: dynamic
memFree: 128077824
memTotal: 890982400
ociRuntime:
name: runc
package: runc-1.0.2-1.module_el8.5.0+911+f19012f9.x86_64
path: /usr/bin/runc
version: |-
runc version 1.0.2
spec: 1.0.2-dev
go: go1.16.7
libseccomp: 2.4.1
os: linux
remoteSocket:
path: /run/podman/podman.sock
security:
apparmorEnabled: false
capabilities: CAP_NET_RAW,CAP_CHOWN,CAP_DAC_OVERRIDE,CAP_FOWNER,CAP_FSETID,CAP_KILL,CAP_NET_BIND_SERVICE,CAP_SETFCAP,CAP_SETGID,CAP_SETPCAP,CAP_SE
TUID,CAP_SYS_CHROOT rootless: false
seccompEnabled: true
seccompProfilePath: /usr/share/containers/seccomp.json
selinuxEnabled: false
serviceIsRemote: false
slirp4netns:
executable: /usr/bin/slirp4netns
package: slirp4netns-1.1.8-1.module_el8.5.0+890+6b136101.x86_64
version: |-
slirp4netns version 1.1.8
commit: d361001f495417b880f20329121e3aa431a8f90f
libslirp: 4.4.0
SLIRP_CONFIG_VERSION_MAX: 3
libseccomp: 2.4.1
swapFree: 0
swapTotal: 0
uptime: 100h 51m 2.99s (Approximately 4.17 days)
registries:
f0pqsi2y.mirror.aliyuncs.com:
Blocked: false
Insecure: false
Location: f0pqsi2y.mirror.aliyuncs.com
MirrorByDigestOnly: false
Mirrors: null
Prefix: f0pqsi2y.mirror.aliyuncs.com
search:
- docker.io
store:
configFile: /etc/containers/storage.conf
containerStore:
number: 0
paused: 0
running: 0
stopped: 0
graphDriverName: overlay
graphOptions:
overlay.mountopt: nodev,metacopy=on
graphRoot: /var/lib/containers/storage
graphStatus:
Backing Filesystem: xfs
Native Overlay Diff: "false"
Supports d_type: "true"
Using metacopy: "true"
imageStore:
number: 0
runRoot: /run/containers/storage
volumePath: /var/lib/containers/storage/volumes
version:
APIVersion: 3.3.1
Built: 1636493036
BuiltTime: Wed Nov 10 05:23:56 2021
GitCommit: ""
GoVersion: go1.16.7
OsArch: linux/amd64
Version: 3.3.1
4、查找镜像(举例apache镜像)
4-1:模糊查询
4-2:精准查询
5、拉取镜像:
[root@yb ~]# podman pull docker.io/library/httpd
6、运行一个容器
1、查看下载好的镜像
[root@yb ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/httpd latest 28505717e3ae 5 days ago 150 MB
2、运行容器
[root@yb ~]# podman run -tid --name myweb -p 80:80 28505717e3ae
[root@yb ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES0b762f3d7238 docker.io/library/httpd:latest httpd-foreground 5 seconds ago Up 5 seconds ago 0.0.0.0:80-
>80/tcp myweb
3、测试一下
4、进入容器修改内容
[root@yb ~]# podman exec -it myweb /bin/bash
# root@0b762f3d7238:/usr/local/apache2# ls
bin build cgi-bin conf error htdocs icons include logs modules
# root@0b762f3d7238:/usr/local/apache2# cd htdocs/
# root@0b762f3d7238:/usr/local/apache2/htdocs# ls
index.html
# root@0b762f3d7238:/usr/local/apache2/htdocs# echo "hello world" > index.html
# root@0b762f3d7238:/usr/local/apache2/htdocs# cat index.html
hello world
[root@yb ~]# curl 10.60.98.125
hello world
5、podman inspectl 查看容器详细信息
[root@yb ~]# podman inspect -l
部分省略..........
6、查看容器日志
[root@yb ~]# podman logs -l
7、查看容器状态(这个经常使用到,建议记住)
[root@yb ~]# podman top -l
7、将容器保存为文件(比较重要)
- docker export 【容器名称】 [options] 【文件名称】
OPTIONS说明:
-o表示输出的文件,这里指定了输出的路径,如果没有指定路径,则默认生成到当前文件夹。
[root@yb ~]# podman export -o myweb.tar.gz myweb
[root@yb ~]# ls
myweb.tar.gz
或者
[root@yb ~]# podman export myweb > myweb.tar.gz
提示:此刻的容器正在运行中
- 从tar包导入内容为podman镜像
docker import [OPTIONS] file|URL|- [REPOSITORY[:TAG]]
OPTIONS说明:
-c :应用docker 指令创建镜像;
-m :提交时的说明文字
[root@yb ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/httpd latest 28505717e3ae 5 days ago 150 MB
[root@yb ~]# ls
myweb.tar.gz
[root@yb ~]# podman import myweb.tar.gz apache-yb:v1 -m "this is web"
Getting image source signatures
Copying blob 776919d514f7 done
Copying config 992fa5f7de done
Writing manifest to image destination
Storing signatures
sha256:992fa5f7de42339d98beb23a004575d46f334226642544d010b2443d333990f5
[root@yb ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/apache-yb v1 992fa5f7de42 9 minutes ago 147 MB
docker.io/library/httpd latest 28505717e3ae 5 days ago 150 MB
8. 将容器打包成镜像
可以使用podman commit命令来完成,podman commit可以从容器创建一个新的镜像
语法格式 docker commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
[root@yb ~]# podman commit -a "xbjuejin" 0b762f3d7238 apache.io/centos:v2
说明:此处命令和git和svn的命令有些类似
commit 是提交的意思,类似告诉svn服务器我要生成一个新的版本。
-m 添加注释
-a 作者。
108a85b1ed99 容器环境id:就是你每次输入命令行@后面的字符,例如:root@108a85b1ed99:/#
daocloud.io/ubuntu:v2 镜像名称:hub的名称/镜像名称:tag
-p,–pause=true 提交时暂停容器运行
9、将镜像打包成文件
docker save -o <保存路径> <镜像名称:标签>
[root@yb ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
apache.io/centos v2 d42716ed65a3 8 minutes ago 150 MB
localhost/apache-yb v1 992fa5f7de42 55 minutes ago 147 MB
docker.io/library/httpd latest 28505717e3ae 5 days ago 150 MB
[root@yb ~]# podman save -o ./images.tar.gz docker.io/library/httpd
Getting image source signatures
Copying blob 8553b91047da done
Copying blob 1f1fd2176485 done
Copying blob ce0966b9747d done
Copying blob dd2c46072168 done
Copying blob bcd6790c3ff4 done
Copying config 28505717e3 done
Writing manifest to image destination
Storing signatures
[root@yb ~]# ls
images.tar.gz myweb.tar.gz
10、将文件导入
命令解释:
方式一:podman load --input uu.tar(也可以使用podman load -i uu.tar或者 podman load < uu.tar);
方式二:docker load < uu.tar
[root@yb ~]# ls
images.tar.gz myweb.tar.gz
[root@yb ~]# clan
.bash_history .bash_profile .cshrc myweb.tar.gz .ssh/ .viminfo
.bash_logout .bashrc images.tar.gz .pip/ .tcshrc
[root@yb ~]# podman load --input images.tar.gz
Getting image source signatures
Copying blob 8553b91047da skipped: already exists
Copying blob 1f1fd2176485 skipped: already exists
Copying blob ce0966b9747d skipped: already exists
Copying blob dd2c46072168 skipped: already exists
Copying blob bcd6790c3ff4 [--------------------------------------] 0.0b / 0.0b
Copying config 28505717e3 done
Writing manifest to image destination
Storing signatures
Loaded image(s): docker.io/library/httpd:latest
11、看到容器、镜像导入,导出,文件什么的,可能有些同学已经开始口吐芬芳了,这里小饼给大家总结一下
容器导入导出与镜像导入导出区别 export/import 操作对象:容器 导出对象:tar文件 导入对象:镜像 镜像层数:一层 save/load 操作对象:镜像 导出对象:tar文件 导入对象:镜像 镜像层数:多层 说明: 你需要把 A 机器上的 甲 容器迁移到 B 机器, 且 甲 容器中有重要的数据需要随之一起迁移的, 就可以使用 export 和 import 参数来导入和导出
【导入的镜像层数】 最大的区别就在这里, 通过export 和 import导出的容器形成镜像时, 该镜像只有一层。通过save 和 load 导出的镜像保留了原镜像所有的层次结构, 导出时原镜像有几层, 导入的时候就还是有几层 想导出容器, 但是还想保留层次结构怎么办?
导出容器, 很快就想到唯一一个可以导出容器的工具 export,但是又想保留底层镜像的层次结构, 那么 export 就不符合需求了。想想导出带层次结构的工具就只有镜像导出工具 save 了, 但是容器在镜像层之上还有一层新的数据怎么一起导出去呢?
这个时候就需要引入一个新的参数 commit, 用来保存容器现有的状态为一个新的镜像。 比如在 A 机器上运行的甲容器是基于甲方乙方这个镜像跑起来的, 那么我就可以通过 commit 参数, 将 甲 容器的所有内容保存为一个新的镜像, 名字叫 私人订制 (内含一梗哦) 最后我再通过镜像导出工具 save 就可以完整的将 私人订制镜像(也就是 甲容器 )导出为一个 tar 包了 而且包含了 X+1 层镜像, X 层是原镜像 甲方乙方的所有镜像层数, 是容器甲多的那一层可写层的镜像