《精通Docker第三版》完整目录:
第一章 Docker概览
第二章 创建容器镜像
第三章 存储和发布镜像
第四章 管理容器
第五章 Docker Compose
第六章 Windows容器
第七章 Docker Machine
第八章 Docker Swarm
第九章 Docker和Kubernetes
第十章 在公有云上运行Docker
第十一章 Portainer – 一个Docker的GUI
第十二章 Docker安全
第十三章 Docker工作流
第十四章 Docker进阶
本章中我们将深入地学习Docker Machine,讲解前面章节中还没讲到内容。可以很容易地使用它来在不同平台的本地或云端环境上启动或初始配置Docker主机。我们也可以使用它来控制Docker主机。我们来看看本章所涵盖的主要内容:
- Docker Machine的介绍
- 使用Docker Machine来设置Docker主机
- 在云端启动Docker主机
- 使用其它基操作系统
技术准备
和其它章节一样,我们将继续使用本地安装的 Docker。同样,本章的所有截图都来自我个人偏好的操作系统macOS。
我们会一起来看如何使用Docker Machine来启动基于Docker的虚拟主机,既可以使用本地的VirtualBox也可以使用公有云,所以如果你想要照着本章的示例进行操作的话会需要有一个Digital Ocean的账户。
像之前一样,我们使用的所有Docker命令在读者进行安装的三种操作系统上都可以运行。但是其中有少部分的支持命令,仅在macOS和Linux操作系统上可以使用。
观看如下视频来查看实时操作效果:
Docker Machine的介绍
在我们撸起袖子深入学习Docker Machine之前,先来讨论下它在整个Docker生态系统中所处的地位。
Docker Machine最大的优势是它为许多公有云提供商提供了连续性的界面,如 AWS, DigitalOcean, Microsoft Azure和Google Cloud,也包括一些自己托管的虚拟主机/云平台,包括OpenStack和VMware vSphere。此外,也支持以下本地托管的hypervisor,如Oracle VirtualBox和VMware Workstation或Fusion。
如果你某一天需要快速访问 AWS 上的Docker主机,而另一天需要在DigitialOcean上使用,通过一条命令以最小化的用户交互来应对所有这些技术很非常的节约时间,你所获得的体验是一致的。
因为它是一个命令行工具,将指令发送给同事或者甚至是发送Docker主机上启动和分解的脚本都会非常容易:想象一下每天早上以一个全新构建的环境进行操作,然后又在晚上进行删除来节约成本。
部署本地Docker Machine的Docker主机
在我们开启云端旅程之前,先通过在本地启动Docker Machine 来了解它的基本知识,这里使用VirtualBox来提供虚拟主机。
ℹ️VirtualBox是来自甲文公司一款免费的虚拟化产品。它允许我们跨平台和在不同的CPU类型上安装虚拟机。通过https://www.virtualbox.org/wiki/Downloads/来下载并安装VirtualBox。
要启动该机器,我们只需要运行如下命令:
1 |
$ docker-machine create --driver virtualbox docker-local |
这时会开始部署,在部署期间可以看到Docker Machine运行的任务列表。在启动Docker主机时,Docker Machine所启动的每个主机都会经历相同的步骤。
首先,Docker Machine运行一些基础检查,如确认VirtualBox已安装,创建证书和存储文件及虚拟机的目录结构:
1 2 3 4 |
Creating CA: /Users/alan/.docker/machine/certs/ca.pem Creating client certificate: /Users/alan/.docker/machine/certs/cert.pem Running pre-create checks... (docker-local) Image cache directory does not exist, creating it at /Users/alan/.docker/machine/cache... |
然后会检查用于虚拟机的镜像是否存在。如不存在,则会下载该镜像:
1 2 3 4 5 |
Running pre-create checks... (docker-local) Default Boot2Docker ISO is out-of-date, downloading the latest release... (docker-local) Latest release for github.com/boot2docker/boot2docker is v18.09.5 (docker-local) Downloading /Users/alan/.docker/machine/cache/boot2docker.iso from https://github.com/boot2docker/boot2docker/releases/download/v18.09.5/boot2docker.iso... (docker-local) 0%....10%....20%....30%....40%....50%....60%....70%....80%....90%....100% |
检查通过后,会使用所选驱动来创建虚拟机:
1 2 3 4 5 6 7 8 |
Creating machine... (docker-local) Copying /Users/alan/.docker/machine/cache/boot2docker.iso to /Users/alan/.docker/machine/machines/docker-local/boot2docker.iso... (docker-local) Creating VirtualBox VM... (docker-local) Creating SSH key... (docker-local) Starting the VM... (docker-local) Check network to re-create if needed... (docker-local) Waiting for an IP... Waiting for machine to be running, this may take a few minutes... |
可以看到,Docker Machine为虚拟机创建一个独立的SSH key。这表示你可以通过SSH来连接虚拟机,后面会讨论。启动了虚拟机之后,Docker Machine会连接虚拟机:
1 2 3 4 5 6 7 8 |
detecting operating system of created instance... Waiting for SSH to be available... Detecting the provisioner... Provisioning with boot2docker... Copying certs to the local machine directory... Copying certs to the remote machine... Setting Docker configuration on the remote daemon... Checking connection to Docker... |
可以看到,Docker Machine 检测所使用的操作系统并选择对应的启动脚本来部署Docker。安装了Docker后,Docker Machin生成证书并在本机和Docker主机之间分享证书。然后它配置远程Docker安装来完成证书认证,也就是说你本地的客户端可以与远程的Docker服务器进行连接和交互:
1 2 |
Docker is up and running! To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env docker-local |
最后,它会检查本地Docker客户端是否能进行远程连接并通过发送指令来对新启动的Docker主机进行本地客户端的配置来完成任务。
如是你打开VirtualBox,可以看到新的虚拟机:
接下来,我们需要配置本地Docker客户端来连接新启动的Docker主机,在启动主机的输出中也提到了,运行如下命令会显示如何进行连接:
1 |
$ docker-machine env docker-local |
该命令会返回如下内容:
1 2 3 4 5 6 |
export DOCKER_TLS_VERIFY="1" export DOCKER_HOST="tcp://192.168.99.100:2376" export DOCKER_CERT_PATH="/Users/alan/.docker/machine/machines/docker-local" export DOCKER_MACHINE_NAME="docker-local" # Run this command to configure your shell: # eval $(docker-machine env docker-local) |
这会通过提供新启动Docker主机的IP地址和端口号以及用于认证的证书路径来重载本地Docker安装。在输出的最后,给出了一条运行配置终端会话来进行连接的命令。
在运行该命令之前,我们先运行docker version 来查看当前设置的信息:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ docker version Client: Docker Engine - Community Version: 18.09.2 API version: 1.39 Go version: go1.10.8 Git commit: 6247962 Built: Sun Feb 10 04:12:39 2019 OS/Arch: darwin/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 18.09.2 API version: 1.39 (minimum version 1.12) Go version: go1.10.6 Git commit: 6247962 Built: Sun Feb 10 04:13:06 2019 OS/Arch: linux/amd64 Experimental: true |
这是我所运行的Docker for Mac安装。运行如下命令,然后再次运行docker version应该会显示一些变化:
1 |
$ eval $(docker-machine env docker-local) |
该命令的输出信息如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
API version: 1.39 Go version: go1.10.8 Git commit: 6247962 Built: Sun Feb 10 04:12:39 2019 OS/Arch: darwin/amd64 Experimental: false Server: Docker Engine - Community Engine: Version: 18.09.5 API version: 1.39 (minimum version 1.12) Go version: go1.10.8 Git commit: e8ff056dbc Built: Thu Apr 11 04:50:00 2019 OS/Arch: linux/amd64 Experimental: false |
可以看到,Docker Machine所启动的服务器与本地安装的基本一致,事实上,主要的区别是构建时间。可以看到我的Docker for Mac 软件上的Docker引擎二进制和Docker Machine版本是不同的。
此处,我们可以像本地Docker软件一样与Docker主机进行交互。在进入到云端启动Docker主机之前,还有一些Docker Machine的基本命令需要讲解。
第一个命令列出当前所配置的Docker主机:
1 |
$ docker-machine ls |
该命令的输出内容如下:
1 2 3 |
$ docker-machine ls NAME ACTIVE DRIVER STATE URL SWARM DOCKER ERRORS docker-local * virtualbox Running tcp://192.168.99.100:2376 v18.09.5 |
可以看到,它显示了一些明细信息:机器名、所使用的驱动、Docker接入点URL以及主机上所运行的Docker版本。
你还注意到在ACTIVE一栏下有一个*,这表示当前客户所配置进行交互的Docker主机。你还可以通过运行docker-machine active来查看活跃的机器。
下一条命令可使用SSH与Docker主机连接:
1 |
$ docker-machine ssh docker-local |
该命令的输出如下:
1 2 3 4 5 6 |
$ docker-machine ssh docker-local ( '>') /) TC (\ Core is distributed with ABSOLUTELY NO WARRANTY. (/-_--_-\) www.tinycorelinux.net docker@docker-local:~$ |
这对于需要安装其它软件或在Docker Machine以外进行配置非常的有用。在需要查看日志等信息时也非常有用,因为你可以通过运行 exit 随时退出远程shell。还可以在回到本机后运行如下命令来查看你的Docker主机的 IP 地址:
1 |
$ docker-machine ip docker-local |
我们在本章后面会使用到。还有一些命令用于查看Docker主机的更多信息:
1 2 3 4 |
$ docker-machine inspect docker-local $ docker-machine config docker-local $ docker-machine status docker-local $ docker-machine url docker-local |
最后,还有用于停止、启动、重启和删除Docker主机的命令。使用最后一条命令来删除本地启动的主机:
1 2 3 4 |
$ docker-machine stop docker-local $ docker-machine start docker-local $ docker-machine restart docker-local $ docker-machine rm docker-local |
docker-machine rm命令会提示让你确定是否真的要删除该实例:
1 2 3 4 5 |
$ docker-machine rm docker-local About to remove docker-local WARNING: This action will delete both local reference and remote instance. Are you sure? (y/n): y Successfully removed docker-local |
我们已快速地了解这些基础知识,下面来尝试一些更具挑战性的。
在云端启动Docker主机
这一部分中,我们来看Docker Machine所支持的一种公有云驱动器。前面已经提到过,有很多种可以使用的,但Docker Machine所带来的体验是连贯的,所以这些驱动器之间并没有什么分别。
我们将使用Docker Machine来在DigitalOcean上启动Docker主机。唯一需要做的是获取一个API访问令牌。这里不再说明如何进行生成,新参照https://www.digitalocean.com/help/api/上的教程。
ℹ️使用API令牌启动Docker主机会产生费用,请确保对所启动过的Docker主机有记录。DigitalOcean价格相关的信息请参见https://www.digitalocean.com/pricing/。同时,保留API令牌密钥,因为它可用于获取账户未授权访问。本章中所使用的所有令牌均已做撤销。
首先我们要做的是将令牌设置为环境变量,这样就不需要反复输入了。通过如下命令即可设置环境变量,但请记得将API令牌替换成你自己的:
1 |
$ DOTOKEN=0cb54091fecfe743920d0e6d28a29fe325b9fc3f2f6fccba80ef4b26d41c7224 |
ℹ️因为我需要向Docker Machine传递其它参数。这里会使用 \ 来将命令分隔为多行以提高可读性。
启动一个名为docker-digtialocean的Docker主机,我们需要运行如下命令:
1 2 3 4 |
$ docker-machine create \ --driver digitalocean \ --digitalocean-access-token $DOTOKEN \ docker-digitalocean |
因Docker主机是一台远程的机器,会需要花费一点时间来启动、配置以进行访问。可以从下面的输出中看到,在Docker Machine启动Docker主机时会发生一些修改:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
Running pre-create checks... Creating machine... (docker-digitalocean) Creating SSH key... (docker-digitalocean) Creating Digital Ocean droplet... (docker-digitalocean) Waiting for IP address to be assigned to the Droplet... Waiting for machine to be running, this may take a few minutes... Detecting operating system of created instance... Waiting for SSH to be available... Detecting the provisioner... Provisioning with ubuntu(systemd)... Installing Docker... Copying certs to the local machine directory... Copying certs to the remote machine... Setting Docker configuration on the remote daemon... Checking connection to Docker... Docker is up and running! To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env docker-digitalocean |
启动之后,就可以在DigitalOcean的控制面板中看到该Docker主机了:
通过运行如下命令来重新配置本地客户端以连接到远程主机:
1 |
$ eval $(docker-machine env docker-digitalocean) |
同时,你可以运行docker version和docker-machine inspect docker-digitalocean来查看Docker主机的更多信息。
最后,运行docker-machine ssh docker-digitalocean可以通过SSH连接到主机。从以下输出以及在初次启动Docker主机的输出中可以看出,使用的操作系统存在不同:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
$ docker-machine ssh docker-digitalocean Welcome to Ubuntu 16.04.6 LTS (GNU/Linux 4.4.0-145-generic x86_64) * Documentation: https://help.ubuntu.com * Management: https://landscape.canonical.com * Support: https://ubuntu.com/advantage Get cloud support with Ubuntu Advantage Cloud Guest: http://www.ubuntu.com/business/services/cloud 29 packages can be updated. 10 updates are security updates. New release '18.04.2 LTS' available. Run 'do-release-upgrade' to upgrade to it. root@docker-digitalocean:~# |
可以通过运行exit来退出远程shell。刚刚我们并没有告诉Docker Machine使用什么操作系统、Docker主机的大小、甚至是在哪个区域进行启动。这是因每个驱动器都有默认的选项。添加这些默认选项后命令如下:
1 2 3 4 5 6 7 8 9 10 11 12 |
$ docker-machine create \ --driver digitalocean \ --digitalocean-access-token $DOTOKEN \ --digitalocean-image ubuntu-16-04-x64 \ --digitalocean-region nyc3 \ --digitalocean-size 512mb \ --digitalocean-ipv6 false \ --digitalocean-private-networking false \ --digitalocean-backups false \ --digitalocean-ssh-user root \ --digitalocean-ssh-port 22 \ docker-digitalocean |
可以看到,你可以自定义大小、区域和操作系统,甚至是还是启动Docker主机使用的网络。假设我们想要修改操作系统和droplet的大小。本例中,我们可以运行如下命令:
译者注:droplet是DigitalOcean对于其上所创建主机的称呼
1 2 3 4 5 6 |
$ docker-machine create \ --driver digitalocean \ --digitalocean-access-token $DOTOKEN \ --digitalocean-image ubuntu-18-04-x64 \ --digitalocean-size 1gb \ docker-digitalocean |
可以在DigitalOcean的控制面板中查看到,这会启动一台如下的机器:
你可以通过运行如下命令来删除DigitalOcean上的Docker主机:
1 |
$ docker-machine rm docker-digitalocean |
使用其它基操作系统
你无面使用Docker Machine的默认操作系统,它还包含一些其它基操作系统的提供商,包括那些可配置来运行容器的。在结束本章之前,我们先来看下启动其它的一种系统,CoreOS。
我们将使用的发行版仅包含足够用于运行内核、网络栈和容器的操作系统,类似于Docker自己的MobyOS,它用作Docker for Mac和Docker for Windows的基操作系统。
虽然CoreOS支持它自己的容器运行时,称为RKT(读作Rocket),它也支持 Docker。但是,我们会看到,Docker当前使用的CoreOS稳定版本有点老了。
启动DigitalOcean管理的coreos-stable版,运行如下命令:
1 2 3 4 5 6 7 |
$ docker-machine create \ --driver digitalocean \ --digitalocean-access-token $DOTOKEN \ --digitalocean-image coreos-stable \ --digitalocean-size 1GB \ --digitalocean-ssh-user core \ docker-coreos |
和在公有云上启动其它Docker主机一样,输出基本相同。你可以看到Docker Machine使用了CoreOS的提供商:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
Running pre-create checks... Creating machine... (docker-coreos) Creating SSH key... (docker-coreos) Creating Digital Ocean droplet... (docker-coreos) Waiting for IP address to be assigned to the Droplet... Waiting for machine to be running, this may take a few minutes... Detecting operating system of created instance... Waiting for SSH to be available... Detecting the provisioner... Provisioning with coreOS... Copying certs to the local machine directory... Copying certs to the remote machine... Setting Docker configuration on the remote daemon... Checking connection to Docker... Docker is up and running! To see how to connect your Docker Client to the Docker Engine running on this virtual machine, run: docker-machine env docker-coreos |
启动之后,可以运行如下命令:
1 |
$ docker-machine ssh docker-coreos cat /etc/*release |
这会返回release文件中的内容:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
DISTRIB_ID="Container Linux by CoreOS" DISTRIB_RELEASE=2079.3.0 DISTRIB_CODENAME="Rhyolite" DISTRIB_DESCRIPTION="Container Linux by CoreOS 2079.3.0 (Rhyolite)" NAME="Container Linux by CoreOS" ID=coreos VERSION=2079.3.0 VERSION_ID=2079.3.0 BUILD_ID=2019-04-22-2119 PRETTY_NAME="Container Linux by CoreOS 2079.3.0 (Rhyolite)" ANSI_COLOR="38;5;75" HOME_URL="https://coreos.com/" BUG_REPORT_URL="https://issues.coreos.com" COREOS_BOARD="amd64-usr" |
运行如下命令会显示在CoreOS主机上运行的Docker版本的更多信息:
1 |
$ docker $(docker-machine config docker-coreos) version |
可以从如下输出中看到,我们也讲到,这个版本是有些老的:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
$ docker $(docker-machine config docker-coreos) version Client: Docker Engine - Community Version: 18.09.2 API version: 1.38 (downgraded from 1.39) Go version: go1.10.8 Git commit: 6247962 Built: Sun Feb 10 04:12:39 2019 OS/Arch: darwin/amd64 Experimental: false Server: Engine: Version: 18.06.3-ce API version: 1.38 (minimum version 1.12) Go version: go1.10.8 Git commit: d7080c1 Built: Tue Feb 19 23:07:53 2019 OS/Arch: linux/amd64 Experimental: false |
这表示本书中的有些命令在这里可能用不了。运行如下命令来删除CoreOS主机:
1 |
$ docker-machine rm docker-coreos |
总结
本章中,我们学习了如何使用Docker Machine来在本地的VirtualBox上创建Docker主机,并回顾了可以与Docker Machine所启动的Docker主机进行交互和管理所使用的命令。
然后我们一起来看了如何使用Docker Machine来部署Docker主机到云端的环境,这里使用的是DigitalOcean。最后,我们快速地查看了如何启动一个不同的对容器优化过的操作系统,上面使用了CoreOS。
相信读者也会认可使用Docker Machine让这些任务(存在着不同方法)具有一致性的体验,从长远看,这会节约大量的时间以及说明。
下一章中,我们将告别单个Docker主机的交互,来启动和运行一个Docker Swarm集群。
课后问题
- 在运行docker-machine create命令时,使用哪个标记来定义Docker Machine用于启动Docker主机的服务或提供商?
- 是非题:运行docker-machine env my-hos会重新配置与my-host交互的本地Docker客户端?
- 说明Docker Machine背后的基本原理。
扩展阅读
有关各平台对Docker Machine的支持信息,参见如下链接:
- Amazon Web Services: https://aws.amazon.com/
- Microsoft Azure: https://azure.microsoft.com/
- DigitalOcean: https://www.digitalocean.com/
- Exoscale: https://www.exoscale.ch/
- Google Compute Engine: https://cloud.google.com/
- Rackspace: https://www.rackspace.com/
- IBM SoftLayer: https://www.softlayer.com/
- Microsoft Hyper-V: https://www.microsoft.com/en-us/cloud-platform/server-virtualization
- OpenStack: https://www.openstack.org/
- VMware vSphere: https://www.vmware.com/uk/products/vsphere.html
- Oracle VirtualBox: https://www.virtualbox.org/
- VMware Fusion: https://www.vmware.com/uk/products/fusion.html
- VMware Workstation: https://www.vmware.com/uk/products/workstation.html
- CoreOS: https://coreos.com/