Datawhale-Docker学习笔记-0002-镜像与容器

镜像

什么是镜像

如果大家使用过虚拟机模板,就可以很好的理解Docker的镜像其实和VM的模板很类似。其实镜像并没有那么复杂,我们可以把镜像和容器放在一起理解。容器时一组正在运行的OS和应用的集合,而镜像我们可以理解为容器再某一时刻的快照。就像照片一样,镜像是静止的,而容器是动态的,正在运行的。这就是两者的区别。

镜像的操作

镜像的获取

我们有时如果不想自己配置环境的话,可以直接从Docker Hub上下载别人已经配置好的环境。这个过程就是镜像的获取。

$ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]

我们可以直接使用docker pull命令来拉取镜像。
例如:

docker pull ubuntu:latest

如果不指定地址的话,我们一般默认是从Docker hub中拉取镜像。同时,我们还可以在命令中看到我们在仓库名ubuntu后面使用的是":latest",这是因为在一个仓库中,往往有很多版本的同名镜像,我们需要在这个位置指定镜像的标签,也可以理解为版本。
我们可以稍微了解一下镜像的命名规则。首先是镜像仓库,镜像仓库分为两类,有官方仓库和非官方仓库。往往我们在使用非官方的仓库时需要保持谨慎。而在官方的镜像库中,我们只要有了名字和标签就可以唯一的确定一个镜像。命令如下:

docker image pull <repository>:<tag>

如果我们没有在后面指明tag的话,则默认是下载latest版本。顾名思义,我们一般会认为latest是仓库的最新镜像,但是,latest并不一定是最新的镜像。例如Alpine仓库中的最新的镜像一般为edge,所以我们在使用latest标签的时候一定要谨慎。
而如果想要从非官方的仓库下载镜像的话,我们则需要首先确定镜像仓库的地址,一般为<域名/IP地址>[:端口号]。这一部分在官方仓库的话则是docker.io。然后是用户名,在官方镜像库中则默认为library。然后才是镜像名和标签。所以一个完整的指令的话,应该如下:

docker image pull docker.io/library/ubuntu:latest

需要注意的点是,通常情况下,我们在国内使用Docker从Docker Hub下载镜像的话是十分缓慢的。所以我们可以使用国内的镜像库,比如清华的镜像库或者阿里云的镜像库,这样可以加速镜像的下载速度。

列出镜像

如果想要查看本地已经下载的镜像,则可以使用如下指令:

docker image ls

指令运行的结果应该如下:
docker image ls运行结果
其中,ubuntu是镜像的名字,tag是镜像的标签。Imgae ID则是镜像的ID。每一个镜像都有唯一的ID,所以可以通过镜像的ID来引用镜像。通常我们可以只输入ID开头的几个字符即可,Docker会自动匹配。
同时该指令也可以类似于Linux指令,有很多种玩法:

docker image ls -q  # 只显示镜像的ID
docker image ls  --digests  # 同时显示摘要
docker image ls -a  # 显示所有
docker image ls -f  # 过滤器

删除镜像

我们想要删除本地的Docker镜像的话,可以使用如下指令:

docker image rm [选项] <镜像1> [<镜像2> ...]

使用该指令的话,我们有很多种方式来确定镜像。第一种方式就是使用镜像的ID,这里可以是镜像的完成ID,也可以是镜像的模糊ID,Docker可以自行匹配。
当然,最精确的话,可以是使用镜像摘要。在上述列出镜像中,我们可以使用"-- digests"可以同时显示镜像的摘要。
带镜像摘要的列表
我们可以使用镜像摘要作为删除的镜像定位。
同时我们甚至可以使用"ls -q"作为删除的方法。例如:

docker image rm (docler image ls -q [镜像名])  # []为可选,如不添加默认删除全部

最后,我们还可以使用 “镜像名:标签” 的方式来删除镜像。但是我不推荐这种方式,因为这种方式可能会并不产生真正的删除镜像行为。因为删除镜像可以分为两步,第一步是Untagged,第二步则是Delete。对于同一个镜像,有时可以有很多个镜像指向它,此时删除标签只是去除这个标签的指向,还会有其他标签指向此镜像,并不会导致真正的删除镜像行为。

Dockerfile制作镜像

首先,我们需要知道什么是Dockerfile。其实,Docker就是一组指令的集合,每一条指令构建一层。每一条指令都描述了该层应该如何构建。其实,Docker镜像都是由一些松耦合的只读镜像层组成,Docker只负责堆叠这些镜像层,将他们表示成为一个整体。
有点像Java都是起源于Object类一样,所有的Docker镜像都是起源于一个基础镜像层,当进行修改和增加新内容的时候,就会在该层上面创建新的镜像层。
这样做的好处是,多个镜像之间可以共享镜像层,来减少消耗。
而Dockerfile文件中,尝试用的是两种指令,一种是FROM和RUN指令。
首先是FROM指令,表示基于的镜像层。想要定制镜像,就必须有一个基础镜像。所以FROM指令是Dockerfile文件所必须的,同时,还必须是Dockerfile文件的第一条指令。在Docker hub中有很多可以直接拿来使用的镜像,例如ubuntu,centos,nginx,tensorflow等。其中有一些是操作系统,还有一些是应用。
其中有一个较为特殊的镜像:

FROM scratch

这个镜像为空白镜像,对于 Linux 下静态编译的程序来说,并不需要有操作系统提供运行时支持,所需的一切库都已经在可执行文件里了,因此直接 FROM scratch 会让镜像体积更加小巧。使用 Go 语言 开发的应用很多会使用这种方式来制作镜像,这也是为什么有人认为 Go 是特别适合容器微服务架构的语言的原因之一。
然后就是RUN指令,其可以执行两种类型的指令。其中一种就是直接执行shell格式的指令,RUN <命令>例如:

RUN echo '<h1>Hello, Docker!</h1>' > /usr/share/nginx/html/index.html

也可以是exec格式,RUN [“可执行的文件”, “参数”]。
但是,在开头就说过,每一条指令会对应的创建一个层,所以我们不可以简单的一条指令对应一个层,这样是没有意义的。而且会使镜像变得很臃肿。我们可以使用 ""作为换行符,然后使用 “&&” 串联多个shell指令。这样就可以写出高效的Dockerfile文件了。
镜像是多层存储,每一层的东西并不会在下一层被删除,会一直跟随着镜像。因此镜像构建时,一定要确保每一层只添加真正需要添加的东西,任何无关的东西都应该清理掉。
在制作完Dockerfile文件后,我们可以通过其来构建镜像了。

docker build [选项] <上下文路径/URL/->

举个例子:

$ docker build -t nginx:v3 .

我们cd到存储Dockerfile文件的文件夹,执行上述指令。其中"-t nginx:v3"指定了镜像的标签。而在后面还有一个 “.” 这个代表的使当前文件夹。这个 "."表示的应是上下文路径,而不应该使Dockerfile所在的路径。只是通常情况下,Dockerfile所在的文件夹,就是其上下文路径。
其实,这涉及到Docker的工作模式,Docker指令并不在本地运行,而是在Docker引擎中运行。Docker会将上下文中的所有文件上传到Docker引擎中。所以真正的运行路径应该是在服务器中的文件夹中。

容器

什么是容器

容器就是镜像运行时的实例。可以做一个不太准确的比喻,容器和镜像的关系,有一点像进程和程序的关系。又有一点不太像,镜像是容器某一时刻的静态,容器则是不断运行的。而进程是基于程序的,又添加了类似PCB的数据结构来进行管理。

容器操作

启动容器有两个不同的方式,第一种是基于镜像启动一个容器,第二种是基于已经终止的容器来重新启动。

基于镜像启动容器

基于镜像启动容器最主要的指令就是docker container run。一个很经典的指令:

docker run ubuntu /bin/echo 'hello world'

这个会输出 ‘hello world’ 然后终止容器。
同时,docker run还有一些比较常用的选项:

  1. -t Docker会分配一个伪终端,绑定到docker的标准输出上
  2. -i 让容器的标准输入保持打开
  3. -d 让docker在后台运行

重新启动已经终止的容器

可以使用docker container start来重新启动一个已经终止的容器。

容器列表

可以使用docker ps来查看所有正在运行的容器。
同时我们可以使用-a选项来选择显示所有的容器,包括已经停止的容器。在为运行状态下的容器我们可以使用上述的docker container start来重新启动。

查看在后台运行的容器

我们可以使用docker container logs 来查看在后台运行的容器的输出。

进入后台运行的容器

有两种方式,第一种是使用docker container attach,第二种是使用docker container exec。
这两种方式的区别:

  1. attach直接进入容器启动命令的终端,不会启动新的进程;
  2. exec则是在容器中打开新的终端,并且可以启动新的进程;
  3. 如果想直接在终端中查看命令的输出,用attach,其他情况使用exec;

删除容器

删除容器也十分简单,就是docker container rm。需要注意的是,此指令只能删除终止状态下的容器。

export和import

docker export可以导出容器快照。而docker import则可以再导入为镜像。

参考文献

  1. Datawhale Docker教程
  2. 《深入浅出Docker》
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值