/ Docker

Docker 入门教程

一些常见的虚拟化技术

经常买 VPS 的同学可能会知道,一般 VPS 商家会提供采用 OpenVZ、KVM、Xen 等虚拟化技术的产品,采用 OpenVZ 的机器比较便宜,KVM、Xen 的则相对比较贵。

在云基础设施服务商这里,他们的主要需求是把一台台的物理机器变成可以向用户提供的 VPS。对于一台物理机器而言(一般称为母鸡),服务商可以在上面装上操作系统,然后使用 OpenVZ、KVM、Xen、VMWare、Hyper-V 这几种虚拟化技术在母鸡上虚拟出来若干个独立的操作系统(一般称为小鸡)。

如果采用的是 OpenVZ 的话,由于 OpenVZ 是一个操作系统层的虚拟化技术,采用这种技术的 VPS 无法修改内核,只能安装 Linux。由于它的配置比较灵活,对资源的利用率比较高,性能也比较好。但是也正是由于它的配置比较灵活,基本上采用这种虚拟化技术的 VPS 都是超卖的。

而 KVM 是一个基于内核级别的虚拟化技术,使用这种虚拟化技术的 VPS 可以修改内核,可以安装 Linux,也可以安装 Windows,这种技术对母鸡的利用率没有 OpenVZ 那么高,但是对于使用者而言,买到的 VPS 质量相对比较高,受到同一台母鸡上其他用户的影响比较小。

如果你购买的是 OpenVZ 的机器,有些软件就有可能装不上,比如 Google 推出的 BBR(一种 TCP 拥塞控制技术,能够有效提高网络质量),BBR 对于内核的要求比较高,而 KVM 的机器就可以。一般 VPS 提供商都会在购买页面说明这是 KVM 还是 OpenVZ 的机器,对于一些大的厂商,比如 Google Cloud,Do,Linode,他们提供的机器都是采用 KVM 或者 Xen 虚拟化的。

基于容器的虚拟化技术

dotCloud 公司在 2013 年将自己公司内部使用的 Container 容器技术开源,Docker 基于 Go 语言开发,代码放到了 github 上。和上面说的几种虚拟化技术不同的是,Docker 采用将进程隔离的办法来实现虚拟化,是一种更加轻量的虚拟化技术,对于资源的利用效率更高。

在 Docker 出现之前,一个 App 服务能够成功发布,作为开发人员需要关心的东西太多,包括各种 OS、中间件、依赖环境,而且环境之间难免产生冲突。而 Docker 的出现让这一切变得简单,你可以把一个应用和相关依赖单独打包到一个容器里部署,比如说 Web 应用、数据库应用、大数据应用分开部署,容器之间不会相互影响。

Docker 是基于 Linux container 的一个容器管理工具。在 Linux Kernel 里对资源进行控制的机制是 cgroup,实现资源隔离的机制是 namespaces。它的作用是将应用程序给容器化,以保证在同一个 Kernel 上运行的应用程序的运行环境相互隔离,让容器内的这些进程觉得在这个系统里只有这些进程而感知不到其他进程的存在。

基础命令

  • 查看 docker 版本
docker version  
  • 查看 docker 信息
docker info  
  • 查看正在运行 docker container 列表
docker ps  
  • 查看本地所有的 docker 镜像
docker images
  • 搜索 docker 镜像
docker search <Image Name>
  • 拉取 docker 镜像
docker pull
  • 保存容器为一个新的 image
docker commit
  • 推送容器到 registry
docker push
  • 查看本地所有 docker container 列表
docker ps -a
  • 运行 | 停止 | 重启 已经存在的 docker container
docker run | stop | restart <ContainerID>

部署一个 Docker 应用

对于开发者来说,我们无需关注应用的依赖环境,就能使用 Docker 快速部署一个应用。

使用 Nginx 镜像启动一个容器

docker run -d -p 80:80 --name webserver nginx

使用 Ghost 镜像启动一个容器

docker run -d -p 80:2368 --name myblog ghost

使用 MySQL 镜像启动一个容器

docker run -d -p 3306:3306 --name sqlserver -e MYSQL_ROOT_PASSWORD=password mysql

Volume

Docker 镜像是由多个文件系统(只读层)叠加而成。当我们启动一个容器的时候,Docker 会加载只读镜像层并在其上(译者注:镜像栈顶部)添加一个读写层。如果运行中的容器修改了现有的一个已经存在的文件,那该文件将会从读写层下面的只读层复制到读写层,该文件的只读版本仍然存在,只是已经被读写层中该文件的副本所隐藏。当删除Docker容器,并通过该镜像重新启动时,之前的更改将会丢失。

在 Docker 中,只读层及在顶部的读写层的组合被称为 Union File System(联合文件系统)。

为了能够保存(持久化)数据以及共享容器间的数据,Docker 提出了 Volume 的概念。简单来说,Volume 就是目录或者文件,它可以绕过默认的联合文件系统,而以正常的文件或者目录的形式存在于宿主机上。

Volume 并不是为了持久化,Volume 的目标是可以将容器以及容器产生的数据分离开来,这样,当你使用 docker rm my_container 删除容器时,不会影响相关的数据。

编写 DockerFile

进入 docker 容器:

docker exec -it webserver bash

修改 Nginx 默认页面:

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

发现默认页面已经更新了。

现在我们也可以使用 docker commit 来生成新的镜像:

docker commit -a "slark" -m "update default nginx page" webserver nginx:v2

可以使用 docker diff <image name> 来查看变更。