这篇内容将会介绍podman管理容器。

        ●  了解什么是容器

        ●  安装和配置podman

        ●  拉取和删除镜像

        ●  给镜像打标签

        ●  导出和导入镜像

        ●  创建和删除镜像

        ●  数据卷的使用

        ●  管理容器的命令

       对于初学者来说,不太容易理解什么是容器,这里举一个例子,想象一下,我们把系统安装在一个U盘中,此系统中安装好了MySQL。然后我们把这个U盘插入一台正在运行的物理机上,这个物理机上并没有安装MySQL,如图1-1所示

        然后把U盘中的musqld进程“曳”到物理机上运行。但是这个mysqld进程只能适应U盘中的系统,不一定能适应物理机上的系统。所以,我们找一个类似气球的东西把mysqld进程在物理机中包裹保护起来,这个musqld进程依然适应U盘中的生态环境(系统),却可以从物理机上吸收CPU和内存作为维持mysqld进程的“养分”。

        那么这个类似气球的东西就是容器,U盘就是镜像。

        在linux中安装软件包时经常会遇到各种包依赖,或者有人不会在Linux系统(如Ubuntu、CentOS)中安装软件包。这样以后我们就不需要安装和配置MySQL了,直接把这个“U盘”插到电脑上,然后运行一个容器出来,这样就有MySQL这个服务了。

        所谓镜像,就是安装了系统的硬盘文件,这个系统中安装了想要运行的程序,如MySQLNginx,并规定好使用这个镜像所生成的容器里面运行什么进程。这里假设有一个安装了MySQL的镜像,如图1-2所示。

图1-2 了解镜像和容器
图1-1 了解镜像和容器

        在服务器上由一个MySQL的镜像(已经安装好了MySQL),然后使用这个镜像生成一个容器。这个容器中只运行一个mysqld进程,容器中的mysqld进程直播从物理机上吸收CPU和内存以维持它的正常运行。

        以后需要什么应用,就直接拉取什么镜像下来,然后使用这个镜像生成容器,例如,需要对外提供MySQL服务,那么就拉取一个MySQL镜像,然后生成一个MySQL容器。如果需要对外提供Web服务,那么就拉取一个Nginx镜像没然后生成一个Nginx容器。

        一个镜像是可以生成很多歌容器的,如图1-3所示。

图1-3 了解镜像和容器

一、安装及配置podman

        前面已经配置了yum源,所以这里直接使用yum install podman -y命令安装,命令如下。

1 [root@server ~]# yum ‐y install podman

        查看现在系统中有多少镜像,命令如下。

1 [root@server ~]# podman images
2 REPOSITORY TAG IMAGE ID CREATED SIZE
3 [root@server ~]#

        没有任何输出,说明现在还没有镜像。

        查看系统中有多少容器,命令如下。

1 [root@server ~]# podman ps
2 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3 [root@server ~]#

        没有任何输出,说明当前没有容器。

        如果要拉取镜像,一般是从国外网站的镜像仓库中拉取,速度会很慢,默认podman从以下仓库中拉取镜像:registry.access.redhat.com、registry.redhat.io、docker.io。下面配置加速器,提高docker.io中拉取镜像的速度。

        登录阿里云控制台,找到容器颈项服务,单击镜像工具→镜像加速器,找到自己的加速器地址,这里使用的是https://frz7i079.mirror.aliyuncs.com.

        修改podman的配置文件/etc/containers/registries.conf,修改内容如下。

1 [root@server ~]# cat /etc/containers/registries.conf
2
3 unqualified‐search‐registries = ["docker.io"]
4 [[registry]]
5 prefix = "docker.io"
6 location = "frz7i079.mirror.aliyuncs.com"

        这里的意思是从docker.io中拉取镜像时使用加速器frz7i079.mirror.aliyuncs.com,注意这里不需要加https,配置好之后不需要重启什么服务。

        下面开始拉取docker.io/nginx镜像,命令如下。

1 [root@server ~]# podman pull mysql
2 Resolving "mysql" using unqualified‐search registries (/etc/containers/registries.conf)
3 Trying to pull docker.io/library/mysql:latest...
4 Getting image source signatures
5 ...输出...
6 Writing manifest to image destination
7 Storing signatures
8 3218b38490cec8d31976a40b92e09d61377359eab878db49f025e5d464367f3b
9 [root@server ~]#

        拉取MySQL镜像docker.io/mysql,命令如下。

1 [root@server ~]# podman pull mysql
2 Resolving "mysql" using unqualified‐search registries (/etc/containers/registries.conf)
3 Trying to pull docker.io/library/mysql:latest...
4 Getting image source signatures
5 ...输出...
6 Writing manifest to image destination
7 Storing signatures
8 3218b38490cec8d31976a40b92e09d61377359eab878db49f025e5d464367f3b
9 [root@server ~]#

        网易仓库地址是https://c.163yun.com/hub#/home,在浏览器中打开此界面需要登录,然后搜索需要的镜像即可。下面从网易仓库中拉取CentOS镜像,命令如下。

1 [root@server ~]# podman pull hub.c.163.com/library/centos
2 Trying to pull hub.c.163.com/library/centos:latest...
3 Getting image source signatures
4 Copying blob a3ed95caeb02 done
5 Copying blob a3ed95caeb02 done
6 Copying blob 2409c3878ba1 done
7 Writing manifest to image destination
8 Storing signatures
9 328edcd84f1bbf868bc88e4ae37afe421ef19be71890f59b4b2d8ba48414b84d
10 [root@server ~]#

二、镜像管理

        前面讲了想要创建容器必须有镜像,本节主要讲解镜像的管理。

1.镜像的命名

        一般情况下,镜像的命名格式如下。

1 服务器IP:端口 /分类 /镜像名 :tag

        如果不指定端口则默认为80,如果不指定tag则默认为latest。

        例如,192.168.26.101:5000/cka/centos:v2。

        再如,hub.c.163.com/library/mysql:latest。

        分类也是可以不写的,如docker.io/nginx:latest。

        再把镜像上传(push)到仓库时,镜像必须按这种格式命名,因为仓库地址就是由镜像前面的IP决定的,如果只是在本机使用镜像命名可以随意。

        查看当前系统有多少镜像,命令如下。

1 [root@server ~]# podman images
2 REPOSITORY TAG IMAGE ID CREATED SIZE
3 docker.io/library/nginx latest 605c77e624dd 15 months ago 146 MB
4 docker.io/library/mysql latest 3218b38490ce 15 months ago 521 MB
5 hub.c.163.com/library/centos latest 328edcd84f1b 5 years ago 200 MB
6 [root@server ~]#
 2.对镜像重新做标签

        如果想给本地已经存在的镜像起一个新的名称,可以用tag来做,语法如下。

1 podman tag 旧的镜像名 新的镜像名

        tag之后,新的镜像名和旧的镜像名是同时存在的。

        步骤 ①:给镜像做新标签,命令如下。

1 [root@server ~]# podman tag docker.io/library/mysql 192.168.8.11/rhce/mysql:v2
2 [root@server ~]#

        这里是为docker.io/library/mysql重新做个tag,名称为192.168.26.101/rhce/mysql,标签为2,这样命名的目的是让大家看到命名的随意性,建议tag 可以设置为版本号,日期等有意义的字符。

       步骤 ②:再次查看镜像,命令如下。

1 [root@server ~]# podman images
2 REPOSITORY TAG IMAGE ID CREATED SIZE
3 docker.io/library/nginx latest 605c77e624dd 15 months ago 146 MB
4 docker.io/library/mysql latest 3218b38490ce 15 months ago 521 MB
5 192.168.8.11/rhce/mysql v2 3218b38490ce 15 months ago 521 MB
6 hub.c.163.com/library/centos latest 328edcd84f1b 5 years ago 200 MB
7 [root@server ~]#

        可以看到,对某镜像做了标签之后,看似是两个镜像没气势对应的是同一个(这类似于Linux中硬链接的概念,一个文件两个名称而已),镜像ID都是一样的。删除其中一个镜像,是不会删除存储在硬盘上的文件的,只有把IMAGE ID所对应的所有名称全部删除,才会从硬盘上删除。

3.删除镜像

        如果要删除进行,需要按如下语法来删除。

1 podman rmi 镜像名.tag

        例如,下面要把docker.io/library/mysql:latest删除。

        步骤 ①:删除镜像,命令如下。

1 [root@server ~]# podman rmi docker.io/library/mysql:latest
2 Untagged:docker.io/library/mysql:latest
3 [root@server ~]#

        可以看到,只是简单的一个Untagged操作,并没有任何Deleted操作。

        步骤 ②:查看镜像,命令如下。

1 [root@server ~]# podman images
2 REPOSITORY TAG IMAGE ID CREATED SIZE
3 docker.io/library/nginx latest 605c77e624dd 15 months ago 146MB
4 192.168.8.11/rhce/mysql v2 3218b38490ce 15 months ago 521MB
5 hub.c.163.com/library/centos latest 328edcd84f1b 5 years ago 200MB
6 [root@server ~]#

        可以看到,b05128b000dd的本地文件依然是存在的,因为它(ID为b05128b000dd)有两个名称,现在只是删除了一个名称而已,所以在硬盘上仍然是存在的。

        只有删除最后一个名称,本地文件才会被删除。

        步骤③:删除镜像,命令如下。

1 [root@server ~]# podman rmi 192.168.8.11/rhce/mysql:v2
2 Untagged:192.168.8.11/rhce/mysql:v2
3 Deleted: 3218b38490cec8d31976a40b92e09d61377359eab878db49f025e5d464367f3b
4 [root@server ~]#
4.查看镜像的层结构

        虽然外面所用的镜像都是从网上下载下来的,但这些镜像在制作过程中都是一点点修改。一步步做出来的。如果我们要看某镜像的这些步骤,可以用podman history命令,语法如下。

1 podman history镜像名

        查看镜像的结构,命令如下。

1 [root@server ~]# podman history hub.c.163.com/library/centos
2 ID CREATED CREATED BY SIZE COMMENT
3 328edcd84f1b 5 years ago /bin/sh ‐c #(nop) CMD ["/bin/bash"] 0 B
4 <missing> 5 years ago /bin/sh ‐c #(nop) LABEL name=CentOS Base ... 0 B
5 <missing> 5 years ago /bin/sh ‐c #(nop) ADD file:63492ba809361c5... 200 MB
6 [root@server ~]#

        最上层的CMD,定义的是当使用这个镜像生成的容器时,运行的进程为/bin/bash

5.导出和导入镜像

        一些服务器是无法连接到互联网的,所以无法从互联网上下载镜像。在还没有私有仓库的情况下,如何把现有的镜像传输到其他机器上呢?这里就需要把本地已经pull下来的镜像导出为一个本地文件,这样就可以很容易地传输到其他机器。导出镜像的语法如下。

1 podman save 镜像名 > file.tar

        步骤 ①:把docker.io/nginx:latest 导出为nginx.tar,命令如下。

1 [root@server ~]# podman save docker.io/library/nginx > nginx.tar

        删除Nginx这个镜像,命令如下。

1 [root@server ~]# podman rmi docker.io/library/nginx
2 Untagged: docker.io/library/nginx:latest
3 Deleted: 605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
4 [root@server ~]#
5 [root@server ~]# podman images
6 REPOSITORY TAG IMAGE ID CREATED SIZE
7 hub.c.163.com/library/centos latest 328edcd84f1b 5 years ago 200 MB
8 [root@server ~]#

        既然上面已经把镜像导出为一个文件了,那么需要把这个文件导入,语法如下。

1 podman load -i file.tar

        步骤 ②:把nginx。tar导入为镜像,命令如下。

1 [root@server ~]# podman load ‐i nginx.tar
2 ...输出...
3 Writing manifest to image destination
4 Storing signatures
5 Loaded image(s): docker.io/library/nginx:latest
6 [root@server ~]#

        查看现有镜像,命令如下。

1 [root@server ~]# podman images
2 REPOSITORY TAG IMAGE ID CREATED SIZE
3 docker.io/library/nginx latest 605c77e624dd 15 months ago 146 MB
4 hub.c.163.com/library/centos latest 328edcd84f1b 5 years ago 200 MB
5 [root@server ~]#

三、创建容器

        容器就是镜像在宿主机上运行的一个实例,大家可以把容器理解为一个气球,气球中运行了一个进程,这个进程透过气球吸收物理机的内存和CPU资源。

        查看当前有多少正在运行的容器,命令如下。

1 [root@server ~]# podman ps
2 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3 [root@server ~]#

        这个命令显示的仅仅是正在运行的容器,如果要查看不管是运行还是不运行的容器,需要加上-a选项,即podman ps-a。

1.创建一个简单的容器

        运行一个最简单的容器,命令如下。

1 [root@server ~]# podman run hub.c.163.com/library/centos
2 [root@server ~]# podman ps
3 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
4 [root@server ~]# podman ps -a
5 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6 9d378ad18604 hub.c.163.com/library/centos:latest /bin/bash 10         
  secondsagoExited(0)9secondsago youthful_darwin
7 [root@server ~]#

        可以看到,创建了一个容器,容器ID为455391081738,容器名是随机产生的,名称为kind_elgamal,所使用的镜像是hub.c.163.com/library/centos,容器中运行的进程为/bin/bash(也就是镜像中的CMD指定的)。

         podman ps看不到,podman ps -a能看到,且状态为Exited,说明容器时关闭状态。

2.容器的生命期

        把容器理解为人的肉体,里面运行的进程理解为人的灵魂。如果人的灵魂宕机了,肉体也就宕机了,只有灵魂正常运行,肉体才能正常运行,如图1-4所示

图1-4 容器和进程之间的关系

        同理,只有容器中的进程正常运行,容器才能正常运行,容器中的进程宕机了,容器也就宕机了,因为没有终端的存在,/bin/bash就像执行ls命令一样就执行完了,所以容器生命期也就到期了。如果把这个bash附着到一个终端上,这个终端一直存在,bash就一直存在,那么是不是容器就能一直存活了呢?

        删除容器的语法如下。

1 podman rm 容器ID/容器名

        如果删除正在运行的容器,可以使用-f选项。

1 podman rm -f 容器ID/容器名

        步骤 ①:删除刚才的容器,命令如下。

1 [root@server ~]# podman rm 9d378ad18604
2 9d378ad18604cfd7d96812de5bb688abab7cbc85107622ca34c7c7568453c8ef
3 [root@server ~]#

        重新创建新的容器,加上-i -t 选项,可以写作-it或-i-t。

        (1)-t:模拟一个终端

        (2)-i:可以让用户进行交互,否则用户看到一个提示符之后就卡主不动了。

        步骤 ②:创建一个容器,命令如下。

1 [root@server ~]# podman run -it hub.c.163.com/library/centos
2 [root@5ff643f2a4f6 /]#
3 [root@5ff643f2a4f6 /]# exit
4 exit
5 [root@server ~]#

        创建好容器之后就自动进入容器中了,可以通过exit退出容器,命令如下。

1 [root@server ~]# podman ps ‐q #‐q选项可以只显示容器ID,不会显示太多信息
2 [root@server ~]#
3 [root@server ~]# podman ps ‐a ‐q
4 5ff643f2a4f6
5 [root@server ~]#

        但是一旦退出容器,容器就不再运行了。

        步骤 ③:删除此容器,命令如下。

1 [root@server ~]# podman rm -f 5ff643f2a4f6
2 5ff643f2a4f6887ef46ecf503bf00bfb2e45515047adeb76bca1ec7dac8d4a9b
3 [root@server ~]#

        如果希望创建好容器之后不自动进入容器中,可以加上-d选项。

        步骤④:再次创建一个容器,命令如下。

1 [root@server ~]# podman run -dit hub.c.163.com/library/centos
2 c4a834e35be7cdf22ce090b361dbcd56f14597d1816bd6182cba30b3672c3654
3 [root@server ~]#

        因为加了-d选项,所以创建好容器之后并没有自动进入容器中。进入容器中,命令如下。

1 [root@server ~]# podman attach c4a834e35be7
2 [root@c4a834r35be7 /]# exit
3 exit
4
5 [root@server ~]# podman ps -q
6 [root@server ~]# podman ps -a -q
7 c4a834e35be7
8 [root@server ~]#

        可以看到,只要退出来容器就会自动关闭。

        步骤⑤:删除此容器,命令如下。

1 [root@server ~]# podman rm c4a834e35be7
2 c4a834e35be7cdf22ce090b361dbcd56f14597d1816bd6182cba30b3672c3654
3 [root@server ~]#

        在运行容器室加上--restart=always选项可以解决退出容器自动关闭的问题。

        步骤⑥:创建容器,增加--restart=always选项,命令如下。

1 [root@server ~]# podman run ‐dit ‐‐restart=always hub.c.163.com/library/centos
2 21f30fdeff624427625b92118a933d37fb4ddfebc6704274f2e85a97695c2b15
3 [root@server ~]#

        进入容器并退出,命令如下。

1 [root@server ~]# podman ps ‐q
2 21f30fdeff62
3 [root@server ~]# podman attach 21f30fdeff62
4 [root@21f30fdeff62 /]# exit
5 exit
6
7 [root@server ~]# podman ps ‐q
8 21f30fdeff62
9 [root@server ~]#

        可以看到,容器依然是存活的。

        步骤⑦:删除此容器,因为容器是运行的,所以需要加上-f选项,命令如下。

1 [root@server ~]# podman rm ‐f 21f30fdeff62
2 21f30fdeff624427625b92118a933d37fb4ddfebc6704274f2e85a97695c2b15
3 [root@server ~]#

        每次删除容器时,都要使用容器ID,这种方式比较麻烦,在创建容器时可以使用--name选项指定容器名。

        步骤⑧:创建容器,使用--name 选项制动容器的名称。

1 [root@server ~]# podman run ‐dit ‐‐restart=always ‐‐name=c1 hub.c.163.com/library/centos
2 09506132c09e4ab00ccbeed7a73f1e63de60f96861d5c02047b1496912e2f153
3 [root@server ~]#

        这样容器的名称为c1,以后管理起来比较方便,如切换到容器,然后退出,命令如下。

1 [root@server ~]# podman attach c1
2 [root@09506132c09e /]#
3 [root@09506132c09e /]# exit
4 exit
5
6 [root@server ~]#

        步骤⑨:删除此容器,命令如下。

1 [root@server ~]# podman rm ‐f c1
2 09506132c09e4ab00ccbeed7a73f1e63de60f96861d5c02047b1496912e2f153
3 [root@server ~]# podman ps ‐a ‐q
4 [root@server ~]#
3.创建临时容器

        如果要临时创建一个测试容器,又怕用完忘记删除它,可以加上--rm选项。

        创建临时容器,命令如下。

1 [root@server ~]# podman run ‐it ‐‐name=c1 ‐‐rm hub.c.163.com/library/centos
2 [root@fcfc9f1fd3d0 /]# exit
3 exit
4 [root@server ~]#

        创建容器时加了 --rm选项,退出容器之后容器会被自动删除

1 [root@server ~]# podman ps ‐a ‐q
2 [root@server ~]#

        可以看到,此容器被自动删除了,注意--rm和--restart=always选项不可以同时使用

4.指定容器中运行的命令

        创建容器时,容器中运行的是什么进程,都是有镜像中的CMD指定的。如果想自定义容器中运行的进程,可以在创建容器的命令最后指定,如下所示。

1 [root@server ~]# podman run ‐it ‐‐name=c1 ‐‐rm hub.c.163.com/library/centos sh
2 sh‐4.2#
3 sh‐4.2# exit
4 exit
5 [root@server ~]#

        这里就是以sh的方式运行,而不是以bash的方式运行。

5.创建容器时使用变量

        在利用一些镜像创建容器时需要传递变量,例如。使用MySQL的镜像、WordPress的镜像创建容器时都需要通过变量来指定一些必备的信息。需要使用-e选项来指定,可以多次使用-e选项来指定多个变量

        创建一个你名称为c1的容器,里面传递两个变量,命令如下。

1 [root@server ~]# podman run ‐it ‐‐name=c1 ‐‐rm ‐e aa=123 ‐e bb=456 hub.c.163.com/library/centos
2 [root@6559a724d0d6 /]# echo $aa
3 123
4 [root@6559a724d0d6 /]# echo $bb
5 456
6 [root@6559a724d0d6 /]# exit
7 exit
8 [root@server ~]#

        在创建容器时,通过-e选项指定了两个变量aa和bb,然后进入容器之后可以看到具有这两个变量。

6.把容器的端口映射到物理机上

        外部主机(主机之外的其他主机)是不能和容器进行通信的,如果希望外部主机能访问到容器的内容,就需要使用-p选项将容器的端口映射到物理机上,以后访问物理机对应的端口就可以访问到容器了,如图1-5所示。

图1-5 把容器的端口映射到物理机上

         语法如下

-p N:物理机随机生成一个端口映射到容器的端口N上

-p M:N:把容器的端口N映射到物理机指定的端口M上

步骤 ①:创建一个名称为web的容器,把容器的端口80映射到物理机的一个随机端口上,命令如下。

1 [root@server ~]# podman run ‐d ‐‐name=web ‐‐restart=always ‐p 80 docker.io/library/nginx
2 ab224c828bebed2f078cf795a626ea9c36413bb8fe839be2ea6beedfde1da38d
3 [root@server ~]#

        这里把web容器的端口80映射到物理机的随机端口上,这个端口号可以通过如下命令来查询.

[root@server ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
ab224c828beb docker.io/library/nginx:latest nginx -g daemon o... 42 seconds ago Up 42 seconds ago 0.0.0.0:34137->80/tcpweb
[root@server ~]#

        可以看到,映射到物理机的33513上了,访问物理机的端口33513即可访问到web容器,结果如图1-6所示

图1-6 访问物理机的端口 33513

         删除此容器,命令如下。

1 [root@server ~]# podman rm ‐f web
2 ab224c828bebed2f078cf795a626ea9c36413bb8fe839be2ea6beedfde1da38d
3 [root@server ~]#

        步骤 ②:如果想映射到物理机指定的端口上,命令如下。

1 [root@server ~]# podman run ‐d ‐‐name=web ‐‐restart=always ‐p 88:80 docker.io/library/nginx
2 aa18014a48cb9a626c072b6d29332f0d2726d2d25bcfc390ad2fcd0fcec05d28
3 [root@server ~]#

        这里把web容器的端口80映射到物理机的端口88上(可以自己指定端口,如80),那么访问物理机的端口88即可访问到web容器的端口80,结果如图1-7所示。

图1-7 访问物理机的端口88

         删除此容器,命令如下。

1 [root@server ~]# podman rm ‐f web
2 aa18014a48cb9a626c072b6d29332f0d2726d2d25bcfc390ad2fcd0fcec05d28
3 [root@server ~]#

 四、实战训练——创建MySQL的容器

        创建MySQL容器时不要使用从阿里云或Docker官方仓库中下载的镜像,请拉取镜像

hub.c.163.com/library/mysql.

        在使用MySQL镜像时至少需要指定一个变量 MYSQL_ROOT_PASSWORD来指定root密码,其他变量如MySQL_USER、MYSQL_PASSWORD、MYSQL_DATABASE都是可选的。

1 [root@server ~]# podman history hub.c.163.com/library/mysql
2 ID CREATED CREATED BY SIZE COMMENT
3 9e64176cd8a2 5 years ago /bin/sh ‐c #(nop) CMD ["mysqld"] 0 B
4 ...输出...
5 [root@server ~]#

        可以看到,使用MySQL镜像创建出来的容器中运行的是myssql。

        步骤 ①:创建容器,命令如下。

[root@server ~]# podman run -d --name=db --restart=always -e MYSQL_ROOT_PASSWORD=haha001 -e
MYSQL_DATABASE=blog hub.c.163.com/library/mysql
8d0b321e8035bc246b182e64b26f30dfb133db031a86b43db3ccb0cbc8223aea
[root@server ~]#

        这里使用MYSQL_ROOT_PASSWORD指定了MySQL root密码为haha001,通过MYSQLDATABASE在容器中创建了一个名称数据库。

        步骤②:做连接测试。

        查看db容器的IP,命令如下。

1 [root@server ~]# podman inspect db | grep ‐i ipaddr
2 "IPAddress": "10.88.0.2",
3 "IPAddress": "10.88.0.2",
4 [root@server ~]#

        在宿主机上用yum命令安装MariaDB客户端(命令式yum -y install mariadb),然后连接容器,命令如下。

1 [root@server ~]# mysql ‐uroot ‐phaha001 ‐h10.88.0.2
2 ...输出...
3 MySQL [(none)]> show databases;
4 +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
5 | Database |
6 +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
7 | information_schema |
8 | blog |
9 | mysql |
10 | performance_schema |
11 | sys |
12 +‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐+
13 5 rows in set (0.001 sec)
14
15 MySQL [(none)]>

        可以看到,用密码haha001能正确地连接到容器中,并且也创建了一个名称为blog的库。

五、管理容器的命令

        容器如同一台没有显示器的电脑,如何查看容器中的内容呢,又如何在容器中执行命令呢?使用podman exec命令来实现,如图1-8所示

图1-8 在容器中执行命令
 1.在容器中执行指定的命令

        语法如下

1 podman exec 容器名 命令

        步骤①:在db容器中执行 ip a | grap 'inet'  命令,命令如下

1 [root@server ~]# podman exec db ip a | grep 'inet '
2 inet 127.0.0.1/8 scope host lo
3 inet 10.88.0.2/16 brd 10.88.255.255 scope global eth0
4 [root@server ~]#

        如果容器中没有要执行的命令,就会出现如下报错。

1 [root@server ~]# podman exec db ifconfig
2 Error: exec failed: container_linux.go:380: starting container process caused: exec: "ifconfig": executable file
not found in $PATH: OCI runtime attempted to invoke a command that was not found
3 [root@server ~]#

        如果想获取shell控制台,需要加上-it选项。

        步骤②:获取容器中的bash控制台,命令如下。

1 [root@server ~]# podman exec ‐it db bash
2 root@8d0b321e8035:/# exit
3 exit
4 [root@server ~]#
注意
有的镜像中不存在bash,可以使用sh替代
2.物理机和容器互相拷贝文件

        有时我们需要让物理机和容器之间互相拷贝一些文件。拷贝文件的语法如下。

1 podman cp /path/file 容器:/path2 把物理机中的/path/f1e拷贝到容器的/path2中
2 podman cp 容器:/path2/file /path/ 把容器中的/path2/l1e拷贝到物理机的/path2中

        步骤①:把物理机中的/etc/hosts拷贝到容器的/opt中,命令如下。

1 [root@server ~]# podman exec db ls /opt/
2 [root@server ~]# podman cp /etc/hosts db:/opt/
3 [root@server ~]# podman exec db ls /opt/
4 hosts
5 [root@server ~]#

        步骤②:把容器中的/etc/password拷贝到物理机的/opt中,命令如下。

1 [root@server ~]# rm ‐rf /opt/*
2 [root@server ~]# podman cp db:/etc/passwd /opt/
3 [root@server ~]# ls /opt/
4 passwd
5 [root@server ~]#
 3.关闭、启动、重启容器

        一般情况下,在操作系统中重启某个服务,可以通过“systemctl restart服务名”来重启,容器中一般是无法使用systemctl命令的。要重启容器中的程,直接重启容器就可以啦。下面演示如何关闭、启动、重启容器。

        步骤①:关闭、启动、重启容器,命令如下。

1 [root@server ~]# podman stop db
2 db
3 [root@server ~]# podman start db
4 db
5 [root@server ~]# podman restart db
6 8d0b321e8035bc246b182e64b26f30dfb133db031a86b43db3ccb0cbc8223aea
7 [root@server ~]#

        步骤②:查看容器中运行的进程。

        语法为“podman top 容器名”,这个类似于任务管理器,可以查看到容器中正在运行的进程,命令如下。

1 [root@server ~]# podman top db
2 USER PID PPID %CPU ELAPSED TTY TIME COMMAND
3 mysql 1 0 0.000 24m13.019055174s ? 0s mysqld
4 [root@server ~]#
4.查看容器中的输出

        当容器无法正常运行时,需要查看容器中的输出来进行排错。如果要查看容器中的日志信息,可以通过如下命令来查看。

1的podman logs 容器名

        如果想不间断地查看输出,可以使用如下命令。

1 podman logs -f 容器名

        步骤①:查看容器日志输出,命令如下。

1 [root@server ~]#podman logs db
2 Initializing database
3 ...输出...
4 [root@server ~]#

        如果要查看容器的属性,可以使用“podman inspect容器名”命令。

        步骤②:查看b容器的属性,命令如下。

1 [root@server ~]# podman inspect db

        在这个输出中,可以查看到容器的各种信息,如数据卷、网络信息等。

5.数据卷的使用

        当容器创建出来之后,会映射到物理机的某个目录(这个目录叫作容器层)中,在容器中写的数据实际都存储在容器层,所以只要容器不被删除,在容器中写的数据就会一直存在。但是一旦删除容器,对应的容器层也被删除。

图1-9 数据卷

        如果希望数据能永久保存,则需要配置数据卷,把容器中的指定目录挂载到物理机的某目录上,如图1-9所示

        这里把容器中的目录aa挂载到物理机的目录bb上,当往容器目录aa中写数据时,实际上是往物理机的目录bb中写的。这样即使删除了容器,物理机目录bb中的数据仍然是存在的,就实现了数据的永久保留(除非手动删除)。

        在创建容器时,用-v选项指定数据卷,用法如下。

1 ‐v /dirl 把物理机的一个随机目录映射到容器的/dir1目录中
2 ‐v /dir2:/dirl:Z 把物理机的指定目录/dir2映射到容器的/dir1目录中

        记住,冒号左边的/dir2是物理机的目录,此目录需要提前创建出来;冒号右边的/dir1是容器中的目录,如果此目录不存在则会自动创建。这里大写Z的意思是把物理机的目录/dir2的上下文改成container_file_t。

        步骤①:创建一个名称为c1的容器,把物理机的一个随机目录映射到容器的/data目录中,命令如下。

[root@server ~]# podman run -dit --name=c1 --restart=always -v /data/ hub.c.163.com/library/centos
2062485cca2814f3c8190921ce58ffc5bd26aa5c572ade99a4cafe074473890a
[root@server ~]#

        在此命令中,v后面只指定了一个目录/data,指的是在容器中创建/data,挂载到物理机上的一个随机目录上。

        步骤②:查看对应物理机是哪个目录,命令如下。

1 [root@server ~]# podman inspect c1 | grep ‐A5 Mounts
2 "Mounts": [
3 {
4 "Type": "volume",
5 "Name": "974991051a4dc7e2e088fcc9f015159e4670994299484259d1e72692c89c68b4",
6 "Source": "/var/lib/containers/storage/volumes/974991051a4dc7e2e088fcc9f015159e4670994299484259d1e72692c89c68b
4/_data",
7 "Destination": "/data",
8 [root@server ~]#

        上面有两个参数,其中 Destin ation 指的是容器中的目录,Source指的是物理机对应的目录。得到的结论就是容器中的目录/data对应物理机的/var/lib/containers/storage/volumes/d18f9d35971c7e11dfba9423058812a22e0da5b176ee2f0ce9649eeecf995463/_dat

        先查看c1容器的目录/data中的数据和物理机对应目录的数据,命令如下。

1 [root@server ~]# podman exec c1 ls /data/
2 [root@server ~]# ls /var/lib/containers/storage/volumes/974991051a4dc7e2e088fcc9f015159e4670994299484259d1e72692
c89c68b4/_data/
3 [root@server ~]#

        可以看到,目录是空的,如下所示。

1 [root@server ~]# podman cp /etc/hosts c1:/data/
2 [root@server ~]# podman exec c1 ls /data/
3 hosts
4 [root@server ~]# ls /var/lib/containers/storage/volumes/974991051a4dc7e2e088fcc9f015159e4670994299484259d1e72692
c89c68b4/_data/
5 hosts
6 [root@server ~]#

        往容器中拷贝数据,物理机中也会有这个数据了。

        步骤③:删除此容器,命令如下。

1 [root@server ~]# podman rm ‐f c1
2 2062485cca2814f3c8190921ce58ffc5bd26aa5c572ade99a4cafe074473890a
3 [root@server ~]#

        如果想在物理机中也指定目录而非随机挂载目录,则使用-v/xx:/data,此处冒号左边是物理机的目录,冒号右边是容器中的目录,这里要提前在物理机上把目录/xx创建出来

        步骤④:创建一个名称为c1的容器,把物理机的目录/xx映射到容器的/data目录中,命令如下。

1 [root@server ~]# mkdir /xx
2 [root@server ~]#
3 [root@server ~]# podman run ‐dit ‐‐name=c1 ‐‐restart=always ‐v /xx:/data/:Z hub.c.163.com/library/centos
4 c169fc621b11abefbcbefc94ba6d1c99337878f5dfa75939b8577acdc536ebbf
5 [root@server ~]#

        这里大写Z的意思是把物理机的目录/xx的上下文改成container_file_t。查看/xx的上下文,命令如下。

1 [root@server ~]# ls ‐dZ /xx
2 system_u:object_r:container_file_t:s0:c341,c956 /xx
3 [root@server ~]#

        查看此容器的属性,命令如下。

1 [root@server ~]# podman inspect c1 | grep ‐A5 Mounts
2 "Mounts": [
3 {
4 "Type": "bind",
5 "Source": "/xx",
6 "Destination": "/data",
7 "Driver": "",
8 [root@server ~]#

        步骤⑤:拷贝一些测试文件过去并观察一下,命令如下。

1 [root@server ~]# podman exec c1 ls /data/
2 [root@server ~]# ls /xx/
3 [root@server ~]#
4 [root@server ~]# podman cp /etc/hosts c1:/data/
5 [root@server ~]# podman exec c1 ls /data/
6 hosts
7 [root@server ~]# ls /xx/
8 hosts
9 [root@server ~]#

        步骤⑥:删除此容器,命令如下。

1 [root@server ~]# podman rm ‐f c1
2 c169fc621b11abefbcbefc94ba6d1c99337878f5dfa75939b8577acdc536ebbf
3 [root@server ~]#

        在重启系统后,所创建的容器并不会随着系统自动运行,可把容器创建为一个服务,然后设置这个服务开机自动启动,那么这个容器也就可以实现开机自动启动了。

        下面用blab用户创建一个容器,然后实现开机自动启动。

6.使用普通用户对容器进行管理

        使用blab用户通过ssh登录到server,切记这里不能通过其他用户用su命令切换到blab用户。

        不同用户对镜像和容器的管理都是独立的,所以root拉取的镜像并不能给laduan用户使用。

1 [blab@server ~]$ podman images
2 REPOSITORY TAG IMAGE ID CREATED SIZE
3 [blab@server ~]$

        可以看到,使用lduan用户查询时是没有任何镜像的,所以先拉取Nginx镜像,命令如下。

1 [blab@server ~]$ podman pull docker.io/library/nginx
2 Trying to pull docker.io/library/nginx:latest...
3 ...输出...
4 605c77e624ddb75e6110f997c58876baa13f8754486b461117934b24a9dc3a85
5 [blab@server ~]$

        查看现有镜像,命令如下。

1 [blab@server ~]$ podman images
2 REPOSITORY TAG IMAGE ID CREATED SIZE
3 docker.io/library/nginx latest 605c77e624dd 15 months ago 146 MB
4 [blab@server ~]$

        为了使用数据卷,先使用root用户创建一个目录/yy并把所有者和所属组改为blab,命令如下。

1 [root@server ~]# mkdir /yy
2 [root@server ~]# chown blab.blab /yy
3 [root@server ~]#

        然后使用blab用户创建一个名称为web的容器,并把物理机的目录/yy映射到容器的/data目录中,命令如下。

1 [blab@server ~]$ podman run ‐dit ‐‐name=web ‐‐restart=always ‐v /yy:/data/:Z docker.io/library/nginx
2 4fa5fe299870329dbd8e5a4449e68eaf4fbfdcdc82b16788d85beab79ececead
3 [blab@server ~]$

        现在容器创建好了,但是这个容器在系统重启时并不会随着系统一起启动,所以下面设置允许开机自动运行容器。要让容器跟着系统一起启动,需要为这个容器创建一个服务。

        首先设置blab用户创建的服务在系统启动时能自动启动,命令如下。

1 [blab@server ~]$ loginctl enable‐linger blab
2 [blab@server ~]$

        如果这里没有开启,或者通过loginctl disable-lin ger blab关闭了,那么系统启动之后lduan用户创建的服务是不会启动启动的,只有lduan用户通过ssh或者控制台登录之后,服务才会启动起来。

        这里设置了logincd enable-linger blab,当系统启动之后,blab用户及时没有通过ssh或控制台登录,blab用户创建的服务也会自动启动,是开启还是关闭可以通过loginctl show-user blab | grep Linger来查看。

        因为要为容器创建出来一个服务,所以先创建存储服务文件的目录,命令如下。

1 [blab@server ~]$ mkdir ‐p ~/.config/systemd/user ; cd ~/.config/systemd/user
2 [blab@server user]$ ls
3 [blab@server user]$

        web容器生成一个服务文件,命令如下。

1 [blab@server user]$ podman generate systemd ‐‐name web ‐‐files ‐‐new
2 /home/blab/.config/systemd/user/container‐web.service
3 [blab@server user]$ ls
4 container‐web.service
5 [blab@server user]$

        这里--new的意思是,及时现在把web容器删除,那么重启系统时也会自动创建这个容器。

        其中--name可以简写为-n,--files可以简写为-f,--new可以省略,所以整个命令可以简写如下。

1 podman generate systemd ‐n web ‐f

        重新加载这个服务文件这里要加上--user选项,命令如下。

1 [blab@server user]$ systemctl ‐‐user daemon‐reload
2 [blab@server user]$

        设置这个服务开机自动启动,命令如下。

1 [blab@server user]$ systemctl ‐‐user enable container‐web.service
2 ...输出...
3 [blab@server user]$ ls
4 container‐web.service default.target.wants multi‐user.target.wants
5 [blab@server user]$

        然后重启操作系统进行验证,命令如下。

1 [blab@server ~]$ podman ps
2 CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
3 29f2207c3e95 docker.io/library/nginx:latest nginx ‐g daemon o... 5 seconds ago Up 6 seconds ago web

        等系统启动之后发现web容器跟着系统启动起来了。

Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐