Docker 容器与镜像管理
查看系统信息
docker info
docker system info
帮助:
docker -h
我们可以看到运行结果如下图所示。如果之前有学习过 docker 相关知识的同学,可能会发现一些不一样的地方。即下图中标出的 Management commands 和 Commands。在 1.13 版本之前,docker 并没有 Mangement commands。
在 Docker 1.12 CLI 中大约有四十个左右的顶级命令,这些命令没有经过任何组织,显得十分混乱,对于新手来说,学习它们并不轻松。
而在 Docker 1.13 中将命令进行分组,就得到如上图中所示的 Management Commands。例如经常使用的容器的一些相关命令:
# 创建一个新的容器,下面分别为 Commands 和 Management Commands,作用相同
docker create
docker container create
# 显示容器列表
docker ps
docker container ls
# 在一个新的容器中运行一个命令
docker run
docker container run
...
如上所示,对于新的命令而言相比于旧命令明显更具有可读性。并且在实验环境中的 docker 版本以及最新版本中两者都是有效的命令,所以在这里我们将一些常用的命令,及其对应的 Management Commands 命令都列举出来,方便大家在后续的学习过程中可以进行参考。
docker-commands.png查看容器列表可以使用如下命令:
docker container ls [OPTIONS]
或者旧的命令
docker ps [OPTIONS]
在使用命令时,我们可以使用一些可选的配置项 [OPTIONS]
。
-
-a
显示所有的容器 -
-q
仅显示ID
-
-s
显示总的文件大小
这些配置项对于上述的两个命令都是有效的,在后面的内容不会再特殊说明。
默认情况下,直接使用该命令仅显示正在运行的容器,如下所示:
$ docker container ls
此处输入图片的描述
此时并没有处于运行中的容器,所以显示为空。我们可以使用 -a
参数,来显示所有的容器,并加上 -s
选项,显示大小,命令如下:
$ docker container ls -a -s
容器
#显示运行的容器
docker ps
docker container ls
# 显示所有容器
docker ps -a
# 显示容器id
docker ps -aq
# 显示容器大小
docker ps -a -s
docker container ls -as
docker run
首先,我们回顾在上一节使用到的 docker run hello-world 命令,该命令的格式为:
docker run [OPTIONS] IMAGE [COMMAND]
对应于 Management Commands 的命令为:
docker container run [OPTIONS] IMAGE [COMMAND]
上述两个命令的作用相同,docker run 命令会在指定的镜像 IMAGE 上创建一个可写的容器(因为镜像是只读的),然后开始运行指定的命令 [COMMAND]。
一些常用的配置项为:
-i 或 --interactive, 交互模式
-t 或 --tty, 分配一个 pseudo-TTY,即伪终端
--rm 在容器退出后自动移除
-p 将容器的端口映射到主机
-v 或 --volume, 指定数据卷
对于指定镜像而言,首先会在本地查找,找不到时将从镜像仓库中下载
镜像下载完成后,通过镜像启动容器,并运行 echo "hello shiyanlou" 命令,输出运行结果之后退出。
在执行命令之后,容器就会退出,如果我们需要一个保持运行的容器,最简单的方法就是给这个容器一个可以保持运行的命令或者应用,比如 bash,例如我们在 ubunutu 容器中运行 /bin/bash 命令:
$ docker container run -i -t ubuntu /bin/bash
对于交互式的进程而言(例如这里的 bash),必须将 -i 和 -t 参数一起使用,才能为容器进程分配一个伪终端,通常我们会直接使用 -it。
退出伪终端方式:
-
直接使用 exit 命令,这时候 bash 程序终止,容器进入到停止状态
-
使用组合键退出,容器仍然保持运行的状态,可以再次连接到这个 bash 中,组合键是 ctrl + p 和 ctrl +q。即先同时按下 ctrl 和 p 键,再同时按 ctrl 和 q 键。就可以退出
#重新登入容器伪终端
docker attach <container_id>
docker run
首先,我们回顾在上一节使用到的 docker run hello-world
命令,该命令的格式为:
docker run [OPTIONS] IMAGE [COMMAND]
对应于 Management Commands
的命令为:
docker container run [OPTIONS] IMAGE [COMMAND]
上述两个命令的作用相同,docker run
命令会在指定的镜像 IMAGE
上创建一个可写的容器(因为镜像是只读的),然后开始运行指定的命令 [COMMAND]
。
一些常用的配置项为:
-
-i
或--interactive
, 交互模式 -
-t
或--tty
, 分配一个pseudo-TTY
,即伪终端 -
--rm
在容器退出后自动移除 -
-p
将容器的端口映射到主机 -
-v
或--volume
, 指定数据卷
关于该命令的详细参数较多,并且大多数参数在很多命令中的意义是相同的,将在后面的内容中使用到时进行相应的介绍。
我们指定 busybox
镜像,然后运行命令 echo "hello shiyanlou"
命令,如下所示:
$ docker container run busybox echo "hello shiyanlou"
此处输入图片的描述
在上图中,我们可以看到该命令执行的过程:
-
对于指定镜像而言,首先会在本地查找,找不到时将从镜像仓库中下载
-
镜像下载完成后,通过镜像启动容器,并运行
echo "hello shiyanlou"
命令,输出运行结果之后退出。
在执行命令之后,容器就会退出,如果我们需要一个保持运行的容器,最简单的方法就是给这个容器一个可以保持运行的命令或者应用,比如 bash
,例如我们在 ubunutu
容器中运行 /bin/bash
命令:
$ docker container run -i -t ubuntu /bin/bash
对于交互式的进程而言(例如这里的 bash),必须将 -i
和 -t
参数一起使用,才能为容器进程分配一个伪终端,通常我们会直接使用 -it
。
如上所示,我们已经进入到分配的终端中了,这时如果我们需要退出 bash
,可以使用以下两种方式,它们的效果完全不同:
-
直接使用
exit
命令,这时候bash
程序终止,容器进入到停止状态 -
使用组合键退出,容器仍然保持运行的状态,可以再次连接到这个
bash
中,组合键是ctrl + p
和ctrl +q
。即先同时按下ctrl
和p
键,再同时按ctrl
和q
键。就可以退出
这里我们使用第二种方式,然后使用 docker container ls
命令,可以看到该容器仍然处于运行中。
docker container create
严格意义上来讲,docker run
命令的作用并不是创建一个容器,而是在一个新的容器中运行一个命令。而用于创建一个新容器的命令为
docker container create [OPTIONS] IMAGE [COMMAND] [ARG...]
或者使用旧的
docker create [OPTIONS] IMAGE [COMMAND] [ARG...]
该命令会在指定的镜像 IMAGE
上创建一个可写容器层,并 准备 运行指定的命令。需要着重强调的是,这里是准备运行,并不是立即运行。即该命令只创建容器,并不会运行容器。
一些常见的配置项如下所示:
-
--name
指定一个容器名称,未指定时,会随机产生一个名字。 -
--hostname
设置容器的主机名 -
--mac-address
设置MAC
地址 -
--ulimit
设置 Ulimit 选项。
关于上述提到的
ulimit
,我们可以通过其对容器运行时的一些资源进行限制。ulimit
是一种linux
系统的内建功能,一些简单的描述,可以参考 https://www.ibm.com/developerworks/cn/linux/l-cn-ulimit/ ,而对于在下面我们将要设置的部分值的含义,可以参考https://access.redhat.com/solutions/61334 。
除此之外,关于创建容器,我们还可以设置有关存储和网络的详细内容,将会在下一节的内容中进行介绍。
如下示例,我们指定容器的名字为 shiyanlou
,主机名为 shiyanlou
,设置相应的 MAC
地址,并通过 ulimit
设置最大进程数(1024:2048
分别代表软硬资源限制,详细内容可以参考上面的链接),使用 ubuntu
的镜像,并运行 bash
:
$ docker container create --name shiyanlou --hostname shiyanlou --mac-address 00:01:02:03:04:05 --ulimit nproc=1024:2048 -it ubuntu /bin/bash
此处输入图片的描述
此时,容器创建成功后,会打印该容器的 ID
,这里需要简单说明一下,在 docker
中,容器的标识有三种比较常见的标识方式:
-
UUID
长标识符,例如1f6789f885029dbdd4a6426d7b950996a5bcc1ccec9f8185240313aa1badeaff
-
UUID
短标识符,从长标识符开始,只要不与其它标识符冲突,可以从头开始,任意选用位数,例如针对上面的长标识符,可以使用1f
,1f678
等等 -
Name
最后一种方式即是使用容器的名字
在容器创建成功后,我们可以查看其运行状态,使用如下命令:
# 此时该容器并未运行,需要使用 -a 参数
$ docker container ls -a
此处输入图片的描述
新创建的容器的状态 (STATUS
) 为 Created
,并且其容器名被设置为对应的值
查看容器的详细信息可以使用如下命令:
docker container inspect [OPTIONS] CONTAINER [CONTAINER...]
或者旧的
docker inspect [OPTIONS] CONTAINER [CONTAINER...]
例如我们查看刚刚创建的容器的详细信息就可以使用以下命令:
# 使用容器名
$ docker container inspect shiyanlou
# 使用 ID ,因生成的 ID 不同,需要修改为相应的 ID
$ docker container inspect 1f6789
$ docker container inspect 1f6
例如,我们查看刚刚创建的名为 shiyanlou
的容器的 MAC
地址,就可以使用如下命令:
$ docker container inspect shiyanlou | grep "00:01"
此处输入图片的描述
docker run 实际是通过镜像 新创建一个容器然后执行命令
docker create 单纯根据镜像创建容器
docker stat <container_name>
实时显示容器状况
容器的启动命令为:
docker container start [OPTIONS] CONTAINER [CONTAINER...]
对于上面我们创建的容器而言,此时处于 Created
状态,需要使用如下命令启动它:
$ docker container start shiyanlou
此处输入图片的描述
此时,运行一个容器我们分成了两个步骤,即创建和启动,使用的命令如下:
# 创建
$ docker container create --name shiyanlou --hostname shiyanlou --mac-address 00:01:02:03:04:05 --ulimit nproc=1024:2048 -it ubuntu /bin/bash
# 启动
$ docker container start shiyanlou
上述的两个命令如果我们使用 docker container run
只需要一步即可,即此时 run
命令同时完成了 create
及 start
操作:
$ docker container run --name shiyanlou --hostname shiyanlou --mac-address 00:01:02:03:04:05 --ulimit nproc=1024:2048 -it ubuntu /bin/bash
除此之外,上面的
run
命令还完成一些其它的操作,例如没有镜像时会pull
镜像,使用-it
参数时完成了attach
操作(后面会学习该操作),使用--rm
参数在容器退出后还会完成container rm
操作。
run
命令是一个综合性的命令,如果能够熟练的使用它可以简化很多步骤,但是其使用方式较为复杂
启动之后,暂停容器可以使用如下命令:
# 暂停一个或多个容器
docker container stop [OPTIONS] CONTAINER [CONTAINER...]
# 暂停一个或多个容器中的所有进程
docker container pause CONTAINER [CONTAINER...]
上述两个命令的区别在于一个是暂停容器中的进程,而另外一个是暂停容器,例如,我们使用 stop
停止刚刚启动的容器就可以使用如下命令:
$ docker container stop shiyanlou
# 查看容器的状态
$ docker container ls -a
此处输入图片的描述
如上图所示,容器被暂停后,此时处于 Exited
状态。
注意 docker attach 后 需要敲一次回车才有输出
docker pause / unpause 暂停/恢复 容器内所有进程
除了上面介绍的一些命令之外,还有很多其它的命令,下面简单描述
获取日志
获取容器的输出信息可以使用如下命令:
docker container logs [OPTIONS] CONTAINER
常用的配置项有:
-
-t
或--timestamps
显示时间戳 -
-f
实时输出,类似于tail -f
如下所示,我们查看刚刚创建的容器的日志,使用如下命令:
$ docker container logs -tf shiyanlou
显示进程
除了获取日志之外,还可以显示运行中的容器的进程信息,例如查看刚刚创建的容器的进程信息:
$ docker container top shiyanlou
此处输入图片的描述
需要注意的是,该命令对于并未运行的容器是无效的
查看修改
查看相对于镜像的文件系统来说,容器中做了哪些改变,可以使用如下命令:
docker container diff shiyanlou
例如我们在 shiyanlou
容器中创建一个文件,就可以使用 diff
命令查看到相应的修改:
[图片上传中...(image-800183-1533115979338-1)]
重启
重启容器可以使用如下命令:
docker container restart shiyanlou
执行命令
除了使用 docker container run
来创建容器并在容器里执行命令之外,我们还可以在一个已经处于运行中的容器中执行命令,使用如下格式:
docker container exec [OPTIONS] CONTAINER COMMAND [ARG...]
例如,我们在刚刚创建的容器中执行 echo "test_exec"
命令,就可以使用如下命令:
$ docker container exec shiyanlou echo "test_exec"
此处输入图片的描述
删除容器
删除容器的命令:
docker container rm [OPTIONS] CONTAINER [CONTAINER...]
需要注意的是,在删除容器后,在容器中进行的操作并不会持久化到镜像中
镜像仓库Repository
镜像仓库(Repository)用于存放镜像,每个仓库都有其唯一地址,类似于网址。镜像仓库需要托管在某个 Registry,Registry 的作用类似于 GitHub。Docker 提供了一个官方的 Registry,官方 Registry 里的镜像仓库地址可以省去前面的域名前缀,其它 Registry 里的镜像仓库地址必须要指定域名前缀,以保证唯一性。
镜像仓库地址后面可以跟一个 TAG。比如一个镜像名称 ubuntu:14.04
,冒号前面的 ubuntu
是镜像仓库地址(由于是官方 Registry 里的,可以省略域名前缀),后面的 14.04
是 TAG,TAG 通常设置为镜像的版本号。
Docker
镜像是分层存储的,每一个镜像都由多层组成。镜像之间会共享一些相同的层,从而可以减小所有镜像占用的存储空间。对于实验环境中的 docker
来说,其使用的存储驱动是 aufs
,如下图所示:
aufs
是一种联合文件系统(UnionFS),理解其原理对于我们理解 Docker 镜像比较有帮助,有兴趣的同学可以学习 Linux 文件系统之 aufs。
docker images
docker image ls
docker image ls ubuntu
查看镜像信息
docker inspect ubuntu
从仓库中拉取镜像的命令如下:
docker pull [OPTIONS] NAME[:TAG|@DIGEST]
比较常用的配置参数为 -a
,代表下载仓库中所有 TAG 的镜像,默认只下载 latest
TAG 的镜像。
如果要下载 ubuntu:14.04
镜像,可使用如下命令:
$ docker image pull ubuntu:14.04
此处输入图片的描述
对于 pull
下来的镜像,具体的保存路径为 /var/lib/docker
。
commit
此时,对于我们 pull
的新镜像 ubuntu:14.04
来说,如果我们需要对其进行更新,可以创建一个容器,在容器中进行修改,然后将修改提交到一个新的镜像中。
提交修改使用如下命令:
docker container commit [OPTIONS] CONTAINER [REPOSITORY[:TAG]]
该命令从一个修改过的容器创建一个新的镜像。例如,我们运行一个容器,然后在其中创建一个文件,最后使用 commit
命令:
# 使用 run 创建运行一个新命令
$ docker container run -it --name shiyanlou001 busybox /bin/sh
# 在运行的容器中创建两个文件,test1 和 test2
touch test1 test2
# 使用 ctrl + p 及 ctrl+q 键退出
# 使用提交命令,提交容器 shiyanlou001 的修改到镜像 busybox:test 中
$ docker container commit shiyanlou001 busybox:test
# 查看通过提交创建的镜像
$ docker image ls busybox
此处输入图片的描述
通过上述操作我们创建了一个新的镜像,但是本方法不推荐在生产环境使用,因为这种方式的可维护性很差。推荐的创建镜像的方法是使用
Dockerfile
,修改镜像可通过修改Dockerfile
,然后使用新的Dockerfile
来构建新的镜像。
BUILD
docker
可以从一个 Dockerfile
文件中读取指令来构建镜像。 Dockerfile
是一个包含用户构建镜像所需命令的文本文件。在 创建好该文件后,我们可以使用如下命令来构建镜像:
docker image build [OPTIONS] PATH | URL
构建镜像的第一件事是将
Dockerfile
文件所在目录下的所有内容发送给 Docker 守护进程。所以最好创建一个新的目录,在其中保存Dockerfile
,并在其中添加构建镜像所需的其它文件。
对于一个 Dockerfile
文件内容来说,基本语法格式如下所示:
# Comment
INSTRUCTION arguments
使用 #
号作为注释,指令(INSTRUCTION
)不区分大小写,但是为了可读性,一般将其大写。Dockerfile
中的指令一般包含下面几个部分:
-
基础镜像:以哪个镜像为基础进行制作,使用
FROM
指令来指定基础镜像,一个Dockerfile
必须以FROM
指令启动。 -
维护者信息:可以指定该
Dockerfile
编写人的姓名及邮箱,使用MAINTAINER
指令。 -
镜像操作命令:对基础镜像进行修改的命令,比如安装新的软件,进行配置等,常见的是
RUN
命令。 -
容器启动命令:基于该镜像的容器启动时需要执行的命令,常见的是
CMD
命令或ENTRYPOINT
下面是一个最基本的 Dockerfile
:
# 指定基础镜像
FROM ubuntu:14.04
# 维护者信息
MAINTAINER shiyanlou/shiyanlou001@simplecloud.cn
# 镜像操作命令
RUN apt-get -yqq update && apt-get install -yqq apache2
# 容器启动命令
CMD ["/usr/sbin/apache2ctl", "-D", "FOREGROUND"]
通过阅读上述内容中我们熟悉的一些 linux
指令,可以很容易的知道该 Dockerfile
将创建一个 apache
镜像。
其中 FROM
指定基础镜像。RUN
命令默认使用 /bin/sh
,并使用 root
权限执行。CMD
命令也是默认在 /bin/sh
中执行,但是只能有一条 CMD
指令,如果有多条则只有最后一条会被执行。
下面我们创建一个空目录,在其中编辑 Dockerfile
文件,然后基于此文件构建一个新的镜像:
# 首先创建目录并切换目录
$ mkdir /home/shiyanlou/test1 && cd /home/shiyanlou/test1
# 编辑 Dockerfile 文件,默认文件名为 `Dockerfile`,也可以使用其它值,使用其它值需要在构建时通过 `-f` 参数指定,这里我们使用默认值。并在其中添加上述示例的内容
$ vim Dockerfile
# 使用 build 命令,`-t` 参数指定新的镜像
$ docker image build -t shiyanlou:1.0 .
此处输入图片的描述
在执行构建命令后,需要花费一些时间来完成构建。在运行结束后,最后查看新创建的镜像:
此处输入图片的描述在构建完成后,我们可以使用该镜像启动一个容器来运行 apache
服务,运行如下命令:
# 使用 -p 参数将本机的 8000 端口映射到容器中的 80 端口上。
$ docker container run -d -p 8000:80 --name shiyanlou002 shiyanlou:1.0
此处输入图片的描述
此时,容器启动成功后,并且配置了端口映射,我们就可以通过本机的 8000
端口访问容器 shiyanlou002
中的 apache
服务了。我们打开浏览器,输入 localhost:8000
,显示结果如下图:
更多有关于 Dockerfile 文件格式的信息可以参考官方文档 https://docs.docker.com/engine/reference/builder/