一 、什么是Docker
1.1 简介
Docker 使用 Google 公司推出的 Go 语言 (opens new window)进行开发实现,基于 Linux 内核的 cgroup (opens new window),namespace (opens new window),以及 OverlayFS (opens new window)类的 Union FS (opens new window)等技术,对进程进行封装隔离,属于 操作系统层面的虚拟化技术 (opens new window)。由于隔离的进程独立于宿主和其它的隔离的进程,因此也称其为容器。
Docker 在普通进程容器的基础上,进行了进一步的封装,包括从文件系统、网络互联到进程隔离等等,极大的简化了容器的创建和维护,使得 Docker 技术比虚拟机技术更为轻便、快捷。
下图比较了 Docker 和传统虚拟化方式的不同之处。传统虚拟机技术是虚拟出一套硬件后,在其上运行一个完整操作系统,在该系统上再运行所需应用进程;而容器内的应用进程直接运行于宿主的内核,容器内没有自己的内核,而且也没有进行硬件虚拟。因此容器要比传统虚拟机更为轻便。
1.2 Docker的优点
1.2.1 高效的利用系统资源
容器不需要进行硬件虚拟以及运行完整操作系统等额外开销,Docker 对系统资源的利用率更高。无论是应用执行速度、内存损耗或者文件存储速度,都要比传统虚拟机技术更高效。因此,相比虚拟机技术,一个相同配置的主机,往往可以运行更多数量的应用。
此外可以通过Docker来限制单个应用对资源的使用,例如限制某个进程最大可使用的CPU核数、内存、磁盘空间等,来对机器上各个应用的资源进行合理分配。
1.2.2 轻松的维护和扩展
开发过程中一个常见的问题是环境一致性问题。由于开发环境、测试环境、生产环境不一致,导致有些 bug 并未在开发过程中被发现。而 Docker 的镜像提供了除内核外完整的运行时环境,确保了应用运行环境一致性,从而不会再出现 「这段代码在我机器上没问题啊」 这类问题。
对开发和运维(DevOps (opens new window))人员来说,最希望的就是一次创建或配置,可以在任意地方正常运行。
使用 Docker 可以通过定制应用镜像来实现持续集成、持续交付、部署。开发人员可以通过 Dockerfile 来进行镜像构建,并结合 持续集成(Continuous Integration) (opens new window)系统进行集成测试,而运维人员则可以直接在生产环境中快速部署该镜像,甚至结合 持续部署(Continuous Delivery/Deployment) (opens new window)系统进行自动部署。
使用 Dockerfile 使镜像构建透明化,不仅仅开发团队可以理解应用运行环境,也方便运维团队理解应用运行所需条件,帮助更好的生产环境中部署迁移该镜像。
二、Docker中的基本概念
2.1 镜像
Docker 镜像 是一个特殊的文件系统,除了提供容器运行时所需的程序、库、资源、配置等文件外,还包含了一些为运行时准备的一些配置参数(如匿名卷、环境变量、用户等)。镜像 不包含 任何动态数据,其内容在构建之后也不会被改变。
为了避免镜像文件和以前的ISO文件一样臃肿,Docker 在设计时就利用 Union FS (opens new window)的技术,设计为了分层存储的架构。所以Docker镜像实际体现为是由一组文件系统,或者说是多层文件系统的联合组。这种设计使得镜像的复用、定制变的极为容易,甚至可以用之前构建好的镜像作为基础层,然后进一步添加新的层,以定制自己所需的内容,构建新的镜像。
2.2 容器
镜像(Image)和容器(Container)的关系,就像是面向对象程序设计中的 类 和 实例 一样,镜像是静态的定义,容器是镜像运行时的实体。容器可以被创建、启动、停止、删除、暂停等。
容器的实质是进程,但与直接在宿主执行的进程不同,容器进程运行于属于自己的独立的 命名空间 (opens new window)。因此容器可以拥有自己的 root 文件系统、自己的网络配置、自己的进程空间,甚至自己的用户 ID 空间。容器内的进程是运行在一个隔离的环境里,使用起来,就好像是在一个独立于宿主的系统下操作一样。这种特性使得容器封装的应用比直接在宿主运行更加安全。
镜像使用的是分层存储,容器也是如此。每一个容器运行时,是以镜像为基础层,在其上创建一个当前容器的存储层,可以称这个为容器运行时读写而准备的存储层为容器存储层。容器存储层的生存周期和容器一样,容器消亡时,容器存储层也随之消亡。因此,任何保存于容器存储层的信息都会随容器删除而丢失,因此容器不应该向其存储层内写入任何数据,容器存储层要保持无状态化。所有的文件写入操作,都应该使用 数据卷(Volume)、或者 绑定宿主目录,在这些位置的读写会跳过容器存储层,直接对宿主(或网络存储)发生读写,其性能和稳定性更高。
2.3 仓库
镜像构建完成后,可以很容易的在当前宿主机上运行,但是,如果需要在其它服务器上使用这个镜像,就需要一个集中的存储、分发镜像的服务,仓库(Docker Registry) 就是这样的服务。
最常使用的 Registry 公开服务是官方的 Docker Hub (opens new window),这也是默认的 Registry,并拥有大量的高质量的 官方镜像 (opens new window)。
在仓库中每个镜像都可以包含多个 标签(Tag),而一般同一个软件会有多个不同版本的镜像,标签就常用于对应软件的各个版本。可以通过 <仓库名>:<标签> 的格式来指定具体是这个软件哪个版本的镜像。如果不给出标签,将以 latest 作为默认标签。
三、Docker安装
可以下载安装包然后安装,也可以使用官方安装脚本自动安装,我用的是官方提供的安装脚本:
curl-fsSL https://test.docker.com -o test-docker.sh
sudosh test-docker.sh
安装过程如下:
最后:
需要注意,最后查看docker版本的时候提示:
permission denied while trying to connect to the Docker daemon socket at unix:///var/run/docker.sock: Get "http://%2Fvar%2Frun%2Fdocker.sock/v1.24/version": dial unix /var/run/docker.sock: connect: permission denied
这个不是问题,只是权限不够,改成root账号权限再查看就没问题了;
#四、镜像使用
4.1 下载镜像
Docker Hub上有大量的镜像可以用,从上面获取镜像的命令是 docker pull。其命令格式为:
$ docker pull [选项] [Docker Registry 地址[:端口号]/]仓库名[:标签]
具体的选项可以通过 docker pull --help 命令看到;关于获取的镜像名称的格式。
- Docker 镜像仓库地址:地址的格式一般是 <域名/IP>[:端口号]。默认地址是 Docker Hub(docker.io)。
- 仓库名:如之前所说,这里的仓库名是两段式名称,即 <用户名>/<软件名>。对于 Docker Hub,如果不给出用户名,则默认为 library,也就是官方镜像。
比如:
上面拉取ubuntu的时候仅仅指定了一个ubuntu及其版本号,因此将会获取Docker hub中标签为 18.04 的镜像,然后下载的镜像会展示它的ID(sha256:XXX)。
如果是在私有镜像库中拉取镜像,需要指定库地址等等,这个过程其实和git几乎一样,就不细写了。
4.2 运行镜像
运行刚刚拉去的ubuntu:
在这里用的是run指令,其中的参数含义:
- it:这是两个参数,一个是 -i:交互式操作,一个是 -t 终端。我们这里打算进入 bash 执行一些命令并查看返回结果,因此我们需要交互式终端。
- -rm:这个参数是说容器退出后随之将其删除。默认情况下,为了排障需求,退出的容器并不会立即删除,除非手动 docker rm。这里只是随便执行个命令,看看结果,不需要排障和保留结果,因此使用 --rm 可以避免浪费空间。
- ubuntu:18.04:这是指用 ubuntu:18.04 镜像为基础来启动容器。
- bash:放在镜像名后的是 命令,这里我们希望有个交互式 Shell,因此用的是 bash。
可以看到,执行run指令之后就进入了一个shell,然后测试执行 cat /etc/os-release,查看镜像的系统版本,从返回的结果可以看到容器内是 Ubu
ntu 18.04.6 LTS 系统。
4.3 查看已有镜像
需要使用image ls指令:
这个指令会展示一个镜像列表,列表中包含 仓库名、标签、镜像 ID、创建时间 以及 所占用的空间。
这个指令不加任何参数时展示的是所有的镜像, 也可以添加参数展示部分镜像,例如
$ docker image ls ubuntu // 根据仓库名列出镜像
$ docker image ls ubuntu:18.04 // 列出特定的某个镜像,指定仓库名和标签
$ docker image ls -f since=mongo:3.2 // 过滤器参数 --filter,或者简写 -f
等等,image ls是个很强大的指令,具体就不全列出来了;
4.4 删除镜像
删除镜像是用 rm 指令,,其格式为:
$ docker image rm [选项] <镜像1> [<镜像2> ...]
其中,<镜像> 可以是 镜像短 ID、镜像长 ID、镜像名 或者 镜像摘要。
刚刚通过image ls列出来的镜像列表中就有一列IMAGE ID项,这是短ID,使用短ID也可以只使用部分,一般是使用前三位以上,确保这一部分是唯一的就可以。
之前介绍过,镜像的唯一标识是其 ID 和摘要,而一个镜像可以有多个标签。因此当我们删除镜像的时候,实际上是在要求删除某个标签的镜像。所以首先需要做的是将满足我们要求的所有镜像标签都取消,这在命令行中展示出来的看就是 Untagged 信息。因为一个镜像可以对应多个标签,因此当我们删除了所指定的标签后,可能还有别的标签指向了这个镜像,如果是这种情况,那么真正的 Delete 行为就不会发生。所以并非所有的 docker image rm 都会产生删除镜像的行为,有可能仅仅是取消了某个标签而已。只有当该镜像所有的标签都被取消了,才会触发删除行为。
rm还可以和ls指令配和使用,例如:
$ docker image rm $(docker image ls -q ubuntu)
// 删除所有仓库名为 ubuntu的镜像:
版权归原作者 LL596214569 所有, 如有侵权,请联系我们删除。