Docker 的镜像与容器

Docker 是基于 linux 内核的 cgroup 和 namespace 等实现的进程隔离技术,是操作系统层面的虚拟化技术。由于进程在宿主机上被分割成独立的空间,就像一个独立的容器将这些进程与外界隔离开来,因此被称为容器。

Docker 容器与传统的虚拟化技术最大的区别在于,传统的虚拟化技术是在宿主机器上虚拟出一套硬件后,在其上面运行完整的操作系统,然后在该系统上运行用户进程,属于硬件层面的虚拟化技术。而 docker 是操作系统层面的虚拟化技术,不需要虚拟化硬件,同一宿主机器上的所有容器共享宿主机的硬件和操作系统内核,只是在用户态隔离进程的运行环境和存储空间,因此对于上层用户而言一个容器就好像是一台独立的主机。下图是 docker 官网上的一张对比图,左边描述的是 docker 容器技术,右边描述的是传统的虚拟机技术。

docker与虚拟机的区别

这个区别使得 docker 相比与传统的虚拟化技术要轻量的多,启动一个虚拟机需要占用几 G 到几十 G 的磁盘空间,需要的时间也是几分钟到十几分钟不等,而启动一个容器只一般只要几十 M 到上百 M,启动的速度更是可以在秒级时间内完成。

Docker 中有三个最重要的概念:镜像、容器和仓库。弄懂这三个概念就可以使用基本的容器了。首先你可以将容器想象成是一台 linux 主机,在这个主机中会启动需要的进程,比如一个 redis 的容器就会启动一个 redis 的服务器。而启动一个容器需要镜像,类似于安装一个 linux 系统需要安装包,你可以想象镜像就是容器的安装包。最后仓库就是存放镜像的地方,方便的是从这个仓库下载镜像只需要一个命令就能搞定,就像 apt-get 安装软件那样方便。

使用镜像

有了镜像才能生成容器,因此我们先来了解镜像。

下载镜像——docker pull

下载镜像使用 docker pull 命令来实现,该命令格式如下:

docker pull [OPTIONS] NAME[:TAG|@DIGEST]
  • 可以通过 docker pull --help 查询帮助信息
  • OPTIONS 中 -a 选项表示拉取所有标签的镜像,-q 选项表示静默下载,不打印输出信息到屏幕
  • NAME 由仓库名/镜像名:标签名的格式组成,仓库名没有则从默认仓库 library 拉取,也就是官方镜像,镜像名必须有,标签名没有则默认拉取 latest 标签的镜像。同一个镜像名的镜像可以有多个标签,一般每更新一个版本就新增一个标签,latest 标签就是最新的镜像。

比如可以这样下载标签为 18.04 的 ubuntu 镜像:

$ docker pull ubuntu:18.04
18.04: Pulling from library/ubuntu
bf5d46315322: Pull complete
9f13e0ac480c: Pull complete
e8988b5b3097: Pull complete
40af181810e7: Pull complete
e6f7c7e5c03e: Pull complete
Digest: sha256:147913621d9cdea08853f6ba9116c2e27a3ceffecf3b492983ae97c3d643fbbe
Status: Downloaded newer image for ubuntu:18.04

列出镜像——docker image ls

docker image ls 命令可以列出系统中已经下载了的所有镜像。docker 中很多命令与 linux 的命令相似,因此在使用的时候可以类比,docker 中有诸如 rm、ls、ps等命令。将了解更多的命令同样可以通过 docker image --help 来查看帮助信息。

$ docker image ls         
REPOSITORY          TAG                 IMAGE ID            CREATED             SIZE
zookeeper           latest              e41846a619f5        17 hours ago        224MB
ubuntu              18.04               cf0f3ca922e0        3 days ago          64.2MB
ubuntu              latest              cf0f3ca922e0        3 days ago          64.2MB
redis               latest              f7302e4ab3a8        2 months ago        98.2MB
hello-world         latest              fce289e99eb9        9 months ago        1.84kB

列表分别包含了仓库名标签镜像ID创建时间镜像大小docker image ls命令展示的是一个完整镜像的大小,但是由于镜像是分层存储的,不同的镜像如果使用了相同的层,这个层只会存储一份数据,所有镜像公用,因此镜像实际占用的空间大小要比显示的小。

删除镜像——docker image rm

docker image rm 命令可以删除镜像,一般配合docker image ls命令来使用。docker image rm命令的使用格式是:

docker image rm [OPTIONS] IMAGE [IMAGE...]
  • 使用 docker image rm --help 可以查看帮助信息
  • OPTIONS: --force/-f 强制删除
  • 镜像可以是镜像名,或者镜像名加标签,或者镜像的ID

比如可以这样删除标签为 latest 的 ubuntu 镜像:

$ docker image rm ubuntu:latest
Untagged: ubuntu:18.04
Untagged: ubuntu@sha256:a7b8b7b33e44b123d7f997bd4d3d0a59fafc63e203d17efedf09ff3f6f516152
Deleted: sha256:cf0f3ca922e08045795f67138b394c7287fbc0f4842ee39244a1a1aaca8c5e1c
Deleted: sha256:c808877c0adcf4ff8dcd2917c5c517dcfc76e9e8a035728fd8f0eae195d11908
Deleted: sha256:cdf75cc6b4d28e72a9931be2a88c6c421ad03cbf984b099916a74f107e6708ff
Deleted: sha256:b9997ded97a1c277d55be0d803cf76ee6e7b2e8235d610de0020a7c84c837b93
Deleted: sha256:a090697502b8d19fbc83afb24d8fb59b01e48bf87763a00ca55cfff42423ad36

Untagged 和 Deleted
在执行 docker image rm 时,出现了两种情况,Untagged 和 Deleted。因为同一个镜像(不只是同名,而是真正意义上的同一个)可以对应多个标签,当执行 rm 命令时先移除这个指定的标签,只有当移除的标签是最后一个标签的时候才会同时删除这个镜像。除此之外,因为镜像是分层存储的,要删除的镜像可能是别的镜像的基础层,如果删除了这个镜像也会导致依赖方出现问题。因此,如果有别的镜像依赖这个镜像,那么这是这个镜像也不会被删除。另外,如果有其他容器依赖于这个镜像,那么也不能删除这个镜像,因为删除这个镜像必然会导致容器出现故障。

操作容器

运行容器——docker run

运行容器有两种方式,一种是新建一个容器并启动,另一种是启动一个已终止的容器。

docker run 命令用来新建一个容器并启动,该命令的使用格式是:

docker run [OPTIONS] IMAGE [COMMAND] [ARG...]

比如下面这个命令会通过 ubuntu 镜像创建并运行一个容器,然后执行 /bin/bash 命令。

$ docker run -it ubuntu /bin/bash

其中常见的命令选项有:

  • -i 选项是让容器标准输入打开,就可以接受键盘输入了
  • -t 选项是让docker分配一个伪终端,绑定到标准输入上。通过这个伪终端就可以像操作一台 linux 机器来操作这个容器了。
  • --name <容器名称> 选项为容器指定一个名称
  • -d 选项让容器在后台运行,什么是后台运行,下文有说明
  • -rm 选项是让容器终止时自动销毁

用这个命令启动一个容器后,就可以像操作一台普通的 ubuntu 机器一样,操作这个容器了。可以尝试在这个容器中执行一些 linux 命令。

root@e7cd5bc73508:/# ps
  PID TTY          TIME CMD
    1 pts/0    00:00:00 bash
   10 pts/0    00:00:00 ps

root@e7cd5bc73508:/# ls
bin  boot  dev  etc  home  lib  lib64  media  mnt  opt  proc  root  run  sbin  srv  sys  tmp  usr  var

需要注意的是,对于这种以交互模式启动的容器,当终止交互后,容器就退出了。

docker container start 可以启动一个终止的容器,该命令的使用格式是:

docker container start [OPTIONS] CONTAINER [CONTAINER...]

要启动一个容器,需要知道容器的ID来作为docker container start的参数,接下来介绍如何查看容器。

查询容器状态——docker container ls

docker container ls 列出所有正在运行的容器

docker container ls -a 列出所有的容器,包括已经终止的容器

列出的容器信息包括:

  • 容器ID(CONTAINER ID),这是容器的唯一标识,操作容器相关的命令都需要带上这个标识
  • 依赖的镜像名称(IMAGE)
  • 执行的命令(COMMAND)
  • 创建的时间(CREATED)
  • 容器的状态(STATUS),UP 是运行状态,Exited 是终止状态
  • 暴露的端口(PORTS)
  • 容器的名称(NAMES),可以在启动容器的时候通过 --name 选项指定容器的名称,如果没有指定,系统会生成一个默认名称

终止容器——docker container stop

docker container stop 命令用来终止一个正在运行的容器

终止的容器可以通过 docker container start 命令启动,docker container restart 命令会先终止容器,然后再启动容器。

守护态运行

大多数时候需要容器在后台运行,不需要将输出结果打印到宿主主机上。此时,可以通过 -d 参数来实现。

不使用 -d 选项启动下面这个容器,表现如下:

$ docker run ubuntu /bin/bash -c "while true; do echo hello world; sleep 1; done"
hello world
hello world
hello world
hello world
hello world

使用 -d 选项启动这个容器,表现如下:

$ docker run -d ubuntu /bin/bash -c "while true; do echo hello world; sleep 1; done"
574ee145e9ca501639a233601efe9574a356a8d7bdef461d240b2212b6aeaf77

在宿主的终端只输出了该容器的 ID。如果需要查看容器的输出可以使用 docker container logs 命令。本文在说容器的这些命令时都省略了最后一个参数容器 ID,这个读者在使用的时候需要自行加上,查询容器 ID 的方法前面已经介绍过了。如果想要持续获取容器的输出可以使用 docker container logs -f 命令。

进入容器

使用 -d 参数启动容器后,容器在后台运行,如果需要进入容器可以使用 docker attach 命令或 docker exec 命令。建议使用 docker exec 命令,原因在下面进行说明。

docker attach

$ docker run -it -d ubuntu
2b10efdeaa9f0f24f0060bf636cc8f1bae9598f5e0176b498447a7b63ea10d06

$ docker container ls
CONTAINER ID    IMAGE     COMMAND       CREATED             STATUS              PORTS          NAMES
2b10efdeaa9f    ubuntu    "/bin/bash"   13 seconds ago      Up 11 seconds                      cocky_golick

$ docker attach 2b10efdeaa9f
root@2b10efdeaa9f:/# 

使用 attach 命令,如果从这个终端退出后,这个容器也会被终止,这就是不推荐使用 attach 命令的原因。

docker exec

$ docker run -it -d ubuntu
61299a9b910b029f9a8667131a45aff92fbc35633e4f86c8fcfb72e6362c5115

$ docker container ls
CONTAINER ID        IMAGE      COMMAND         CREATED             STATUS          PORTS           NAMES
61299a9b910b        ubuntu     "/bin/bash"     6 seconds ago       Up 5 seconds                    friendly_hawking

$ docker exec -it 61299a9b910b /bin/bash

使用 exec 命令,可以生成新的伪终端与容器进行交互,因此退出时不会导致容器退出。

删除容器

docker container rm 命令可以删除一个容器,如果要删除一个正在运行的容器可以使用docker container rm -f

如果要清除所有终止的容器可以使用 docker container prune 命令。

访问仓库

  • docker login 登录到docker hub仓库
  • docker logout 退出登录
  • docker search <关键词> 搜索镜像
  • docker pull 从仓库下载镜像
  • docker push 将本地仓库推送到远程仓库

下面演示一下这些命令的使用:

$ docker login
Login with your Docker ID to push and pull images from Docker Hub. If you don't have a Docker ID, head over to https://hub.docker.com to create one.
Username: xxx
Password: xxx
WARNING! Your password will be stored unencrypted in /root/.docker/config.json.
Configure a credential helper to remove this warning. See
https://docs.docker.com/engine/reference/commandline/login/#credentials-store

Login Succeeded

$ docker pull hello-world

# 为镜像 hello-world 生成一个新的标签,而且指定仓库为自己仓库的用户名
$ docker tag hello-world:latest oscarwin/hello-world:3.0

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

推荐阅读更多精彩内容