它们之间的主要区别在于Docker是一个在你的本机操作系统中运行的独立进程,而虚拟机是一个完整的隔离操作系统,它在主机操作系统之上运行,需要更多时间来加载。所以Docker比虚拟机有更多优势,例如:
加载速度与虚拟机不同,所需的硬件资源很少。
在同一操作系统上同时运行多个Docker容器。
你可以修改容器并对其进行部署,或将Docker文件定义提供给朋友,以便在同一环境中工作。
实际上,Docker不是虚拟机的替代品,而是解决特定问题。
假设你的应用程序需要3个或更多在不同操作系统上运行的服务,那么你可以在同一主机上平稳运行3个容器,而不是在同一主机上运行3个虚拟机。听起来很棒!
运行你的容器
在开始之前,请确保已正确安装Docker并准备好接受命令。在新的终端窗口中键入以下命令:
$ docker -v
以上命令输出PC上安装的Docker版本:
Dockerversion17.12.0-ce-rc2,buildf9cde63
是时候开始运行容器了:
$docker container run alpineecho"Hello World"
当您第一次运行上述命令时,你应该在终端窗口中看到与此类似的输出:
Unable to find image 'alpine:latest' locally
latest: Pulling from library/alpine
2fdfe1cd78c2: Pull complete
Digest: sha256:ccba511b...
Status: Downloaded newer image for alpine:latest
Hello World
这很容易,不是吗?尝试再次运行相同的命令:
$docker container run alpineecho"Hello World"
运行上述命令的第二,第三或第n次,你应该只在终端中看到此输出:
HelloWorld
现在你已成功运行容器,现在是时候分析究竟发生了什么。查看以下命令:
$docker container run alpineecho"Hello World"
该命令包含多个部分。首先,你有“docker”这个词。这是Docker命令行界面(CLI)的名称,用于与负责运行容器的Docker引擎进行交互。
接下来,您有单词“container”,它表示你正在使用的上下文。
再下一步是 实际要执行的命令run。
现在,还需要告诉Docker运行哪个容器。在这里,运行的是 alpine 容器。
最后,需要定义在容器运行时,应在容器内执行的进程或任务类型。这是命令的最后一部分,echo "Hello World"。
在容器内运行进程
既然已经了解了运行容器的命令的各个部分,请尝试在另一个容器中运行不同的进程:
$ docker container run centos ping -c5127.0.0.1
输出如下:
Unableto find image'centos:latest'locally
latest: Pulling from library/centos
85432449fd0f: Pull complete
Digest: sha256:3b1a65e9a05...
Status: Downloaded newer image for centos:latest
PING127.0.0.1(127.0.0.1)56(84) bytes of data.
64bytes from127.0.0.1: icmp_seq=1ttl=64time=0.022ms
64bytes from127.0.0.1: icmp_seq=2ttl=64time=0.019ms
64bytes from127.0.0.1: icmp_seq=3ttl=64time=0.029ms
64bytes from127.0.0.1: icmp_seq=4ttl=64time=0.030ms
64bytes from127.0.0.1: icmp_seq=5ttl=64time=0.029ms
---127.0.0.1ping statistics ---
5packets transmitted,5received,0% packet loss, time4103ms
在前面的示例中,使用的容器镜像是CentOS,并且在CentOS容器内执行的进程是ping -c 5 127.0.0.1,它将环回地址ping五次直到它停止。
第一行如下:
Unableto find image'centos:latest'locally
这告诉你Docker没有在系统的本地缓存中找到名为centos:latest的镜像。因此,Docker知道它必须从存储容器的某个镜像源中提。
默认情况下,Docker环境配置为从hub.docker.com的Docker Hub中提取镜像。这由第二行表示如下:
latest: Pullingfromlibrary/centos
接下来的三行输出如下:
85432449fd0f:PullcompleteDigest:sha256:3b1a65e9a05...Status:
这告诉您Docker已成功从Docker Hub中提取了镜像centos:latest。
后续的输出都是由容器内运行的进程生成的,这里运行的是ping工具。
你可能还注意到latest这个关键字出现了几次。每个映像都有一个版本(也称为标记),如果没有明确指定版本,则Docker会自动其视为最新版本。
如果在系统上再次运行这个容器,将不会输出之前的五行,因为Docker将在本地缓存容器映像,因此不必先下载它。试试是不是这样。
运行一个随机引用容器
为了运行随机语句容器,需要一个生成随机语句的算法。可以在此处[1]找到生成这些随机语句的API。
现在的目标是要在容器内运行一个进程,每5秒生成一条随机语句,并且输出到STDOUT:
while:
do
wget -qO- https://talaikis.com/api/quotes/random
printf'n'
sleep 5
done
按Ctrl + C停止脚本。这是输出:
{"quote":"Martha Stewart is extremely talented. Her designs are picture perfect. Our philosophy is life is messy, and rather than being afraid of those messes we design products that work the way we live.","author":"Kathy Ireland","cat":"design"}{"quote":"We can reach our potential, but to do so, we must reach within ourselves. We must summon the strength, the will, and the faith to move forward - to be bold - to invest in our future.","author":"John Hoeven","cat":"faith"}
每个响应都是一个JSON格式的字符串,包含引号,作者及其类别。
现在,让这个容器后台运行。为此,需要将前面的脚本缩成一行,并使用 /bin/sh -c “…” 来执行。Docker 的表达式如下:
$ docker container run -d --name quotes alpine \/bin/sh -c "while :; do wget -qO- https://talaikis.com/api/quotes/random; printf'\n'; sleep5; done"
上面的表达式,你使用了两个命令行参数,-d 和--name。-d告诉Docker以一个Linux守护进程的方式运行容器。-name参数用于为容器指定显式名称。
如果您未指定显式容器名称,Docker将自动为容器分配一个随机但唯一的名称。这个名字将由一位着名科学家的名字和一个形容词组成。
诸如,“boring_borg”或“angry_goldberg”。相当幽默,不是吗?
一个重要的方面是容器名称必须是唯一的。确保引号容器已启动并正在运行:
$ docker container ls -l
前面输出的重要部分是STATUS列,此例中,它显示UP 16 seconds。这意味着容器已经启动并运行了16秒。
随着时间的推移继续运行容器,你的系统也许会产生很多容器。要查找主机上当前正在运行的容器,可以使用container ls命令,如下所示:
$ docker container ls
这将列出所有当前运行的容器。
默认情况下,Docker输出七列,含义如下:
列描述
Container ID唯一的容器 ID 。它是SHA-256.
Image所以用的镜像
Status容器的状态(created,restarting,running,removing,paused,exited,or dead)
Ports映射到宿主机的端口
Names分配到容器的名字 (可以是多个名字的)
如果要列出系统上定义的所有容器,可以使用命令行参数 -a 或 -all,如下所示:
$ docker container ls -a
这将列出任何状态的容器,无论是创建,运行还是退出。
有时,可能只想列出所有容器的ID。为此,你有 -q 参数:
$ docker container ls -q
你可能想知道这有什么用。这里有个例子:
$ docker container rm -f $(docker container ls -a -q)
上面的命令删除当前在系统上定义的所有容器,包括已停止的容器。rm命令代表删除,将在本教程中进一步解释。
在上一节中,您在list命令中使用了-l参数。尝试使用Docker帮助找出-l参数代表什么。您可以为list命令调用help,如下所示:
$ docker container ls -h
停止和启动容器
有时,你可能需要暂时停止正在运行的容器。试试以下这个容器:
$ docker container run -d --name quotes alpine \/bin/sh -c "while :; do wget -qO- https://talaikis.com/api/quotes/random; printf'\n'; sleep5; done"
现在,你可以使用以下命令停止此容器:
$ docker container stop quotes
当你尝试暂停容器时,可能会注意到它需要一段时间(大约10秒)才能执行完成。为什么会这样? Docker将 Linux SIGTERM信号发送到容器内运行的主进程。
在上面的命令中,容器的名称用于指定要停止的容器。也可以使用容器ID。
你如何获得容器ID?
有几种方法可以做到这一点。手动方法是列出所有正在运行的容器,并在列表中找到您要查找的容器。只需从那里复制其ID。
更自动化的方法是使用shell脚本和环境变量。例如,如果要获取引号容器的ID,这是一个示例:
$ export CONTAINER_ID = $(docker container ls| grep quotes |awk'{print $1}')
这里我们使用AWK获取第一个字段,即容器ID。现在,您可以在表达式中使用$CONTAINER_ID变量,而不是使用容器名称:
$ docker container stop $CONTAINER_ID
一旦停止容器后,其状态将更改为“已退出”。
你可以使用docker container start命令重新启动已停止的容器。
移除容器
运行docker container ls -a命令时,您可以看到很多处于“已退出”状态的容器。
如果您不再需要这些容器,最好将它们从内存中删除;否则,他们会占用宝贵的资源。删除容器的命令如下:
$ docker container rm
或者,也可以使用此命令:
$ docker container rm
有时,无法删除正在运行的容器;如果要强制删除,可以使用命令行参数 -f 或 -force。
容器化改变了行业运行方式,将维护成本降低了50%以上,并将产品上市时间缩短了约90%。此外,相对于容器外运行,容器使应用程序更安全。
如果你发现本教程有用并希望了解有关 Docker 容器的更多信息,可以阅读《Docker 的基础知识 - Docker 18.x 的基础知识[2]》,其中介绍了与容器化和编排相关的所有关键概念。
相关链接:
https://talaikis.com/random_quotes_api/
https://amzn.to/2LgQZmN