7.2.7 容器生命周期
坊间流传容器不能持久化数据。其实容器可以做到!
人们认为容器不擅长持久化工作或者持久化数据,很大程度上是因为容器在非持久化领域上表现得太出色。但是在一个领域做得很好并不意味着不擅长其他的领域。很多虚拟机管理员会记得微软或者Oracle告诉他们不能在虚拟机中运行他们的应用,至少他们不会支持这么做。有时会想到容器身上是否也在发生类似的事情——一些人为了保护他们的持久化业务帝国避免受到容器的威胁才这么说?
本节主要关注容器的生命周期——从创建、运行、休眠,直至销毁的整个过程。
前面介绍了如何使用 docker container run
命令来启动容器。接下来会重新启动一个新的容器,这样就可以观察期完整的生命周期。下面的示例中会采用Linux Docker主机来运行Ubuntu容器。但同时,示例内容在前面例子中使用过的Windows PowerShell容器中也是生效的——尽管读者需要将Linux命令替换为对应的Windows命令。
$ docker container run --name percy -it ubuntu:latest /bin/bash
root@9cb2d2fd1d65:/#
这就是新建的容器,名称为“percy”,意指持久化(persistent)。
接下来把该容器投入使用,将一部分数据写入其中。
在新容器内部Shell中,执行下面的步骤来将部分数据写入到 tmp
目录下的某个文件中,并确认数据是否写入成功。
root@9cb2d2fd1d65:/# cd tmp
root@9cb2d2fd1d65:/tmp# ls -l
total 0
root@9cb2d2fd1d65:/tmp# echo "DevOps FTW" > newfile
root@9cb2d2fd1d65:/tmp# ls -l
total 4
-rw-r--r-- 1 root root 14 May 23 11:22 newfile
root@9cb2d2fd1d65:/tmp# cat newfile
DevOps FTW
按 Ctrl-PQ
组合键退出当前容器。
现在使用 docker container stop
命令来停止容器运行,切换到暂停(vacation)状态。
$ docker container stop percy
percy
读者可以在 docker container stop
命令中指定容器的名称或者ID。具体格式为 docker container stop <container-id or container-name>
。
现在运行 docker container ls
命令列出全部处于运行中状态的容器。
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
新建的容器没有在上面的列表中出现,原因是读者通过 docker container stop
命令使该容器停止运行。加上 -a
参数再次运行前面的命令,就会显示出全部的容器,包括处于停止状态的。
$ docker container ls -a
CNTNR ID IMAGE COMMAND CREATED STATUS NAMES
9cb...65 ubuntu:latest /bin/bash 4 mins Exited (0) percy
现在可以看到该容器显示当前状态为 Exited(0)
。停止容器就像停止虚拟机一样。尽管已经停止运行,容器的全部配置和内容仍然保存在Docker主机的文件系统之中,并且随时可以重新启动。
使用 docker container start
命令可以将容器重新启动。
$ docker container start percy
percy
$ docker container ls
CONTAINER ID IMAGE COMMAND CREATED STATUS NAMES
9cb2d2fd1d65 ubuntu:latest "/bin/bash" 4 mins Up 3 secs percy
现在停止的容器已经重新启动了,此时可以确认之前创建的文件是否还存在。使用 docker container exec
命令连接到重启后的容器。
$ docker container exec -it percy bash
root@9cb2d2fd1d65:/#
Shell提示符发生变化,提示正在容器内部空间进行操作。
确认之前创建的文件依然存在,并且文件中仍包含之前写入的数据。
root@9cb2d2fd1d65:/# cd tmp
root@9cb2d2fd1d65:/# ls -l
-rw-r--r-- 1 root root 14 Sep 13 04:22 newfile
root@9cb2d2fd1d65:/#
root@9cb2d2fd1d65:/# cat newfile
DevOps FTW
像是魔术一般,之前创建的文件依然存在,并且文件中包含的数据正是离开的方式!这证明停止容器运行并不会损毁容器或者其中的数据。
尽管上面的示例阐明了容器的持久化特性,还是需要指出卷(volume)才是在容器中存储持久化数据的首选方式。但是在当前阶段,这个示例用于说明容器的持久化特性已经足够了。
到目前为止,读者应该对容器和虚拟机之间的主要区别有了深刻的印象。
现在停止该容器并从系统中删除它。
通过在 docker container rm
命令后面添加 -f
参数来一次性删除运行中的容器是可行的。但是,删除容器的最佳方式还是分两步,先停止容器然后删除。这样可以给容器中运行的应用/进程一个停止运行并清理残留数据的机会。
在下一个示例中会停止 percy
容器,删除它并确认操作成功。如果读者终端仍连接到 percy
容器,则需要按下 Ctrl-PQ组合键
先返回Docker主机终端。
$ docker container stop percy
percy
$ docker container rm percy
percy
$ docker container ls -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
现在容器已经删除了——在系统中消失。如果这是一个有用的容器,那么之后可以作为无服务的工具使用;如果没有用处,则充其量也就是一个蹩脚的终端。
总结一下容器的生命周期。可以根据需要多次停止、启动、暂停以及重启容器,并且这些操作执行得很快。但是容器及其数据是安全的。直至明确删除容器前,容器都不会丢弃其中的数据。就算容器被删除了,如果将容器数据存储在卷中,数据也会被保存下来。
下面简单说明一下为什么推荐两阶段方式来停止并删除容器。