对于初学者来说,不太容易理解什么是容器,这里举一个例子。想象一下,我们把系统安装在一个U盘中,此系统中安装好了MySQL。 然后我们把这个U盘插人一台正在运行的物理机上,这个物理机上并没有安装MySQL,如下左图所示。
然后把U盘中的mysqld进程“曳”到物理机上运行。但是这个mysqld进程只能适应U盘中的系统,不一定能适应物理机上的系统。所 以,我们找一个类似气球的东西把 mysqld进程在物理机中包裹保护起来,这个mysqld进程依然适应U盘中的生态环境(系统),却可以从 物理机上吸收CPU和内存作为维持mysqld进程运行的“养分”。
那么,这个类似气球的东西就是容器,U盘就是镜像。
在Linux中安装软件包时经常会遇到各种包依赖,或者有人不会在 Linux系统(如Ubuntu、CentOS)中安装软件包。这样以后我们就不 需要安装和配置MySQL了,直接把这个“U盘”插到电脑上,然后运行一个容器出来,这样就有MySQL这个服务了。
所谓镜像,就是安装了系统的硬盘文件,这个系统中安装了想要运行的程序,如 MySQL.Nginx,并规定好使用这个镜像所生成的容器 里面运行什么进程。这里假设有一个安装了MySQL的镜像,如下右图所示。
在服务器上有一个MySQL 的镜像(已经安装好了MySQL),然后使用这个镜像生成一个容器。这个容器中只运行一个mysqld进程,容器 中的mysqld进程直接从物理机上吸收CPU和内存以维持它的正常运行。
以后需要什么应用,就直接拉取什么镜像下来,然后使用这个镜像生成容器。例如,需要对外 提供 MySQL服务,那么就拉取一个MySQL镜像,然后生成一个MySQL容器。如果需要对外提供 Web服 务,那么就拉取一个Nginx镜像,然后生成一个Nginx容器。
一个镜像是可以生成很多个容器的,如右图所示。
1.安装及配置podman
前面已经配置了yum源,所以这里直接使用yum install podman -y命令安装
[root@jiayi ~]# yum -y install podman
查看现在系统中有多少镜像
[root@jiayi ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
没有任何输出,说明现在还没有镜像。
下面开始拉取docker.io/nginx镜像
[root@jiayi ~]# podman pull docker.io/nginx
Trying to pull docker.io/library/nginx:latest...
Getting image source signatures
...
Writing manifest to image destination
Storing signatures
a6bd71f48f6839d9faae1f29d3babef831e76bc213107682c5cc80f0cbb30866
网易仓库地址是https://c.163yun.com/hub#/home,在浏览器中打开此界面需要登录,然后搜索需要的镜像即可。下面从网易仓库中 拉取 CentOS镜像
[root@jiayi ~]# podman pull hub.c.163.com/library/centos
Trying to pull hub.c.163.com/library/centos:latest...
Getting image source signatures
Copying blob a3ed95caeb02 done
Copying blob a3ed95caeb02 done
Copying blob 2409c3878ba1 done
Writing manifest to image destination
Storing signatures
328edcd84f1bbf868bc88e4ae37afe421ef19be71890f59b4b2d8ba48414b84d
2.镜像管理
2.1镜像的命名
一般情况下,镜像的命名格式如下
服务器IP: 端口 /分类 /镜像名 :tag
如果不指定端口则默认为80,如果不指定 tag则默认为latest
在把镜像上传(push)到仓库时,镜像必须按这种格式命名,因为仓库地址就是由镜像前面的IP决定的。如果只是在本机使用镜像,命名 可以随意。
查看当前系统有多少镜像
[root@jiayi ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/nginx latest a6bd71f48f68 3 weeks ago 191 MB
hub.c.163.com/library/centos latest 328edcd84f1b 6 years ago 200 MB
2.2对镜像重新做标签
如果想给本地已经存在的镜像起一个新的名称,可以用tag来做
podman tag 旧的镜像名 新的镜像名
tag之后,新的镜像名和旧的镜像名是同时存在的
给镜像做新标签
[root@jiayi ~]# podman tag docker.io/library/nginx nginx
建议tag 可以设置为版本号、日期等有意义的字符。
再次查看镜像
[root@jiayi ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
docker.io/library/nginx latest a6bd71f48f68 3 weeks ago 191 MB
localhost/nginx latest a6bd71f48f68 3 weeks ago 191 MB
hub.c.163.com/library/centos latest 328edcd84f1b 6 years ago 200 MB
可以看到,对某镜像做了标签之后,看似是两个镜像,其实对应的是同一个(这类似于Linux中硬链接的概念,一个文件两个名称而 已),镜像ID都是一样的。删除其中一个镜像,是不会删除存储在硬盘上的文件的,只有把 IMAGE ID所对应的所有名称全部删除,才会从 硬盘上删除。
2.3删除镜像
如果要删除镜像,需要按如下语法来删除
podman rmi 镜像名:tag
删除镜像
[root@jiayi ~]# podman rmi docker.io/library/nginx:latest
Untagged: docker.io/library/nginx:latest
可以看到,只是简单的一个Untagged操作,并没有任何Deleted操作
查看镜像
[root@jiayi ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/nginx latest a6bd71f48f68 3 weeks ago 191 MB
hub.c.163.com/library/centos latest 328edcd84f1b 6 years ago 200 MB
可以看到,a6bd71f48f68对应的本地文件依然是存在的,因为它(ID为a6bd71f48f68)有两个名称,现在只是删除了一个名称而已,所 以在硬盘上仍然是存在的
只有删除最后一个名称,本地文件才会被删除。
2.4查看镜像的层结构
虽然我们所用的镜像都是从网上下载下来的,但这些镜像在制作过程中都是一点点修改、一步步做出来的。如果我们要看某镜像的这些 步骤,可以用podman history命令,语法如下
podman history镜像名
查看镜像的结构
[root@jiayi ~]# podman history hub.c.163.com/library/centos
ID CREATED CREATED BY SIZE COMMENT
328edcd84f1b 6 years ago /bin/sh -c #(nop) CMD ["/bin/bash"] 0 B
6 years ago /bin/sh -c #(nop) LABEL name=CentOS Base ... 0 B
6 years ago /bin/sh -c #(nop) ADD file:63492ba809361c5... 200 MB
最上层的CMD,定义的是当使用这个镜像生成的容器时,运行的进程为/bin/bash。
2.5导出和导入镜像
一些服务器是无法连接到互联网的,所以无法从互联网上下载镜像。在还没有私有仓库的情况下,如何把现有的镜像传输到其他机器上 呢?这里就需要把本地已经pull下来的镜像导出为一个本地文件,这样就可以很容易地传输到其他机器。导出镜像的语法如下
podman save 镜像名 > file.tar
把 localhost/nginx 导出为nginx.tar
[root@jiayi ~]# podman save localhost/nginx > nginx.tar
删除 Nginx这个镜像
[root@jiayi ~]# podman rmi localhost/nginx:latest
Untagged: localhost/nginx:latest
Deleted: a6bd71f48f6839d9faae1f29d3babef831e76bc213107682c5cc80f0cbb30866
既然上面已经把镜像导出为一个文件了,那么需要把这个文件导入,语法如下
podman load ‐i file.tar
把nginx.tar导入为镜像
[root@jiayi ~]# podman load -i nginx.tar
Getting image source signatures
...
Writing manifest to image destination
Storing signatures
Loaded image(s): localhost/nginx:latest
查看现有镜像
[root@jiayi ~]# podman images
REPOSITORY TAG IMAGE ID CREATED SIZE
localhost/nginx latest a6bd71f48f68 3 weeks ago 191 MB
hub.c.163.com/library/centos latest 328edcd84f1b 6 years ago 200 MB
3.创建容器
容器就是镜像在宿主机上运行的一个实例,大家可以把容器理解为一个气球,气球中运行了一个进程,这个进程透过气球吸收物理机的 内存和 CPU 资源
查看当前有多少正在运行的容器
[root@jiayi ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
这个命令显示的仅仅是正在运行的容器,如果要查看不管是运行还是不运行的容器,需要加上-a选项,即 podman ps-a。
3.1创建一个简单的容器
运行一个最简单的容器
[root@jiayi ~]# podman run hub.c.163.com/library/centos
[root@jiayi ~]# podman ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
[root@jiayi ~]# podman ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
5a784d209ba9 hub.c.163.com/library/centos:latest /bin/bash 9 seconds ago Exited (0) 9 seconds ago xenodochial_joliot
可以看到,创建了一个容器,容器ID为5a784d209ba9,容器名是随机产生的,所使用的镜像是 hub.c.163.com/library/centos,容器中运行的进程为/bin/bash(也就是镜像中的CMD指定的)
podman ps看不到,podman ps -a能看到,且状态为Exited,说明容器是关闭状态。容器运行的一瞬间就关闭了,为什么?
3.2容器的生命周期
把容器理解为人的肉体,里面运行的进程理解为人的灵魂。如果人的灵魂宕机了,肉体也就宕机了,只有灵 魂正常运行,肉体才能正常运行,如右图所示。
同理,只有容器中的进程正常运行,容器才能正常运行,容器中的进程宕机了,容器也就宕机了。因为没有终 端的存在,/bin/bash就像执行ls命令一样一下就执行完了,所以容器生命期也就到期了。
如果把这个bash附着到一个终端上,这个终端一直存在,bash就一直存在,那么是不是容器就能一直存活了 呢?
删除容器的语法如下
podman rm 容器ID/容器名
如果删除正在运行的容器,可以使用-f选项
删除刚才的容器
[root@jiayi ~]# podman rm 5a784d209ba9
5a784d209ba9d70982dbd1c591eac603a493b07524c9f019a845329a72bec9df
重新创建新的容器,加上-i -t选项,可以写作-it或-i-t。
(1)-t:模拟一个终端。
(2)-i:可以让用户进行交互,否则用户看到一个提示符之后就卡住不动了。
创建一个容器
[root@jiayi ~]# podman run -it hub.c.163.com/library/centos
[root@7d5534216a50 /]# exit
exit
创建好容器之后就自动进入容器中了,可以通过exit退出容器
但是一旦退出容器,容器就不再运行了
[root@jiayi ~]# podman ps -a -q
7d5534216a50
-q 选项可以只显示容器 ID ,不会显示太多信息
删除此容器
[root@jiayi ~]# podman rm -f 7d5534216a50
7d5534216a50bf8f25ec5329816e6905fd8064594278bde116905f803d490a15
如果希望创建好容器之后不自动进入容器中,可以加上-d选项
再次创建一个容器
[root@jiayi ~]# podman run -dit hub.c.163.com/library/centos
57c413a2f7c31f3700c91b0f1006bbaa8b26ee1a8c76d28d4e5fb2557360374f
因为加了-d选项,所以创建好容器之后并没有自动进入容器中。进入此容器中
[root@jiayi ~]# podman attach 57c413a2f7c31
[root@57c413a2f7c3 /]# exit
exit
[root@jiayi ~]# podman ps -a -q
57c413a2f7c3
[root@jiayi ~]# podman ps -q
可以看到,只要退出来容器就会自动关闭
删除此容器
[root@jiayi ~]# podman rm 57c413a2f7c3
57c413a2f7c31f3700c91b0f1006bbaa8b26ee1a8c76d28d4e5fb2557360374f
在运行容器时加上--restart=always选项可以解决退出容器自动关闭的问题
创建容器,增加--restart=always选项
[root@jiayi ~]# podman run -dit --restart=always hub.c.163.com/library/centos
311d99195cfde508b7978913d9dff264a12a2382cc88a585cf92ccc6ff90c86f
[root@jiayi ~]# podman ps -q
311d99195cfd
[root@jiayi ~]# podman attach 311d99195cfd
[root@311d99195cfd /]# exit
exit
[root@jiayi ~]# podman ps -q
311d99195cfd
可以看到退出后,容器依然是运行中的
删除此容器,因为容器是运行的,所以需要加上-f选项
[root@jiayi ~]# podman rm -f 311d99195cfd
311d99195cfde508b7978913d9dff264a12a2382cc88a585cf92ccc6ff90c86f
每次删除容器时,都要使用容器ID,这种方式比较麻烦,在创建容器时可以使用--name选项指定容器名
创建容器,使用--name 选项指定容器的名称
[root@jiayi ~]# podman run -dit --restart=always --name=jia hub.c.163.com/library/centos
6f36210d6ca477dcd66488cfbc34e720ffa0d0cadb108df78ceafd68315f6eae
这样容器的名称为jia,以后管理起来比较方便,如切换到容器,然后退出
[root@jiayi ~]# podman attach jia
[root@6f36210d6ca4 /]# exit
exit
删除此容器
[root@jiayi ~]# podman rm -f jia
6f36210d6ca477dcd66488cfbc34e720ffa0d0cadb108df78ceafd68315f6eae