Docker 是基于 Go 语言实现的云开源项目。Docker 的主要目标是 Build,Ship and Run Any App,Anywhere,也就是通过对应用组件的封装、分发、部署、运行等生命周期的管理,使用户的 APP(可以是一个 WEB 应用或者数据库应用等等)及其运行环境能够做到 一次封装,到处运行。
Docker 引擎的基础是 Linux 自带的容器(Linux Containers,LXC)技术。IBM 对于容器技术的准确描述如下:
容器有效的将单个操作系统管理的资源划分到孤立的组中,以便更好的在孤立的组之间平衡有冲突的资源使用需求。与虚拟化相比,这样既不需要指令级模拟,也不需要即时编译。容器可以在核心 CPU 本地运行指令,而不需要任何专门的解释机制。此外,也避免了准虚拟化(paravirtualization)和系统调用替换中的复杂性。
我们可以将容器理解为一种沙盒。每个容器内运行一个应用,不同的容器相互隔离,容器之间可以建立通信机制。容器的创建和停止都十分快速(秒级),容器自身对资源的需求十分有限,远比虚拟机本身占用的资源少。
更快速的交付和部署:开发人员可以使用镜像快速的构建标准开发环境;开发完成后,测试和运维人员可以使用开发人员提供的 docker 镜像快速部署应用,可以避免开发和测试运维人员之间的环境差异导致的部署问题。
更高效的资源利用:Docker 容器的运行不需要额外的虚拟化管理程序支持,它是内核级的虚拟化,在占用更少资源的情况实现更高的性能。
更方便的迁移和扩展:Docker 容器几乎可以在任意的平台上运行,包括物理机、虚拟机、公有云、私有云、服务器等。这种兼容使得用户可以在不同的平台之间很方便的完成应用迁移。
更简单的更新管理:使用 Dockerfile,只需要小小的配置修改,就可以替代以往大量的更新工作,并且所有修改都以增量方式进行分发和更新。
虚拟化的核心是对资源进行抽象,目标往往是为了在同一个机器上运行多个系统或应用,从而提高系统资源的利用率。虚拟化分为很多类型,比如常见的硬件辅助虚拟化(VMware workstation、 KVM等)。
Docker 所代表的容器虚拟化技术属于操作系统级虚拟化:内核通过创建多个虚拟的操作系统实例(内核和库)来隔离不同的进程。#
传统虚拟化和容器技术结构比较:传统虚拟化技术是在硬件层面实现虚拟化,增加了系统调用链路的环节,有性能损耗;容器虚拟化技术以共享 Kernel 的方式实现,几乎没有性能损耗。
Docker 是 Client/Server 的架构,Docker 客户端与 Docker daemon 进行交互,daemon负责构建、运行和发布 Docker 容器。客户端可以和服务端运行在同一个系统中,也可以连接远程的 daemon。Docker 的客户端的 daemon 通过 RESTful API 进行 socket 通信。
Docker 守护进程(daemon)在主机上运行,用户不能直接和守护进程打交道,但是可以通过 Docker 客户端与其进行交互;Client 是 Docker 的初始用户界面,它接收用户的命令并反馈,并且与 Docker 的守护进行交互。
Docker 基于 Linux 容器技术(LXC),Namespace,Cgroup,UnionFS(联合文件系统)等技术实现:
命名空间是 Linux 内核一个强大的特性。每个容器都有自己单独的命名空间,运行在其中的应用都像是在独立的操作系统中运行一样。命名空间保证了容器之间彼此互不影响。docker 实际上一个进程容器,它通过namespace实现了进程和进程所使用的资源的隔离。使不同的进程之间彼此不可见。
Docker 用到的一些命名空间有:
是 Linux 内核的一个特性,主要用来对共享资源进行隔离、限制、审计等。只有能控制分配到容器的资源,才能避免当多个容器同时运行时的对系统资源的竞争。控制组技术最早是由 Google 的程序员 2006 年起提出,Linux 内核自 2.6.24 开始支持。控制组可以提供对容器的内存、CPU、磁盘 IO 等资源的限制和审计管理。
Union 文件系统(UnionFS)是一种分层、轻量级并且高性能的文件系统,它支持对 文件系统的修改作为一次提交来一层层的叠加,同时可以将不同目录挂载到同一个虚拟文件系统下(unite several directories into a single virtual filesystem)。Union 文件系统是 Docker 镜像的基础。镜像可以通过分层来进行继承,基于基础镜像(没有父镜像),可以制作各种具体的应用镜像。另外,不同 Docker 容器就可以共享一些基础的文件系统层,同时再加上自己独有的改动层,大大提高了存储的效率。Docker 中使用的 AUFS(AnotherUnionFS)就是一种 Union FS。 AUFS 支持为每一个成员目录(类似 Git 的分支)设定只读(readonly)、读写(readwrite)和写出(whiteout-able)权限, 同时 AUFS 里有一个类似分层的概念, 对只读权限的分支可以逻辑上进行增量地修改(不影响只读部分的)。Docker 目前支持的 Union 文件系统种类包括 AUFS, btrfs, vfs 和 DeviceMapper。
Docker 镜像类似于虚拟机镜像,是一个只读模板,并且包含了文件系统。一个镜像可以只包含一个操作系统环境(比如SUSE镜像),也可以安装了用户程序及其运行环境(比如eBackup镜像)。镜像其实就是一个文件,任何用户程序都可以成为镜像的一部分。
- 镜像 = 操作系统 + 软件运行环境 + 用户程序
一个 layer 就是一个 image,多个 image 又可以打包成一个 image。Image 类似一个单链表系统,每个 image 包含一个指向 parent image 的指针,没有 parent image 的 image 是 baseimage(image 的指针靠 sqlite 数据库来保存)。
最上面的一层(不属于image)是可写的,上面的内容依赖于下面的内容,如果要修改下面的内容,先将下面的内容复制到上面再进行修改。Image 是创建 container 的基础。
关于 image 的一些命令:
- docker pull //从网络上下载镜像
- docker images //查看本地主机已经存在的镜像
-
容器是从镜像创建的运行实例,可以将其启动、开始。停止、删除,而这些容器都是相互隔离(独立进程),互不可见的。
我们对 Docker 有了认识和了解,docker 还有非常重要的一块,那就是 docker 镜像。提到docker镜像必不可少的一个文件是 Dockerfile
docker 可以通过 build 命令自动从 Dockerfile 文件中读取并执行命令,最终生成 docker 镜像。使用 Dockerfile 非常简单,且重要!
写文章时 docker 版本号为:1.8.2 目前 Dockerfile 中共包含14个命令,文章内容详细介绍每个一个命令的含义和用法
格式:INSTRUCTION arguments
instruction 不区分大小写,推荐用大写,以免和其他参数冲突
格式:
Dockerfile中的第一条指令必须是FROM,FROM指令指定了构建镜像的base镜像
格式:MAINTAINER \<name\> \<Email\>
编写维护 Dockerfile 的作者信息
格式:
为容器声明环境变量,环境变量在子镜像中也可以使用。可以直接使用环境变量$variable_name
运行容器指定环境变量:docker run --env <key>=<value>
格式:
第一种 使用 shell 格式时,命令通过 /bin/sh -c 执行;
第二种 使用exec格式时,命令直接执行,容器不调用shell,并且 exec 格式中的参数会看作是JSON
数组被Docker解析,所以要用(")双引号,不能用单引号(')。
举例:
RUN [ "echo", "$HOME" ]HOME变量不会被替换,如果你想运行shell程序,使用:`RUN [ "sh", "-c", "echo", "HOME变量不会被替换,如果你想运行shell程序,使用:‘RUN["sh","−c","echo","HOME" ]`
格式:COPY \<src\>\<dest\>
拷贝本地<src>目录下的文件到容器中<dest>目录。
格式:
ADD hom* /mydir/
从<src>目录下拷贝文件,目录或网络文件到容器的<dest>目录。和COPY非常相似,但比COPY功能多,拷贝的文件可以是一个网络文件,并且ADD有解压文件得功能。
格式:
虽然有三种格式,但在Dockerfile中如果有多个CMD命令,只有最后一个生效。
CMD命令主要是提供容器运行时得默认值。默认值,可以是一条指令,也可以是参数(ENTRYPOINT),CMD命令参数是一个动态值,信息会保存到镜像的JSON文件中。
举例:
- ENTRYPOINT ["executable"]
- CMD ["param1", "param2"]
-
启动容器执行:["executable", "param1", "param2"]
注意: 如果在命令行后面运行docker run时指定了命令参数,则会把Dockerfile中定义的CMD命令参数覆盖
格式:
ENTRYPOINT和CMD命令类似,也是提供容器运行时得默认值,但它们有不同之处。同样一个Dockerfile中有多个ENTRYPOINT命令,只有最后一个生效。
格式:ONBUILD [INSTRUCTION]
ONBUILD指令的功能是添加一个将来执行触发器指令到镜像中。当Dockerfile中FROM的镜像中包含ONBUILD指令,在构建此镜像的时候会触发ONBUILD指令。但如果当前Dockerfile中存在ONBUID指令,不会执行就。ONBUILD指令在生成应用镜像时用处非常大。
ONBUILD如何工作
1.构建过程中,ONBUILD指令会添加到触发器指令镜像元数据中。触发器指令不会在当前构建过程中生效
2.构建完后,触发器指令会被保存到镜像的详情中,主键是OnBuild,可以使用docker inspect命令查看到
3.之后此镜像可能是构建其他镜像的父镜像,在构建过程中,FROM指令会查找ONBUILD触发器指令,并按照之前定义的顺序执行;如果触发器指令执行失败,则构建新镜像失败并退出;如果触发器指令执行成功,则继续往下执行。
4.构建成功后ONBUILD指令清除,固不会被孙子辈镜像继承。
格式:VOLUME ["/data"]
为docker主机和容器做目录映射,volume目录信息会保存到镜像的JSON文件中,在运行docker run命令时指定$HOST_DIR
格式:LABEL <key>=<value> <key>=<value> <key>=<value> ...
LABEL指令,添加一个元数据到镜像中。一个镜像中可以有多个标签,建议写一个(因为没多个LABEL指令镜像会多一个layer)LABEL是一个键值对<key><value>,在一个标签值,包括空间使用引号和反斜杠作为您在命令行解析。
举例:
LABEL multi.label1="value1" multi.label2="value2" other="value3"
格式:EXPOSE <port> [<port>...]
在Dockerfile中定义端口,默认是不往外暴露,在运行docker run -p or -P暴露
格式:USER daemon
设定一个用户或者用户ID,在执行RUN``CMD``ENTRYPOINT等指令时指定以那个用户得身份去执行
格式:WORKDIR /path/to/workdir
当执行RUN``CMD``ENTRYPOINT``ADD``CMD等命令,设置工作目录
如果在Dockerfile文件目录下有.dockerignore文件,docker在构建镜像的时候会把在.dockerignore文件中定义的文件排除出去
- */temp*
- */*/temp*
- temp?
- *.md
- !LICENSE.md
-
正在维护的 Centos 7 以上版本, centos-extras 被启用(默认是启用状态)启用 centos-extras
旧版本被称为docker或者docker-engine,如果之前装有旧版本,需要卸载旧版本,相关依赖一同卸载。
- >$ sudo yum remove docker \\
- docker-common \\
- docker-selinux \\
- docker-engine
-
/var/lib/docker/ 路径下的内容将被保留,现在 Docker-CE 包统称 docker-ce
如果是第一次在一台新的机器上安装,则需要安装 repository,之后就可以通过 repository 进行安装和升级
- >$ sudo yum install -y yum-utils \\
- device-mapper-persistent-data \\
- lvm2
-
- $ sudo yum-config-manager \\
- --add-repo \\
- https://download.docker.com/linux/centos/docker-ce.repo
-
- $ sudo yum-config-manager --enable docker-ce-edge
- $ sudo yum-config-manager --enable docker-ce-test
-
禁用 edge 或者 test repository 可以使用如下命令:
- $ sudo yum-config-manager --disable docker-ce-edge
- $ sudo yum-config-manager --disable docker-ce-test
-
- $ sudo yum install docker-ce
-
Note:如果启用了多个 docker repository,则在使用 yum install 或者 yum update 没有指定版本时,总是会安装最高的版本,可能最高的版本并不是很稳定。
- $ yum list docker-ce --showduplicates | sort -r
- docker-ce.x86_64 17.09.ce-1.el7.centos docker-ce-stable
-
安装指定版本的 docker ce
- sudo yum install \<FULLY-QUALIFIED-PACKAGE-NAME\>
-
example:上面列表中的全称版本 docker-ce-17.06.1.ce
- $ sudo systemctl start docker
-
- $ sudo docker run hello-world
-
这个命令会下载测试镜像,并且运行一个容器,当容器运行成功,会打印信息然后退出。