您的位置:首页 > 运维架构 > Docker

Docker 入门须知

2018-01-14 14:09 218 查看

前言:

之前大概了解了一下 Docker 的一些皮毛,知道 Docker 是基于 Go 语言开发的容器技术,可以在同一台服务器上构建多个互不干扰的干净的隔离环境。

Docker 的优点:

相比于传统的虚拟技术,容器可以以更低的成本为应用提供一个干净的隔离环境,原因大致如下:

传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此,容器要比传统虚拟机更为轻便。

除了资源消耗低外, 使用 Docker 的在一次创建或配置在任何地方地方运行也是优势之一:

开发人员用
Dockerfile
来进行镜像构建,并结合
持续继承(Continuous Integration)系统
进行集成测试;

运维人员可以直接在生产环境中快速部署该镜像,甚至结合
持续部署(Continuous Delivery/Deployment)系统
进行自动部署。

Docker 基础:

在使用Docker 前,需要弄清楚三个概念:

镜像(Image):

一个特殊的文件系统,提供容器运行时所需的程序、库、资源、配置等文件,还有运行时的一些配置参数(环境变量等),不包含任何动态数据,内容在构建之后不会被改变。(使用时充分利用
Union Fs
技术,将其设计为分层存储的架构)

容器(Container):

镜像与容器的关系,就像
实例
一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。使用容器时,存储数据应该使用
数据卷(Volume)
或 绑定宿主目录,不要写在容器存储层中,这样数据在容器被删除后不会丢失。

仓库(Repository):

为了使镜像可以在其他服务器上使用,需要用到一个集中的存储、分发镜像的服务
Docker Registry
,一个
Docker Registry
中可以包含多个
仓库(Repository)
;每个仓库中可以包含多个
标签(Tag)
; 每个标签对应一个镜像。(通常,一个仓库会包含同一个软件不同版本的镜像,而标签就常用于对应该软件的各个版本。我们可以通过
<仓库名>:<标签>
的格式来指定具体是这个软件哪个版本的镜像。)

从 Docker Registry 中获取镜像的指令:

docker pull [选项] [Docker Registry地址]<仓库名>:<标签>


Docker Registry 地址:一般格式是
<域名/IP>[:端口号]
,默认地址是 Docker Hub;

仓库名:两段式名称,即
<用户名>/<软件名>
,在 Docker Hub 中,不给用户名的,则默认为
library
,即官方镜像。

Docker 中的镜像是分层的,这样可以提高层的复用性,即两个不同的镜像可能使用了同一个基础层,那么下载这两个镜像后,docker 中其实只存在一份两者共有的层,提高资源利用率并节省空间,分层也是 Docker 容器技术的核心之一。

常用指令:

docker image

docker image 和 docker images 是用来管理镜像的接口:

docker image ls


docker container

这是用于操作基于 image 启动出来的容器,例如:

docker container stop [containerName]   # 停止一个正在运行的容器
docker container rm [containerName]     # 移除一个已停止运行的容器


containerName
是使用 docker run 启动一个容器时
--name
字段所指定的容器名称。

docker commit

docker commit 用于将当前运行的容器对所基于的镜像的修改内容保存起来,生成新的镜像,但这种方式一般不用于定制镜像,应使用 Dockerfile 来实现自定义镜像。可以把容器当作是基于镜像加一层数据层的运行结果,数据层可变,变化内容可以通过 docker commit 保存下来。指令格式:

docker commit --author "" --message "" <容器 id 或容器名> [<仓库名>[:<标签>]]


可以通过
docker diff <容器名>
查看修改内容。

慎用 docker commit ,原因如下:

对单个文件的简单的操作可能导致多个文件的修改和添加,不及时清理便会导致镜像臃肿;

操作不透明,这种黑箱操作生成的黑箱镜像,只有制作镜像的人才能知道镜像生成过程执行过的操做,其他人即使借助 docker diff 也无法确保能生成一致的镜像;

修改操作仅对当前层有效,即使对上一层的东西执行了删除操作,上层的东西也还存在,即使无法再被访问,但会一致跟随此镜像。

Dockerfile

关于镜像的定制,实际上就是定制每一层所添加的配置和文件。把每一层修改、安装、构建和操作的命令都写入一个脚本,用这个脚本来构建和定制镜像,这个脚本就是
Dockerfile


可以解决 docker commit 中存在的无法重复、景象构建透明性、体积臃肿等问题。

Dockerfile
是一个文本文件,其中包含多条指令(Instruction),每条指令构建一层,因此每条指令的内容,就是描述该层应如何构建。

1. 创建简单的 Dockerfile:

创建一个目录,然后在该目录下创建 Dockerfile 文件:

$ mkdir TestDockerfile
$ cd TestDockerfile
$ touch Dockerfile


然后编辑 Dockerfile 的内容:

vi Dockerfile


输入以下内容:

FROM scratch
RUN apt-get update


FROM
指令用于指定当前镜像的基础镜像,是 Dockerfile 中必备的指令也是第一条指令,假如不需要基于任何基础镜像,可以基于 Docker 的一个特殊的镜像
scratch
,这是一个虚拟的概念,并不实际存在,它表示一个空白镜像。

RUN
指令用来执行命令行命令,使用格式有两种:

shell
格式:
RUN <命令行>


exec
格式:
RUN ["可执行文件","参数1","参数2"]
,更像函数调用的格式。

之前说过 Dockerfile 中一条指令会构建当前镜像的一层,那么假如一层中需要执行多个 shell 命令来完成构建,则需要使用
&&
连接符来连接多个命令,为了提高可读性,
RUN
指令也支持在行尾使用
\
的命令换行方式,例如:

RUN apt-get update \
&& apt-get install -y go \
&& ...


合理地规划好镜像构建的分层非常重要,而且每一层构建完成后,需要将无用的下载和展开文件内容清理掉,否则到了下一层就无法删除了,会不断累积跟随镜像。

2. 执行 Dockerfile 构建镜像:

上面我们已将创建了一个 Dockerfile 文件,接下来我们就要是使用该文件来构建镜像,执行方式就是在 Dockerfile 所在的目录(一个目录下只能存在一个 Dockerfile 文件)下执行如下指令:

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


例如:
docker build -t testDockerfile:v1 .
,即构建出来的镜像名称为
-t testDockerfile:v1
,最后指定上下文路径为
.
,即表示当前目录。

docker 的各种功能其实是使用远程调用的形式在服务端(Docker 引擎)完成的,客户端通过
Dcoker Remote API
来与 Docker 引擎交互,完成各种功能。

上下文目录在执行 docker build 时会将该目录下的所有内容打包,上传给 Docker 引擎,提供引擎构建镜像所需的所有文件。这个过程在 docker build 的输出日志可以看到:

Sending build context to Docker daemon ...


切记不可在上下文目录下放置过多构建镜像时无用的文件,不然这些文件也会全部被打包上传,导致镜像构建缓慢甚至容易失败。所以,通常将 Dockerfile 放置在一个空目录下。

也可以通过
.dockerignore
剔除上下文目录中无需传递给 Docker 引擎的文件,该文件的功能类似与 git 操作中的
.gitignore


构建镜像的 Dockerfile 文件并非必须使用
Dockerfile
来命名,也并非必须放在上下文目录下,可以通过
-f ../Dockerfile.php
参数的形式来指定当前镜像构建脚本,只是一般都习惯直接命名为
Dockerfile
并直接放在上下文目录下而已。

更多 Dockerfile 的指令可以参考:Dockerfile 指令详解

参考文章:

Docker —— 从入门到实践
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: