RedHat专属虚拟化工具-podman-第二季
哈喽,我是烧饼,如约而至的第二季!
一、容器持久化存储
容器最方便的是可以秒开秒关,但是有一定的弊端就是我们容器重启后原来产生的文件会随着容器的结束而结束!
这里再回忆一下上篇常用的podman命令何容器命令
1. podman search ##检索镜像
2. podman pull ##获取镜像
3. podman images ##列出镜像
4. podman rmi ##删除镜像
5. podman image rm ##删除镜像
6. podman save ##导出镜像
7. podman load ##导入镜像
8. podmanfile ##定制镜像(三个)
9. podman build ##构建镜像
10.podman run ##运行镜像
11.podmanfile ##常用指令(四个)
COPY ##复制文件
ADD ##高级复制
CMD ##容器启动命令
ENV ##环境变量
EXPOSE ##暴露端口
12.podman run ##创建并启动容器
13.podman start ##启动容器
14.podman ps ##查看容器
15.podman stop ##终止容器
16.podman restart ##重启容器
17.podman attach ##进入容器
18.podman exec ##进入容器
19.podman export ##导出容器
20.podman import ##导入容器快照
21.podman rm ##删除容器
22.podman logs ##查看日志
我们往往希望数据可以保留下来!
1-了解podman怎么实现数据存储之volumes
podman容器对于宿主机器来说只是一个运行在Linux上的应用,因此它的数据存储还是会依赖宿主机器,podman是通过挂载宿主机文件系统或内存的方式来实现数据存储的,挂载方式有三种:volume、bind mount和tmpfs。
- volumes - 在宿主的文件系统上的podman工作路径下创建一个文件夹(
/var/lib/podman/volumes)来存储数据,其他非podman进程是不能修改该路径下的文件,完全由podman来管理。 - bind mounts - 可以存储在宿主机器任何一个地方,但是会依赖宿主机器的目录结构,不能通过podman CLI 去直接管理,并且非podman进程和podman进程都可以修改该路径下的文件。
- tmpfs - 无论是在podman主机上还是在容器内,tmpfs挂载都不会持久保存在磁盘上,它会将信息存储在宿主机器内存里。 容器在其生存期内可以使用它来存储非持久状态或敏感信息。 例如,在内部,swarm services 使用tmpfs挂载将机密挂载到服务的容器中 或者 我们一些不需要持久化数据的开发测试环境,可以使用tmpfs。
1-2 volumes初体验
Volumes 是Docker推荐的挂载方式,与把数据存储在容器的可写层相比,使用Volume可以避免增加容器的容量大小,还可以使存储的数据与容器的生命周期独立。
- 与bind mounts相比,volumes更易于备份或迁移。
- 您可以使用podman CLI命令或podman API管理Volumes。
- volumes在Linux和Windows容器上均可工作。
- 可以在多个容器之间更安全地共享volumes。
- volumes驱动程序使您可以将volumes存储在远程主机或云提供程序上,以加密volumes内容或添加其他功能。
1-3 Volumes实战
通过-v方式 1.利用我们前面章节学习的image,下载一个mysql镜像创建一个容器,命名为
mysql01
[root@yb ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
apache.io/centos v2 d42716ed65a3 47 hours ago 150 MB
localhost/apache-yb v1 992fa5f7de42 2 days ago 147 MB
docker.io/library/httpd latest 28505717e3ae 7 days ago 150 MB
docker.io/library/mysql latest 8189e588b0e8 3 weeks ago 579 MB
[root@yb ~]# podman run -tid --name mysql01 -e MYSQL_ROOT_PASSWORD=evan123 docker.io/library/mysql
518e79718eb67830a15311e62babc63e6aa53c5381fddd06b380f6f75ff59118
[root@yb ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES0b762f3d7238 docker.io/library/httpd:latest httpd-foreground 2 days ago Up 47 hours ago 0.0.0.0:80-
>80/tcp myweb518e79718eb6 docker.io/library/mysql:latest mysqld 8 seconds ago Up 8 seconds ago
mysql01
1-4 我们可以看看容器到底有没有自动帮我们创建一个volumes
[root@yb ~]# podman volume ls
DRIVER VOLUME NAME
local 4c436b20a6106328fbcb526ac1e37a85758f953007f799939376473a6aeb2c34
通过上面的输出结果可以看到,podman默认帮我创建了一个volume,并且随机起了一个看不懂的名字。
1-5.通过podman inspect查看volume详细信息
[root@yb ~]# podman inspect 4c436b20a6106328fbcb526ac1e37a85758f953007f799939376473a6aeb2c34
[
{
"Name": "4c436b20a6106328fbcb526ac1e37a85758f953007f799939376473a6aeb2c34",
"Driver": "local",
"Mountpoint": "/var/lib/containers/storage/volumes/4c436b20a6106328fbcb526ac1e37a85758f953007f799939
376473a6aeb2c34/_data", "CreatedAt": "2023-05-11T16:20:09.448027507+08:00",
"Labels": {},
"Scope": "local",
"Options": {},
"Anonymous": true
}
]
从上面volume详情可以了解到,现在容器的数据是挂在在宿主机器上 /var/lib/docker/目录下,scope是本地
1-6.通过-v指定容器volume的名字,使用我们自定义的一个可读的名字
[root@yb ~]# podman run -tid --name mysql02 -v evan_volume:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=evan124
docker.io/library/mysql69b44fe47e4c0b75d2a2c8644ddb4fcd6a5ece8133dd1ab8889ecf31d69e39f5
再次查看下volume是否创建成功
[root@yb ~]# podman volume ls
DRIVER VOLUME NAME
local 4c436b20a6106328fbcb526ac1e37a85758f953007f799939376473a6aeb2c34
local evan_volume
1-7. 刚才创建的volume已经成功了,再查看下volume的详细信息
[root@yb ~]# podman inspect evan_volume
[
{
"Name": "evan_volume",
"Driver": "local",
"Mountpoint": "/var/lib/containers/storage/volumes/evan_volume/_data",
"CreatedAt": "2023-05-11T16:27:05.929976112+08:00",
"Labels": {},
"Scope": "local",
"Options": {}
}
]
从上面信息可以看到,容器已经成功挂载宿主机器上的evan_volume
2-bind mount 容器数据持久化
2-1.bind mount初体验
与volumes相比,bind mount的功能有限。 使用绑定安装时,会将主机上的文件或目录安装到容器中。 文件或目录由主机上的完整或相对路径引用。 相比之下,当您使用volume时,将在主机上podman的存储目录中创建一个新目录,并且podman管理该目录的内容。
该文件或目录不需要在Podman主机上已经存在。 如果尚不存在,则按需创建。 bind mounts性能非常好,但是它们依赖于具有特定目录结构的主机文件系统。 如果要开发新的podman应用程序,请考虑使用命名volume。 您不能使用Docker CLI命令直接管理bind mounts
2-2.创建一个tomcat容器,命名为tomcat-bind,挂载宿主机器路径为/tmp
1.搜索一个tomcat的容器
[root@yb ~]# podman search tomcat
INDEX NAME DESCRIPTION
docker.io docker.io/library/tomcat Apache Tomcat is an open source impleme
docker.io docker.io/library/tomee Apache TomEE is an all-Apache Java EE c
docker.io docker.io/bitnami/tomcat Bitnami Tomcat Docker Image
docker.io docker.io/bitnamicharts/tomcat
docker.io docker.io/secoresearch/tomcat-varnish Tomcat and Varnish 5.0
docker.io docker.io/vulhub/tomcat
docker.io docker.io/islandora/tomcat
docker.io docker.io/wnprcehr/tomcat
docker.io docker.io/hivdb/tomcat-with-nucamino
docker.io docker.io/sismics/tomcat Apache Tomcat Servlet Container
docker.io docker.io/eclipse/rdf4j-workbench Dockerfile for Eclipse RDF4J Server and
docker.io docker.io/semoss/docker-tomcat Tomcat, Java, Maven, and Git on top of
docker.io docker.io/eclipse/hadoop-dev Ubuntu 14.04, Maven 3.3.9, JDK8, Tomcat
docker.io docker.io/gbif/ipt The GBIF Integrated Publishing Toolkit
docker.io docker.io/dhis2/base-dev Images in this repository contains DHIS
docker.io docker.io/eclipse/alpine_jdk8 Based on Alpine 3.3. JDK 1.8, Maven 3.3
docker.io docker.io/misolims/miso-base MySQL 5.7 Database and Tomcat 8 Server
docker.io docker.io/dhis2/base Images in this repository contains DHIS
docker.io docker.io/jelastic/tomcat An image of the Tomcat Java application
docker.io docker.io/cfje/tomcat-resource Tomcat Concourse Resource
docker.io docker.io/rightctrl/tomcat CentOS , Oracle Java, tomcat applicatio
docker.io docker.io/amd64/tomcat Apache Tomcat is an open source impleme
docker.io docker.io/arm64v8/tomcat Apache Tomcat is an open source impleme
docker.io docker.io/softwareplant/tomcat Tomcat images for jira-cloud testing
docker.io docker.io/tomcat2111/papercut-mf PaperCut MF Application Server
2. 我们先拉取一个tomcat镜像
[root@yb ~]# podman pull docker.io/library/tomcat
Trying to pull docker.io/library/tomcat:latest...
Getting image source signatures
Copying blob 0d0e0ecb256a done
Copying blob c24bf4c725c2 done
Copying blob 4fb255c76461 done
Copying blob 4800bac131aa done
Copying blob b388fec4cd21 done
Copying blob 1bc677758ad7 done
Copying blob fc4cc5ff9156 done
Copying config 311570738c done
Writing manifest to image destination
Storing signatures
311570738ca337a61aec180371ec60333323079d0f9c69ba6760f8824e41a257
3.创建容器
[root@yb ~]# podman run -tid --name tomcat-bind --mount type=bind,source=/tmp,target=/user/local docker.io/library/mysql
a4c7c48afa5bebd2dd03ea0c69439bb415e056bf67e1c61e832319c7f6de909d
译: 容器名字:tomcat-bind
挂载方式: --mount
挂载类型: bind
挂载源: /tmp 宿主机
目标挂载点: /user/local 容器内的目录
可以看到容器已经成功挂载到宿主机器上的/tmp目录,而不是前面我们演示的docker管理路径下。
2-3 bind mount与volumes总结*****重要的结论,大家务必好好看看!****
-
在podman容器中,bind mount是将主机上的目录或文件夹挂载到podman容器中的指定位置的一种方式。而type参数用于指定挂载类型,常见的挂载类型有bind和volume两种。
-
当type为bind时,表示使用宿主机上的已存在目录或文件进行挂载。这个目录或文件可以在运行命令时直接指定,比如”podman container run -v /host/dir:/container/dir”,这样就可以把主机上的指定目录挂载到容器里面的指定目录中,实现容器与宿主机之间文件共享。
-
而当type为volume时,表示使用podman内部的数据卷进行挂载。这个数据卷可以使用“podman volume create”命令创建,也可以在运行时动态地创建,比如”docker container run -v my_volume_name:/container/dir”。使用volume方式进行挂载,可以实现数据的持久化和跨容器共享。
3-验证podman数码存储
思路:我们尝试在mysql容器创建一个数据库,然后退出后把容器删除掉,再创建一个新的容器,数据存储路径指向同一个volume,观察是否在新的容器可以看到上一个容器创建好的数据库
3-1.进入我们上面创建的mysql
[root@localhost /]# podman exec -it mysql01 /bin/bash
bash-4.4# mysql -uroot -p
Enter password:
提示:上面我们创建容器的时候已经自定义好了密码,我们可以往上翻查阅(密码:evan123)
3-2.创建数据库eshare
mysql> create database eshare
-> ;
Query OK, 1 row affected (0.00 sec)
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| eshare |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
从输出结果可以看到,数据库已经创建成功
3-3.退出容器,删除mysyql01容器
mysql> exit
Bye
root@4dc868313a33:/# exit
exit
[root@yb ~]# podman container rm -f mysql01
mysql01
容器mysql01已经顺利删除
3-4.查看mysql01挂载的volume是否还在
[root@yb ~]# podman volume ls
DRIVER VOLUME NAME
local 3f5b3e857ff3a6d054c74e741eeb84f61ebd9a8ac1063418391bfa8d084390bd ##mysql01
local 4c436b20a6106328fbcb526ac1e37a85758f953007f799939376473a6aeb2c34
local evan_volume
可以看到,对应的volume还在
DRIVER VOLUME NAME
local 3f5b3e857ff3a6d054c74e741eeb84f61ebd9a8ac1063418391bfa8d084390bd ##mysql01
3-5.创建一个新mysql容器,命名为mysql-volume,并且绑定mysql01的volume
[root@yb ~]# podman run -d --name mysql-volume -v 3f5b3e857ff3a6d054c74e741eeb84f61ebd9a8ac1063418391bfa8d084390bd:/var/lib/mysql -e MYSQL_ROOT_PASSWORD=evan123 docker.io/library/mysql
534c4c6c398a6e81af5403d159214af4b35359c00f3ccdce11a3bfea71d22616
3-6.验证新的容器mysql-volume 中,是否存在已经创建好的数据库eshare
root@yb ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
0b762f3d7238 docker.io/library/httpd:latest httpd-foreground 2 days ago Up 2 days ago 0.0.0.0:80->80/tcp myweb
534c4c6c398a docker.io/library/mysql:latest mysqld 53 seconds ago Up 53 seconds ago mysql-volume
[root@yb ~]# podman exec -it mysql-volume /bin/bash
bash-4.4# mysql -uroot -p
Enter password:
mysql> show databases;
+--------------------+
| Database |
+--------------------+
| eshare |
| information_schema |
| mysql |
| performance_schema |
| sys |
+--------------------+
5 rows in set (0.00 sec)
从上面输出结果可以看到,新的容器已经存在之前创建好的数据库,这就证明了docker不仅可以持久化数据,并且不同容器还可以共享同一个volume。
我的步骤是比较详细的哈,大家学习的时候尽量跟着我敲一遍哈!
二、容器网络
1.rootfull 和 rootless 容器网络之间的差异
-
Podman 容器联网的指导因素之一将是容器是否由 root 用户运行。这是因为非特权用户无法在主机上创建网络接口。因此,对于 rootfull 容器,默认网络模式是使用容器网络接口 (CNI) 插件,特别是桥接插件。对于rootless,默认的网络模式是slirp4netns。由于权限有限,slirp4netns缺少CNI组网的一些功能;例如,slirp4netns 无法为容器提供可路由的 IP 地址。
-
由于每次容器重启的时候IP都可能发生变化,为了确保容器间网络的持久性连接,可以采用以下方式进行容器间通过主机名、别名通信,操作如下:
2 自定义配置网络
2-1.podman network create 创建网络
podman支持的网络默认模式是bridge
podman只关心bridge网络
创建podman1网络
[rhel8 root ~]# podman network create podman1
/etc/cni/net.d/podman1.conflist
查看网络
[rhel8 root ~]# podman network ls
NAME VERSION PLUGINS
podman 0.4.0 bridge,portmap,firewall,tuning
podman1 0.4.0 bridge,portmap,firewall,tuning
# --subnet指定subnet创建网络
## podman network create --sunet 网段 创建的网络名
podman network create --subnet 192.5.0.0/16 newnet
# --gateway 指定网关
## podman network create --subnet 网段 --gateway 网关地址 newnet1
podman network create --subnet 192.168.33.0/24 --gateway 192.168.33.3 newnet1
# --ipv6创建ipv6网络
## podman network create --subnet ipv6网段 --ipv6 创建的网络名
podman network create --subnet 2001:db8::/64 --ipv6 newnet6
# --ip-range 指定ip起始地址
podman network create --subnet 192.168.55.0/24 --ip-range 192.168.55.128/25 newnet2
2-2.指定网络运行容器
# podman run --name 容器名 --network 网络名称 镜像名
podman run --name centos1 --network cni-podman2 centos
# 进入容器
podman exec -it centos1 bash
# 查看路由
ip -4 route show
2-3.启动一个容器后,会出现cni-poman0网卡,容器启动时,默认会连接podman网络
[rhel8 root ~]# ip a show cni-podman0
4: cni-podman0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
link/ether ba:97:ef:58:c5:d4 brd ff:ff:ff:ff:ff:ff
inet 10.88.0.1/16 brd 10.88.255.255 scope global cni-podman0
valid_lft forever preferred_lft forever
inet6 fe80::b897:efff:fe58:c5d4/64 scope link
valid_lft forever preferred_lft forever
# bridge link查看网络
[rhel8 root ~]# bridge link
5: veth4fb3982e@ens224: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 master cni-podman0 state forwarding priority 32 cost 2
2-4.检查inspec 容器网络
# 查看容器IP地址
[yb root ~]# podman inspect c8|grep IPAddress
"IPAddress": "10.88.0.2",
"IPAddress": "10.88.0.2",
三、root用户容器开机自启动
1.web容器设置开机自启
[root@yb ~]# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS
NAMES534c4c6c398a docker.io/library/mysql:latest mysqld 3 days ago Up 3 days ago
mysql-volumebb697c6e3df7 docker.io/library/httpd:latest httpd-foreground 17 minutes ago Up 17 minutes ago
new_web
2.基于web容器,在优先级一般的/etc/systemd/system内创建.service单元文件
[root@yb ~]# cd /etc/systemd/system/
[root@yb system]# ls
basic.target.wants getty.target.wants sockets.target.wants
cloud-init.target.wants graphical.target.wants sysinit.target.wants
dbus-org.freedesktop.nm-dispatcher.service multi-user.target.wants syslog.service
dbus-org.freedesktop.timedate1.service network-online.target.wants systemd-timedated.service
default.target remote-fs.target.wants timers.target.wants
3.查看一下容器生成开机自启动参数
[root@podman user]# podman generate systemd --
--container-prefix (Systemd unit name prefix for containers)
--files {生成.service文件,而不是打印到标准输出}
--format (Print the created units in specified format (json)) #以指定的格式打印单元文件
--name (Use container/pod names instead of IDs) #创建新容器,而不是使用现有的容器
--new (Create a new container instead of starting an existing one)#(跳过标头生成)
--no-header (Skip header generation)
--pod-prefix (Systemd unit name prefix for pods)
--restart-policy (Systemd restart-policy)
--separator (Systemd unit name separator between name/id and prefix)
--time (Stop timeout override)
[root@yb system]# podman generate systemd --name new_web --new --files
/etc/systemd/system/container-new_web.service
[root@yb system]# ls
basic.target.wants getty.target.wants sysinit.target.wants
cloud-init.target.wants graphical.target.wants syslog.service
*container-new_web.service* multi-user.target.wants systemd-timedated.service
dbus-org.freedesktop.nm-dispatcher.service network-online.target.wants timers.target.wants
dbus-org.freedesktop.timedate1.service remote-fs.target.wants
default.target sockets.target.wants
4.我们可以查看一下里面得参数
[root@yb system]# vim container-new_web.service
# container-new_web.service
# autogenerated by Podman 3.3.1
# Mon May 15 14:56:49 CST 2023
[Unit]
Description=Podman container-new_web.service
Documentation=man:podman-generate-systemd(1)
Wants=network-online.target
After=network-online.target
RequiresMountsFor=%t/containers
[Service]
Environment=PODMAN_SYSTEMD_UNIT=%n
Restart=on-failure
TimeoutStopSec=70
ExecStartPre=/bin/rm -f %t/%n.ctr-id
ExecStart=/usr/bin/podman run --cidfile=%t/%n.ctr-id --sdnotify=conmon --cgroups=no-conmon --rm --replace
-tid --name new_web 28505717e3aeExecStop=/usr/bin/podman stop --ignore --cidfile=%t/%n.ctr-id
ExecStopPost=/usr/bin/podman rm -f --ignore --cidfile=%t/%n.ctr-id
Type=notify
NotifyAccess=all
[Install]
WantedBy=multi-user.target default.target
~
5、删除刚才得容器
[root@yb system]# podman rm -f new_web
bb697c6e3df7695e243aba0a5bd487211db9ef613fba0d9a10150c4673ada3eb
释义: -f 参数是强制删除的意思,如果没有添加-f参数,容器会报错仍在运行,建议你stop后再删除
6、设置开机自启动
[root@yb system]# systemctl daemon-reload
[root@yb system]# systemctl enable container-new_web.service --now
Created symlink /etc/systemd/system/multi-user.target.wants/container-new_web.service → /etc/systemd/syst
em/container-new_web.service.Created symlink /etc/systemd/system/default.target.wants/container-new_web.service → /etc/systemd/system/
container-new_web.service.[root@yb system]# loginctl enable-linger
[root@yb system]# loginctl show_user root
Unknown operation show_user.
[root@yb system]# loginctl s
seat-status session-status show-seat show-session show-user
[root@yb system]# loginctl show-user root
UID=0
GID=0
Name=root
Timestamp=Mon 2023-05-15 11:40:53 CST
TimestampMonotonic=868172373063
RuntimePath=/run/user/0
Service=user@0.service
Slice=user-0.slice
Display=19
State=active
Sessions=21 20 19
IdleHint=no
IdleSinceHint=0
IdleSinceHintMonotonic=0
Linger=yes
7、测试
1、重启服务器
[root@yb system]# reboot
[root@yb system]# podman ps
[root@yb system]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS
PORTS NAMES534c4c6c398a docker.io/library/mysql:latest mysqld 3 days ago Up 3 days ago
mysql-volume82c6e2a481da docker.io/library/httpd:latest httpd-foreground About a minute ago Up About a minute ago
new_web
此时,容器id已更换了,但容器名和资源还在
四、无根容器开机自启动
1、以普通用户创建的容器使用开机自启动
1-1、设置开机自启动的相关文件位置
[yb@yb ~]$ mkdir -p .config/systemd/user
1-2、拉取容器镜像
[yb@yb user]$ podman pull docker.io/clearlinux/httpd
Trying to pull docker.io/clearlinux/httpd:latest...
Getting image source signatures
Copying blob 3fc5c71a93dd done
Copying blob e154924ae66b done
Copying blob 87901fe5b3ed done
Copying blob d3ac9ef9d58b done
Copying blob 23c4e75893cc done
Copying blob 764bcd048f2d done
Copying config 72b26075d9 done
Writing manifest to image destination
Storing signatures
72b26075d92a9cd024cb12fe8016bbe7ef9276ce9be03936854c6c3f7e32d211
1-3 创建一个容器
[yb@yb user]$ podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/clearlinux/httpd latest 72b26075d92a 5 days ago 143 MB
###设置开机自启动
[yb@yb user]$ podman run -tid --name web 72b26075d92a
6a048c6e116817ecce7a2059628e092dd35ab5dc4d5f171bbcc3512b9d53c137
1-4 设置开启自动动
###
[yb@yb user]$ podman generate systemd --name web --new --files
/home/yb/.config/systemd/user/container-web.service
[yb@yb user]$ systemctl --user enable container-web.service --now
Created symlink /home/yb/.config/systemd/user/multi-user.target.wants/container-web.service → /home/yb/.config/systemd/user/container-web.service.
Created symlink /home/yb/.config/systemd/user/default.target.wants/container-web.service → /home/yb/.config/systemd/user/container-web.service.
[yb@yb user]$ ls
container-web.service default.target.wants multi-user.target.wants
[yb@yb user]$ loginctl enable-linger
[yb@yb user]$ loginctl show-user yb
UID=1000
GID=1000
Name=yb
Timestamp=Mon 2023-05-15 15:51:16 CST
TimestampMonotonic=883195115972
RuntimePath=/run/user/1000
Service=user@1000.service
Slice=user-1000.slice
Display=22
State=active
Sessions=22
IdleHint=no
IdleSinceHint=0
IdleSinceHintMonotonic=0
Linger=no