Docker容器化2023版本——容器

简介

容器是镜像的运行时实例。就像你可以从虚拟机模板启动虚拟机一样,你可以从一个单独的镜像启动一个或多个容器。容器与虚拟机的一个重要区别是,容器更小、更快,且更具可移植性。

图7.1显示了使用单个Docker镜像启动多个Docker容器的情况。

image.png

最简单的启动容器的方法是使用docker run命令。该命令可以接受许多参数,但在最基本的形式中,您需要告诉它要使用的镜像和要运行的应用程序:docker run <镜像> <应用程序>。以下命令将基于Ubuntu Linux镜像启动一个新的容器,并启动一个Bash shell。

$ docker run -it ubuntu /bin/bash

使用-it标志将您当前的终端窗口连接到容器的shell。

容器会一直运行,直到主要应用程序退出。在前面的示例中,当Bash shell退出时,容器也会退出。

一个简单的方法来演示这一点是启动一个新的容器,并让它运行sleep命令,休眠10秒钟。容器将启动,占用您的终端10秒钟,然后退出。以下是在Linux主机上演示这一点的简单方法。

$ docker run -it alpine:latest sleep 10

您可以使用docker stop手动停止运行中的容器,并使用docker start重新启动它。要永久删除一个容器,您必须使用docker rm显式删除它。

这就是简要介绍!现在让我们进入细节...

深入

我们首先将介绍容器和虚拟机之间的基本区别。现在主要是理论内容,但这是非常重要的信息。

容器与虚拟机对比

容器与虚拟机都需要在主机上运行。主机可以是您的笔记本电脑、数据中心中的裸金属服务器或公共云中的实例。

假设您的业务需要在一台物理服务器上运行4个业务应用程序。

在虚拟机模型中,物理服务器启动并启动了虚拟化程序。一旦启动,虚拟化程序会占用所有物理资源,如CPU、RAM、存储和网络卡。然后,它将这些硬件资源划分为看起来、感觉和真实硬件完全相同的虚拟构建块。然后将它们打包到称为虚拟机(VM)的软件构建块中。我们在这些VM上安装操作系统和应用程序。

假设需要在一台单一的物理服务器上运行4个业务应用程序的情况下,我们会创建4个VM,安装4个操作系统,然后在每个VM上安装4个应用程序。在完成后,它看起来就像图7.2所示。

image.png

在容器模型中,情况有些不同。

服务器启动并引导操作系统。在这个容器模型中,主机的操作系统占用所有硬件资源。接下来,您安装一个容器引擎,比如Docker。然后,容器引擎会划分操作系统资源(进程树、文件系统、网络堆栈等),并将它们打包成称为容器的虚拟操作系统。每个容器看起来、感觉和真实操作系统完全相同。在每个容器内部,我们运行一个应用程序。

如果我们假设相同的情景,即一台单一的物理服务器需要运行4个业务应用程序,我们会将操作系统分割成4个容器,并在每个容器内运行一个单独的应用程序。这在图7.3中显示出来。

image.png

从高层次来看,虚拟化管理程序执行硬件虚拟化,将物理硬件资源划分为称为虚拟机(VM)的虚拟版本。另一方面,容器执行操作系统虚拟化,将操作系统资源划分为称为容器的虚拟版本。

虚拟机税(VM tax)

让我们在刚刚讲述的基础上深入探讨虚拟化模型中的一个问题。

我们从一个单独的物理服务器开始,需要运行4个业务应用程序。在虚拟机模型中,我们安装了一个称为“hypervisor”的专用操作系统,而在容器模型中,我们安装了任何现代操作系统。到目前为止,这两种模型几乎是相同的。但是,这就是相似之处的结束。

在虚拟机模型中,低级别的硬件资源被分割成虚拟机。每个虚拟机是一个包含虚拟CPU、虚拟RAM、虚拟磁盘等的软件结构。因此,每个虚拟机都需要自己的操作系统来管理和初始化所有这些虚拟资源。不幸的是,每个操作系统都附带自己的负担和开销。例如,每个操作系统都会消耗CPU、RAM和存储空间。一些操作系统需要自己的许可证,以及人员和基础设施来进行修补和更新。每个操作系统还会呈现一个相当大的攻击面。我们经常将所有这些称为操作系统税(OS tax)或虚拟机税(VM tax)- 每个操作系统都在夺取你本应分配给应用程序的资源。

容器模型中只有一个操作系统内核,而且它运行在共享主机上。可以在单个主机上使用单个共享操作系统运行数百个容器。这意味着只有一个操作系统消耗CPU、RAM和存储空间。它还意味着只需要一个操作系统来进行许可证、更新和修补,只需要一个操作系统来呈现攻击面。总之,只有一个操作系统税账单。

在我们的例子中,一个单独的服务器运行4个业务应用程序可能看起来并不多。但是当你开始讨论数百甚至数千个应用程序时,情况就会发生改变。

另一个需要考虑的因素是应用程序的启动时间。容器启动比虚拟机更快,因为它们只需要启动应用程序 - 内核已经在主机上运行。在虚拟机模型中,每个虚拟机需要在启动应用程序之前启动完整的操作系统。

所有这些使得容器模型比虚拟机模型更为精简和高效。您可以在更少的资源上运行更多的应用程序,更快地启动它们,并在许可证和管理成本方面付出更少的代价,以及呈现更小的攻击面!

容器和容器平台的早期版本被认为比虚拟机不安全。然而,这种情况已经发生了变化,大多数容器引擎和平台现在使用“合理的默认设置”部署容器,试图在不使安全性无法使用的情况下限制其功能。存在许多技术可以使容器比虚拟机更安全,但有时配置起来可能会比较困难。其中包括SELinux、AppArmor、seccomp、capabilities等。

理论部分讲完了,现在让我们开始亲自操作容器吧。

运行容器

你需要一个正常工作的Docker主机来跟随示例操作。我建议使用Docker Desktop或来自Canonical的Multipass。只需在网络上搜索或询问你的AI如何安装它们,它们非常简单。

检查Docker是否正在运行

我每次登录到Docker主机时,首先运行docker version命令来检查Docker是否正在运行。这是一个好的命令,因为它会检查CLI和引擎组件。

$ docker version
Client: Docker Engine - Community
 Version:           24.0.0
 API version:       1.43
 OS/Arch:           linux/arm64
 Context:           default
 <Snip>
Server: Docker Engine - Community
 Engine:
  Version:          24.0.0
  API version:      1.43 (minimum version 1.12)
  OS/Arch:          linux/arm64
  <Snip>

只要在客户端和服务器部分都得到了回应,你应该可以正常运行。如果在服务器部分得到了错误代码,很有可能Docker守护进程(服务器)没有运行,或者你的用户账户没有权限访问它。

在Linux上,你需要确保你的用户账户是本地docker Unix组的成员。如果不是,你可以使用usermod -aG docker <user>命令将其添加进去,然后你需要重新启动你的shell才能使更改生效。另外,你也可以在所有的docker命令前面加上sudo

如果你的用户账户已经是本地docker组的成员,问题可能是Docker守护进程没有在运行。要检查Docker守护进程的状态,请根据你的Docker主机操作系统运行以下命令中的一个。

Linux系统不使用Systemd。

$ service docker status
docker start/running, process 29393

Linux系统使用Systemd。

$ systemctl is-active docker
active

启动一个简单的容器

使用docker run命令是启动容器的最简单方法。

这个命令会启动一个简单的容器,该容器将运行一个以容器方式运行的Ubuntu Linux版本。

$ docker run -it ubuntu:latest /bin/bash

Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
79d0ea7dc1a8: Pull complete
Digest: sha256:dfd64a3b42...47492599ee20739e8eb54fbf
Status: Downloaded newer image for ubuntu:latest
root@e37f24dc7e0a:/#

让我们仔细看看这个命令。

docker run 告诉Docker运行一个新的容器。-it 标志使容器变为交互式,并将其连接到您的终端。ubuntu:latest 参数告诉Docker使用哪个镜像来启动容器。最后,/bin/bash 是在容器中运行的应用程序。

当您按回车键时,Docker客户端会将命令打包并将其POST到运行在Docker守护程序上的API服务器。Docker守护程序接受命令,并在主机的本地映像存储库中搜索,以查看是否已经有镜像的副本。在我们的示例中,它没有找到,因此它前往Docker Hub查找。它找到了镜像,将其拉到本地,并存储在本地缓存中。

注意:在标准的、开箱即用的Linux安装中,Docker守护程序在本地的Unix套接字/var/run/docker.sock上实现Docker API。在Windows上,它在命名管道npipe:////./pipe/docker_engine上监听。还可以配置Docker守护程序在网络上监听。Docker的默认非TLS网络端口是2375,默认TLS端口是2376。

一旦镜像被拉取,守护进程会指示containerd启动容器。containerd使用runc创建容器并启动应用程序。

如果您跟着操作,您的终端现在已连接到容器 — 仔细看,您会注意到您的shell提示已经改变。在示例中是 root@e37f24dc7e0a:/#,但您的会有所不同。@ 后面的长数字是容器唯一ID的前12个字符。

尝试在容器内执行一些基本命令。您可能会注意到有些命令不起作用。这是因为这些镜像经过优化,以轻量级为主,没有安装所有正常的命令和软件包。以下示例显示了几个命令 — 一个成功执行,另一个失败。

root@50949b614477:/# ls -l
total 64
lrwxrwxrwx   1 root root    7 Apr 23 11:06 bin -> usr/bin
drwxr-xr-x   2 root root 4096 Apr 15 11:09 boot
drwxr-xr-x   5 root root  360 Apr 27 17:24 dev
drwxr-xr-x   1 root root 4096 Apr 27 17:24 etc
drwxr-xr-x   2 root root 4096 Apr 15 11:09 home
lrwxrwxrwx   1 root root    7 Apr 23 11:06 lib -> usr/lib
<Snip>

root@50949b614477:/# ping nigelpoulton.com
bash: ping: command not found

正如您所见,ping实用程序并未包含在官方Ubuntu镜像中。

容器进程

当我们启动Ubuntu容器时,我们告诉它运行Bash shell(/bin/bash)。这使得Bash shell成为容器内唯一正在运行的进程。您可以通过在容器内部运行ps -elf命令来查看这一点。

root@e37f24dc7e0a:/# ps -elf
F S UID   PID  PPID   NI ADDR SZ WCHAN  STIME TTY     TIME      CMD
4 S root    1     0    0 -  4558 wait   00:47 ?     00:00:00  /bin/bash
0 R root   11     1    0 -  8604 -      00:52 ?     00:00:00  ps -elf

列表中的第一个进程,具有PID 1,是我们告诉容器运行的Bash shell。第二个进程是我们运行的ps -elf命令,用于生成列表。这是一个短暂存在的进程,一旦输出显示完毕,就会退出。长话短说,此容器正在运行一个单独的进程 — /bin/bash。

在登录到容器时键入exit将终止Bash进程,整个容器也将退出(终止)。这是因为容器不能没有其指定的主进程而存在。这对于Linux和Windows容器都是成立的 — 杀死容器中的主进程将会终止容器。

按下Ctrl-PQ以退出容器,而不终止其主进程。这样做会将您放回到Docker主机的shell中,并将容器保持在后台运行。您可以使用docker ps命令查看系统上正在运行的容器列表。

$ docker ps
CNTNR ID   IMAGE          COMMAND    CREATED  STATUS    NAMES
e37..7e0a  ubuntu:latest  /bin/bash  6 mins   Up 6mins  sick_montalcini

理解这一点很重要,这个容器仍然在运行,您可以使用docker exec命令重新连接到它的终端。

$ docker exec -it e37f24dc7e0a bash
root@e37f24dc7e0a:/#

正如您所看到的,shell提示已经改回容器状态。如果再次运行ps -elf命令,您将会看到两个Bash进程。这是因为docker exec命令创建了一个新的Bash进程并连接到它。这意味着在此shell中键入exit将不会终止容器,因为原始的Bash进程将继续运行。

键入exit以离开容器,并通过docker ps验证它仍在运行。它仍然在运行中。

如果您正在按照示例进行操作,请使用以下两个命令停止并删除容器(您需要替换您的容器ID)。容器可能需要几秒钟来正常停止。

$ docker stop e37f24dc7e0a
e37f24dc7e0a

$ docker rm e37f24dc7e0a
e37f24dc7e0a

容器生命周期

在本节中,我们将查看容器的生命周期——从诞生,经过工作和休息,到最终的终结。

我们已经看过如何使用docker run命令启动容器。让我们启动另一个容器,以便我们可以跟随其完整的生命周期。

$ docker run --name percy -it ubuntu:latest /bin/bash
root@9cb2d2fd1d65:/#

容器已创建,我们将其命名为“percy”以表示持久。

现在让我们通过向其中写入一些数据来让它工作。

以下步骤将在/tmp目录中写入一些文本到一个新文件,并验证操作是否成功。请务必在刚刚启动的容器内部执行这些命令。

root@9cb2d2fd1d65:/# cd tmp

root@9cb2d2fd1d65:/tmp# ls -l
total 0

root@9cb2d2fd1d65:/tmp# echo "Sunderland is the greatest football team in the world" > newfile

root@9cb2d2fd1d65:/tmp# ls -l
total 4
-rw-r--r-- 1 root root 14 Apr 27 11:22 newfile

root@9cb2d2fd1d65:/tmp# cat newfile
Sunderland is the greatest football team in the world

按下Ctrl-PQ以退出容器而不终止它。

现在使用docker stop命令停止容器并让它度假。它会花费几秒钟的时间,就像是它在旅行到度假地一样。;-)

$ docker stop percy
percy

你可以在docker stop命令中使用容器的名称或ID。格式为docker stop <容器ID或容器名称>

现在运行docker ps以列出所有正在运行的容器。

$ docker ps
CONTAINER ID   IMAGE   COMMAND   CREATED  STATUS  PORTS   NAMES

这个容器在输出中没有列出,因为它处于停止状态。再次运行相同的命令,加上-a标志,以显示所有容器,包括停止的容器。

$ docker ps -a
CNTNR ID  IMAGE          COMMAND    CREATED  STATUS      NAMES
9cb...65  ubuntu:latest  /bin/bash  4 mins   Exited (0)  percy

这次我们可以看到容器显示为Exited (137)。停止容器就像停止虚拟机一样,它不再运行,但是它的整个配置和内容仍然存在于Docker主机上。这意味着它可以随时重新启动。

让我们使用docker start命令将其从休假中带回。

$ docker start percy
percy

$ docker ps
CONTAINER ID  IMAGE          COMMAND      CREATED  STATUS     NAMES
9cb2d2fd1d65  ubuntu:latest  "/bin/bash"  4 mins   Up 7 secs  percy

已停止的容器现在已重新启动。是时候验证我们之前创建的文件是否仍然存在了。使用docker exec命令连接到重新启动的容器。

$ docker exec -it percy bash
root@9cb2d2fd1d65:/#

您的命令提示符将会改变,显示您现在正在容器的命名空间中操作。

验证文件仍然存在,并且其中包含您之前写入的数据。

root@9cb2d2fd1d65:/# cd tmp
root@9cb2d2fd1d65:/# ls -l
-rw-r--r-- 1 root root 14 Sep 13 04:22 newfile

root@9cb2d2fd1d65:/# cat newfile
Sunderland is the greatest football team in the world

就像魔术一样,您创建的文件仍然存在,其中的内容和您之前留下的一样。这证明停止容器并不会销毁容器或其中的数据。

虽然这个示例说明了容器的持久性,但有两点很重要:

此示例中创建的数据存储在Docker主机的本地文件系统中。如果Docker主机发生故障,数据将会丢失。 容器被设计为不可变对象,向其中写入数据不是一个好的做法。 出于这些原因,Docker 提供了卷(volumes)。卷存在于容器之外,但可以挂载到容器中。

在您的学习过程中,这是容器生命周期的一个有效示例,您很难在容器和虚拟机的生命周期之间找到重大差异。

现在让我们终止这个容器并从系统中删除它。

您可以使用单个命令强制删除正在运行的容器。然而,最好先停止它,给应用程序一个正常停止的机会。稍后会详细讨论这一点。

下一个示例将停止percy容器,删除它,并验证操作。如果您的终端仍然连接到percy容器,您需要按下 Ctrl-PQ 来优雅地断开连接。

$ docker stop percy
percy

$ docker rm percy
percy

$ docker ps -a
CONTAINER ID    IMAGE      COMMAND    CREATED  STATUS     PORTS      NAMES

该容器现在已被删除,从地球上彻底消失。如果它是一个好的容器,在下一轮中它将成为一个WebAssembly应用程序。如果它是一个淘气的容器,它将变成一个愚蠢的终端 :-D

总结容器的生命周期。您可以随意停止、启动、暂停和重新启动一个容器。只有在您明确删除它时,您才有可能丢失其数据。即使在这种情况下,如果您在容器外部的卷中存储数据,即使容器消失后,数据也会持续存在。

让我们简要提一下为什么我们建议在删除容器之前先停止它。

优雅停止容器

在之前的示例中,容器正在运行 /bin/bash 应用程序。当您使用 docker rm <container> -f 杀死正在运行的容器时,容器会立即被终止,没有任何警告。您实际上没有给容器和它运行的应用程序任何完成操作和优雅退出的机会。

然而,docker stop 命令更为礼貌。它会给容器内部的进程大约 10 秒的时间来完成任何最终任务并优雅地关闭。一旦命令完成,您可以使用 docker rm 删除容器。

在幕后,docker stop 命令会发送一个 SIGTERM 信号给容器内的主应用程序进程(PID 1)。这是一个终止请求,给予进程一个机会来清理和优雅地关闭自己。如果在 10 秒后仍然运行,将会发出一个 SIGKILL,以强制终止它。

docker rm <container> -f 则没有用 SIGTERM 好好地请求,直接使用 SIGKILL。

使用重启策略实现自愈容器

通常建议使用重启策略来运行容器。这是一种非常基本的自愈机制,允许本地的Docker引擎自动重新启动失败的容器。

重启策略是针对每个容器应用的。可以通过在docker run命令中以命令行方式配置,也可以在YAML文件中声明,以便与更高级的工具(如Docker Swarm、Docker Compose和Kubernetes)一起使用。

在撰写本文时,存在以下几种重启策略:

  1. always
  2. unless-stopped
  3. on-failure

always策略是最简单的。它会始终重新启动一个失败的容器,除非已经明确停止。一个简单的演示方法是,使用--restart always策略启动一个新的交互式容器,并让其运行一个shell进程。当容器启动时,您将自动连接到其shell。从shell中键入exit将终止容器的PID 1进程并杀死容器。然而,由于它具有--restart always策略,Docker会自动重新启动它。如果执行docker ps命令,您会看到容器的运行时间小于它创建后的时间。让我们来测试一下。

$ docker run --name neversaydie -it --restart always alpine sh
/#

在键入exit命令之前等待几秒钟。

一旦退出容器并回到正常的shell提示符,检查容器的状态。

$ docker ps
CONTAINER ID    IMAGE     COMMAND    CREATED           STATUS         NAME
0901afb84439    alpine    "sh"       35 seconds ago    Up 9 seconds   neversaydie

看到容器是在35秒前创建的,但只运行了9秒。这是因为exit命令终止了容器,Docker重新启动了它。需要注意的是,Docker已经重新启动了同一个容器,而不是创建了一个新的容器。事实上,如果使用docker inspect命令检查它,可以看到restartCount已经增加。

--restart always策略的一个有趣特性是,如果您使用docker stop命令停止一个容器,然后重新启动Docker守护程序,该容器将被重新启动。清楚地说...您使用--restart always策略启动一个新容器,然后故意使用docker stop命令停止它。此时容器处于停止(Exited)状态。然而,如果重新启动Docker守护程序,容器将在守护程序重新启动时自动重新启动。您需要注意这一点。

--restart always和--restart unless-stopped策略之间的主要区别在于,具有--restart unless-stopped策略的容器在守护程序重新启动时,如果它们处于停止(Exited)状态,将不会重新启动。这可能是一个令人困惑的句子,让我们通过一个示例来说明。

我们将创建两个新容器。一个名为“always”,具有--restart always策略,另一个名为“unless-stopped”,具有--restart unless-stopped策略。我们将使用docker stop命令将它们都停止,然后重新启动Docker。 "always"容器将重新启动,但"unless-stopped"容器不会重新启动。

  1. 创建这两个新的容器
$ docker run -d --name always \
   --restart always \
   alpine sleep 1d

 $ docker run -d --name unless-stopped \
   --restart unless-stopped \
   alpine sleep 1d

 $ docker ps
 CONTAINER ID   IMAGE     COMMAND       STATUS       NAMES
 3142bd91ecc4   alpine    "sleep 1d"    Up 2 secs    unless-stopped
 4f1b431ac729   alpine    "sleep 1d"    Up 17 secs   always

现在我们有两个正在运行的容器。一个叫做 "always",另一个叫做 "unless-stopped"。 2. 停止这两个容器

$ docker stop always unless-stopped

 $ docker ps -a
 CONTAINER ID   IMAGE     STATUS                        NAMES
 3142bd91ecc4   alpine    Exited (137) 3 seconds ago    unless-stopped
 4f1b431ac729   alpine    Exited (137) 3 seconds ago    always
  1. 重启容器

在不同的操作系统上,重新启动Docker的过程是不同的。以下示例展示了如何在运行systemd的Linux主机上停止Docker。如果要求输入密码,请在命令前面加上sudo再次运行它。

$ systemctl restart docker
  1. Docker 重新启动后,您可以检查容器的状态
$ docker ps -a
 CONTAINER   CREATED             STATUS                       NAMES
 314..cc4    2 minutes ago      Exited (137) 2 minutes ago    unless-stopped
 4f1..729    2 minutes ago      Up 9 seconds                  always

注意,“always”容器(使用--restart always策略启动)已被重新启动,但“unless-stopped”容器(使用--restart unless-stopped策略启动)没有被重新启动。

on-failure策略将在容器退出时以非零退出代码重新启动容器。它还将在Docker守护程序重新启动时重新启动容器,甚至是那些处于停止状态的容器。

如果您正在使用Docker Compose或Docker Stacks,可以将重新启动策略应用于服务对象,如下所示。

services:
  myservice:
    <Snip>
    restart_policy:
      condition: always | unless-stopped | on-failure

Web服务器示例

到目前为止,我们已经学习了如何启动一个简单的容器并与之交互。我们还看到了如何停止、重启和删除容器。现在让我们来看一个基于Linux的Web服务器示例。

在这个示例中,我们将从一个包含在端口8080上运行的简单nodejs应用程序的镜像中启动一个新的容器。

运行docker stop和docker rm命令,以清除之前示例中的任何容器。

运行以下命令以启动一个新的Web服务器容器。

$ docker run -d --name webserver -p 80:8080 \
  nigelpoulton/ddd-book:web0.1

请注意,您的Shell提示符并没有改变。这是因为使用了-d标志在后台启动了容器。像这样在后台启动容器不会将其附加到您的终端。

让我们看一下命令中的一些其他参数。

我们知道docker run会启动一个新的容器。然而,这次我们使用了-d标志而不是-it。-d代表分离或守护进程模式,告诉容器在后台运行。您不能在同一命令中使用-d和-it标志。

接下来,命令给容器命名为“webserver”。-p标志将Docker主机的端口80映射到容器内部的端口8080。这意味着命中Docker主机的端口80的流量将被定向到容器内部的端口8080。我们用于此容器的镜像包含一个在端口8080上侦听的Web服务。这意味着容器将启动一个在端口8080上侦听的Web服务器。

最后,命令告诉容器以nigelpoulton/ddd-book:web0.1镜像为基础。该镜像包含一个node.js Web服务器和所有依赖项。它大约每年维护一次,因此可能包含漏洞!

容器运行后,运行docker ps命令将显示容器正在运行以及映射的端口。重要的是要知道端口映射表示为主机端口:容器端口。

$ docker ps
CONTAINER ID  COMMAND           STATUS       PORTS                 NAMES
b92d95e0b95b  "node ./app.js"   Up 2 mins    0.0.0.0:80->8080/tcp  webserver

为了增加可读性,输出中删除了一些列。

现在容器正在运行且端口已映射,您可以通过将 Web 浏览器指向 Docker 主机的 IP 地址或 DNS 名称的 80 端口来连接它。如果您正在使用 Docker Desktop 在本地运行 Docker,您可以连接到 localhost:80 或 127.0.0.1:80。

图 7.4 显示了容器提供的 Web 页面。

image.png

相同的 docker stop、docker pause、docker start 和 docker rm 命令可用于该容器。

检查容器

在之前的 Web 服务器示例中,您可能注意到我们在执行 docker run 命令时没有指定容器的应用程序。然而,容器运行了一个 Web 服务。这是怎么发生的呢?

在构建 Docker 镜像时,您可以嵌入一个指令,列出使用该镜像的任何容器的默认应用程序。您可以通过运行 docker inspect 查看任何镜像中的这个信息。

$ docker inspect nigelpoulton/ddd-book:web0.1

[
    {
        "Id": "sha256:4b4292644137e5de...fc6d0835089b",
        "RepoTags": [
            "nigelpoulton/ddd-book:web0.1"

            <Snip>

            ],
            "Entrypoint": [
                "node",
                "./app.js"
            ],
<Snip>

为了更容易找到我们感兴趣的信息,输出被截取了。

CmdEntrypoint 之后的条目显示容器将运行的应用程序,除非您在使用 docker run 启动容器时使用不同的应用程序进行了覆盖。

通常在构建镜像时使用这样的默认命令,因为它使得启动容器更加方便。它还强制了默认行为,并且是一种自我文档的形式 — 也就是说,您可以检查镜像并知道它设计为运行哪个应用程序。

至此,我们在本章的示例中完成了。让我们来看一种快速整理系统的方法。

整理系统

让我们来看一下在Docker主机上最简单和最快的清除所有正在运行的容器的方法。但请注意,这个过程将强制销毁所有容器,而不给它们清理的机会。这绝不能在生产系统或运行重要容器的系统上执行。

从您的Docker主机shell中运行以下命令以删除所有容器。它将无需警告即删除所有容器。

$ docker rmi $(docker ps -aq) -f
b92d95e0b95b

这个例子中只有一个容器在运行,所以只有一个被删除。然而,这个命令的工作方式与我们在上一章中使用的"docker rmi (dockerimages−q)"命令相同,用于删除单个Docker主机上的所有镜像。我们已经知道"dockercontainerrm"命令用于删除容器。将"(docker images -q)"命令相同,用于删除单个Docker主机上的所有镜像。我们已经知道"docker container rm"命令用于删除容器。将"(dockerimagesq)"命令相同,用于删除单个Docker主机上的所有镜像。我们已经知道"dockercontainerrm"命令用于删除容器。将"(docker ps -aq)"作为参数传递给它,实际上是将系统上每个容器的ID传递给它。"-f"标志强制执行操作,以便即使是在运行状态下的容器也将被销毁。最终结果是,所有容器,无论是运行还是停止状态,都将被销毁并从系统中删除。

全部评论

相关推荐

科大讯飞消费者bg二级研究院 语音算法岗 24k*14
点赞 评论 收藏
转发
点赞 收藏 评论
分享
牛客网
牛客企业服务