Docker教程

Docker对软件开发生命周期产生了巨大影响,使得大规模软件部署变得简单而且安全。这个教程将介绍运行、启动、停止和删除Docker容器的基础知识。

Docker使得在不同的操作系统上使用不同的编程语言很容易,而所有这些都在同一主机上实现。

在Docker之后部署你的软件变得更加容易,你不必担心错过系统配置或先决条件。

Docker与虚拟机

如果你正使用虚拟运行你的软件,为什么还需要Docker来取代呢?

它们之间的主要区别在于Docker是一个在你的本机操作系统中运行的独立进程,而虚拟机是一个完整的隔离操作系统,它在主机操作系统之上运行,需要更多时间来加载。所以Docker比虚拟机有更多优势,例如:

加载速度与虚拟机不同,所需的硬件资源很少。

在同一操作系统上同时运行多个Docker容器。

你可以修改容器并对其进行部署,或将Docker文件定义提供给朋友,以便在同一环境中工作。

实际上,Docker不是虚拟机的替代品,而是解决特定问题。

假设你的应用程序需要3个或更多在不同操作系统上运行的服务,那么你可以在同一主机上平稳运行3个容器,而不是在同一主机上运行3个虚拟机。听起来很棒!

运行你的容器

在开始之前,请确保已正确安装Docker并准备好接受命令。在新的终端窗口中键入以下命令:

$ docker -v

以上命令输出PC上安装的Docker版本:

Docker version 17.12.0-ce-rc2, build f9cde63

是时候开始运行容器了:

$ docker container run alpine echo "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 alpine echo "Hello World"

运行上述命令的第二,第三或第n次,你应该只在终端中看到此输出:

Hello World

现在你已成功运行容器,现在是时候分析究竟发生了什么。查看以下命令:

$ docker container run alpine echo "Hello World"

该命令包含多个部分。首先,你有“docker”这个词。这是Docker命令行界面(CLI)的名称,用于与负责运行容器的Docker引擎进行交互。

接下来,您有单词“container”,它表示你正在使用的上下文。

再下一步是 实际要执行的命令run。

现在,还需要告诉Docker运行哪个容器。在这里,运行的是 alpine 容器。

最后,需要定义在容器运行时,应在容器内执行的进程或任务类型。这是命令的最后一部分,echo "Hello World"。

在容器内运行进程

既然已经了解了运行容器的命令的各个部分,请尝试在另一个容器中运行不同的进程:

$ docker container run centos ping -c 5 127.0.0.1

输出如下:

Unable to find image 'centos:latest' locally

latest: Pulling from library/centos

85432449fd0f: Pull complete

Digest: sha256:3b1a65e9a05...

Status: Downloaded newer image for centos:latest

PING 127.0.0.1 (127.0.0.1) 56(84) bytes of data.

64 bytes from 127.0.0.1: icmp_seq=1 ttl=64 time=0.022 ms

64 bytes from 127.0.0.1: icmp_seq=2 ttl=64 time=0.019 ms

64 bytes from 127.0.0.1: icmp_seq=3 ttl=64 time=0.029 ms

64 bytes from 127.0.0.1: icmp_seq=4 ttl=64 time=0.030 ms

64 bytes from 127.0.0.1: icmp_seq=5 ttl=64 time=0.029 ms

--- 127.0.0.1 ping statistics ---

5 packets transmitted, 5 received, 0% packet loss, time 4103ms

在前面的示例中,使用的容器镜像是CentOS,并且在CentOS容器内执行的进程是ping -c 5 127.0.0.1,它将环回地址ping五次直到它停止。

第一行如下:

Unable to find image 'centos:latest' locally

这告诉你Docker没有在系统的本地缓存中找到名为centos:latest的镜像。因此,Docker知道它必须从存储容器的某个镜像源中提。

默认情况下,Docker环境配置为从hub.docker.com的Docker Hub中提取镜像。这由第二行表示如下:

latest: Pulling from library/centos

接下来的三行输出如下:

85432449fd0f: Pull completeDigest: 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'; sleep 5; 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'; sleep 5; 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 <container ID>

或者,也可以使用此命令:

$ docker container rm <container name>

有时,无法删除正在运行的容器;如果要强制删除,可以使用命令行参数 -f 或 -force。

容器化改变了行业运行方式,将维护成本降低了50%以上,并将产品上市时间缩短了约90%。此外,相对于容器外运行,容器使应用程序更安全。

如果你发现本教程有用并希望了解有关 Docker 容器的更多信息,可以阅读《Docker 的基础知识 - Docker 18.x 的基础知识[2]》,其中介绍了与容器化和编排相关的所有关键概念。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,732评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,496评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,264评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,807评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,806评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,675评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,029评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,683评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,704评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,666评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,773评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,413评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,016评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,204评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,083评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,503评论 2 343

推荐阅读更多精彩内容

  • Docker基础 这篇基础文章是方便用户在使用cSphere平台之前,了解docker基础知识。针对已经有一定的L...
    威谷子阅读 992评论 0 11
  • 8 Docker教程 大量借鉴https://prakhar.me/docker-curriculum/,以下不做...
    quitus阅读 1,594评论 0 3
  • 疲惫的状态似乎还再持续,调整起来没想象的这么容易,又回到一爬山就大口喘气腿发软的阶段,吃力的爬完两遍,回到家下午睡...
    简单就是豆豆阅读 265评论 0 0
  • 我觉得一本书就是一个世界,所以总是会在读完一本书后,有走过一个世界的感觉。简单说这是我读《从零到一》的阅读笔记与感...
    树屋里藏着秘密阅读 213评论 0 0
  • 如果你选择我,不是因为爱,那我该如何是好?——眼泪啊,你为什么这么不合时宜! “你喜欢他什么?” 是啊,我喜欢你什...
    颜儿511阅读 124评论 0 0