7. podman -- 保存容器中修改的内容
1. 导出、导入容器
1.1 export
podman export NAME > xxx.tar
export 命令可以将 NAME 来指定容器,导出到本地文件,可以作为一个快照,
Exports container's filesystem contents as a tar archive and saves it on the local machine.
如上,
podman export 将容器导出为 /tmp/t1.tar,
file 命令能看出,导出的文件为一个 tar 包
1.2 import
podman import
import 命令可以将容器快照的本地文件, 导入为一个镜像,类似于恢复快照
Import a tarball and save it as a filesystem image
podman import 的结果是一个镜像,而不是一个容器。
也就是说:
修改过的容器导出,得到一个 tar 包;tar 包导入,得到一个镜像;镜像运行,才是修改过的容器。
接上图的例子:
如上:
(1)能看到,当前本地有两个镜像
podman import 前面步骤导出的 tar 包 /tmp/t1.tar,
导入完成后,podman images 能看到,本地多出一个镜像,
(2)运行这个新镜像,就能看到前面新创建的 1.txt
podman import --help 里面给出的 import 示例为:
podman import http://example.com/ctr.tar url-image
cat ctr.tar | podman import -
cat ctr.tar | podman -q import --message "importing the ctr.tar tarball" - image-imported
2. 更新(提交)镜像
将修改过的容器,保存为一个镜像,也就是对镜像进行更新
podman commit
Create an image from a container's changes.
2.1 修改容器内容
如上,
运行镜像 ubuntu,命名为 v1
然后再容器中进行了一些修改,(比如说,可以是修改了 httpd 的 index.html 文件等等)
退出容器
-
容器正常的 stop,start 对于已修改的内容没有影响
-
容器的 rm,对于已修改的内容也就一并消失了
2.2 将修改过的容器,保存为镜像
为了保存阶段性修改过的内容,可以对镜像进行更新
如上,
退出容器后,通过 commit 来提交容器,生成镜像
--author | -a=author
Set the author for the committed image
v1
也就是前面作了修改的容器名称,也可以使用 Image ID
xyz/unbutu:v2
生成的镜像名和 tag
提交完成后,podman images 能看到,多了一条本地记录 localhost/xyz/ubuntu v2
接下来,运行此镜像,就能看到原先做的修改依旧存在
对于 docker 格式的镜像(-f 参数),还可以有 -m 参数(message)来做一个注释
3. 挂载
3.1 挂载
运行容器的时候,
可以通过 -v 参数,在容器中,挂载一个宿主机的目录,
这样的话,当容器启停、删除的时候,
因为这个目录是容器外的内容,并不会随着容器的删除而被回收。
而容器再次运行的时候,又可以通过挂载,获取新的内容。
--volume | -v
Create a bind mount.
可以使用 /Host-Dir:/Container-Dir
的格式,
表示将宿主机的目录挂载到容器里面
如:
前面我们已经知道,
例子中的 httpd 镜像创建的 index.html 文件位于 /usr/local/apache2/htdoc/index.html
下面将会把宿主机的 /opt/ 目录挂载到 httpd 这个容器的 /usr/local/apache2/htdoc/
如上,
通过 -v /opt:/usr/local/apache2/htdoc
将宿主机的 /opt 目录挂载到容器的 htdoc 目录,
进入容器,
此时在宿主机的 /opt 目录下新建文件,
在容器的 htdoc 目录下就能同步看见 该文件。
(貌似访问 http 服务的时候,还是原来的首页,不过不管啦,目的暂时实现)
至此,
如果该容器,sotp,rm
再次 run 的时候,同样挂载 /opt 目录,就能看见所做的改动。如下:
因为启动容器的时候有挂载动作,
因此,重新 exec 进入容器的时候,即便没有 -v 选项,也能看见挂载的内容
3.2 selinux
- selinux 的相关操作需要 root 权限,普通用户同步不了安全上下文
在上面的例子中,是在宿主机里的挂载目录 /opt 编辑的 index.html
如果是在容器里面,挂载目录里面来编辑的话,
会受到 SELinux 的影响,导致失败,如:
-
方法一:宿主机 setenforce 0
-
方法二:挂载的时候添加一个挂载选项
--volume /Host-Dir:/Container-Dir[:Options]
https://blog.christophersmart.com/2021/01/31/podman-volumes-and-selinux/
If your host has SELinux enabled,
then container processes are confined to the domain:
system_u:system_r:container_t:s0
...
however the context that is required for container volumes is:
system_u:object_r:container_file_t:s0.
Fortunately, container volumes which podman creates at runtime will have the appropriate context set automatically.
也就是说,容器进程的安全上下文是 system_u:system_r:container_t:s0
那么挂载目录的安全上下文需要是 system_u:object_r:container_file_t:s0 来保持匹配
z 选项表示 podman 在挂载的时候将 SELinux 安全上下进行同步,如:
如上,创建宿主机的挂载目录 /opt/container_dir/
可以看到,其安全上下文为 user_t
podman run 的时候,挂载目录时使用了 z 选项,
连接容器,进入 htdoc/
目录,
成功在容器挂载目录里面创建文件,
并能看到文件的安全上下文为 container_file_t
,
退出容器,
可以看见挂载目录的安全上下文也相应的变为了 container_file_t
且能顺利看见容器重创建 的文件 file1.txt
但上面这种方法会有一个问题:
容器 A,容器 B,容器 C,是个容器都能访问挂载目录,可能会有安全隐患。
如果只是限定容器 A 才能访问挂载目录的话,那么就需要使用到 Z 选项,前面的链接里面有叙述,此处放出截图,不在叙述。