到目前为止,我们一直忙于学习所有关于 Docker 的知识。影响开源项目寿命的一个主要因素是它周围的社区。Docker 的创作者,Docker Inc .(dot cloud 的分支),负责开发和维护 Docker 及其姊妹项目如 libcontainer、libchan、swarm 等(完整列表可在github.com/docker找到)。然而,像任何其他开源项目一样,开发是开放的(在 GitHub 中),它们接受拉请求。
该行业也接受了 Docker。谷歌、亚马逊、微软、易贝和红帽等巨头积极使用 Docker 并为其做出贡献。大多数流行的 IaaS 解决方案,如亚马逊网络服务、谷歌计算云等,都支持创建预装 Docker 并针对 Docker 进行优化的映像。许多初创企业也在将自己的命运押在 Docker 身上。CoreOS、Drone.io 和 Shippable 是一些初创公司,它们被建模为基于 Docker 提供服务。所以你可以放心,它不会很快消失。
在本章中,我们将讨论围绕 Docker 的一些项目以及如何使用它们。我们还将关注您可能已经熟悉的项目,这些项目可以促进您的 Docker 工作流程(并使您的生活更加轻松)。
首先,我们将与 Docker 谈论使用厨师和木偶食谱。你们中的许多人可能已经在工作流程中使用了这些工具。本节将帮助您将 Docker 与您当前的工作流相集成,并帮助您轻松融入 Docker 生态系统。
接下来,我们将尝试设置一个 apt-cacher ,这样我们的 Docker 构建就不会花费大量时间从 Canonical 服务器获取经常使用的包。这将大大减少从 Dockerfiles 构建映像所需的时间。
在早期阶段,让 Docker 大肆宣传的一件事是,当用 Docker 实现时,一些已知很难的事情看起来是多么容易。其中一个项目就是 Dokku ,一个 100 行的 bash 脚本,建立了一个像 PaaS 一样的迷你 - Heroku 。在本章中,我们将使用 Dokku 设置我们自己的 PaaS。我们将在本书中讨论的最后一件事是使用 CoreOS 和 Fleet 部署高可用性服务。
简而言之,在我们旅程的最后一段,我们将关注以下主题:
- 厨师和木偶一起使用 Docker
- 设置一个合适的缓存器
- 建立你自己的迷你英雄库
- 设置高可用性服务
当企业开始向云迁移时,扩展变得更加容易,因为人们可以毫不费力地从一台机器扩展到数百台机器。但这也意味着配置和维护这些机器。配置管理工具(如 Chef 和 Puppet)源于在公共/私有云中自动部署应用的需求。如今,世界各地的初创企业和公司每天都在使用 Chef 和 Puppet 来管理他们的云环境。
厨师网站声明如下:
“厨师”将基础设施转化为代码。借助 Chef,您可以自动构建、部署和管理您的基础架构。您的基础架构变得像应用代码一样可版本化、可测试和可重复。”
现在,假设您已经设置了厨师,并且熟悉厨师工作流程,让我们看看如何使用厨师-docker 烹饪书对厨师使用 Docker。
您可以用任何一本食谱依赖管理器安装这本食谱。烹饪书(https://supermarket.getchef.com/cookbooks/docker)的厨师社区网站上提供了伯克架、图书管理员和小刀的安装说明。
安装 Docker 很简单。只需将recipe[docker]
命令添加到您的运行列表(配置设置列表)中。一个例子抵得上一百万字,那么我们来看看如何编写一个厨师食谱,在 Docker 上运行code.it
文件(我们的示例项目)。
以下厨师食谱基于code.it
启动容器:
# Include Docker recipe
include_recipe 'docker'
# Pull latest image
docker_image 'shrikrishna/code.it'
# Run container exposing ports
docker_container 'shrikrishna/code.it' do
detach true
port '80:8000'
env 'NODE_PORT=8000'
volume '/var/log/code.it:/var/log/code.it'
end
第一个无评论声明包括厨师-Docker 食谱。docker_image 'shrikrishna/code.it'
语句相当于在控制台运行$ docker pull shrikrishna/code.it
命令。食谱末尾的语句块相当于运行$ docker run --d -p '8000:8000' -e 'NODE_PORT=8000' -v '/var/log/code.it:/var/log/code.it' shrikrishna/code.it
命令。
PuppetLabs 的网站声明如下:
“Puppet”是一个配置管理系统,允许您定义 IT 基础架构的状态,然后自动强制执行正确的状态。无论您管理的是几台服务器还是成千上万台物理机和虚拟机,Puppet 都可以自动执行系统管理员通常手动执行的任务,从而释放时间和精神空间,让系统管理员可以从事能够带来更大业务价值的项目。”
木偶相当于厨师烹饪书的是模块。Docker 有一个支持良好的模块。它的安装通过运行以下命令来完成:
$ puppet module install garethr-docker
以下傀儡清单启动一个code.it
容器:
# Installation
include 'docker'
# Download image
docker::image {'shrikrishna/code.it':}
# Run a container
docker::run { 'code.it-puppet':
image => 'shrikrishna/code.it',
command => 'node /srv/app.js',
ports => '8000',
volumes => '/var/log/code.it'
}
第一个非注释语句包括docker
模块。docker::image {'shrikrishna/code.it':}
语句相当于在控制台运行$ docker pull shrikrishna/code.it
命令。配方末尾的语句块相当于运行$ docker run --d -p '8000:8000' -e 'NODE_PORT=8000' -v '/var/log/code.it:/var/log/code.it' shrikrishna/code.it node /srv/app.js
命令。
当你有多个 Docker 服务器时,或者当你构建多个不相关的 Docker 映像时,你可能会发现你每次都要下载包。这可以通过在服务器和客户端之间设置缓存代理来防止。它会在您安装软件包时缓存它们。如果您试图安装一个已经缓存的包,它将由代理服务器本身提供服务,从而减少获取包的延迟并大大加快构建过程。
让我们编写一个 Dockerfile,将 apt 缓存服务器设置为缓存代理服务器:
FROM ubuntu
VOLUME ["/var/cache/apt-cacher-ng"]
RUN apt-get update ; apt-get install -yq apt-cacher-ng
EXPOSE 3142
RUN echo "chmod 777 /var/cache/apt-cacher-ng ;" + "/etc/init.d/apt-cacher-ng start ;" + "tail -f /var/log/apt-cacher-ng/*" >> /init.sh
CMD ["/bin/bash", "/init.sh"]
该 Dockerfile 在映像中安装apt-cacher-ng
包,并暴露端口3142
(供目标容器使用)。
使用以下命令构建映像:
$ sudo docker build -t shrikrishna/apt_cacher_ng
然后运行它,绑定暴露的端口:
$ sudo docker run -d -p 3142:3142 --name apt_cacher shrikrishna/apt_cacher_ng
要查看日志,请运行以下命令:
$ sudo docker logs -f apt_cacher
所以我们设置了一个合适的缓存器。我们现在必须在我们的 Dockerfiles 中使用它:
FROM ubuntu
RUN echo 'Acquire::http { Proxy "http://<host's-docker0-ip- here>:3142"; };' >> /etc/apt/apt.conf.d/01proxy
在第二条指令中,用 Docker 主机的 IP 地址替换<host's-docker0-ip-here>
命令(在docker0
界面)。在构建这个 Dockerfile 时,如果它遇到任何用于之前已经安装的包的apt-get install
安装命令(对于这个映像或任何其他映像),它将从本地代理服务器获取包,而不是使用 Docker 或 Canonical 包存储库,从而加快构建过程中的包安装。如果正在安装的包不在缓存中,那么它将从规范存储库中获取并保存在缓存中。
apt 缓存器只适用于使用 Apt 包管理工具的基于 Debian 的容器(如 Ubuntu)。
现在让我们做一些很酷的事情。对于不熟悉的人来说,Heroku 是一个云 PaaS,这意味着你在构建一个应用时所需要做的就是将它推送到 Heroku,它将被部署到 https://www.herokuapp.com 的 T2。您不需要担心应用如何或在哪里运行。只要 PaaS 支持您的技术栈,您就可以只在本地开发,并将应用推送到服务,使其在公共互联网上实时运行。
除了 Heroku,还有很多 PaaS 提供商。一些受欢迎的提供商是谷歌应用引擎、红帽云和云代工。Docker 就是由这样一个 PaaS 提供商——dot cloud 开发的。几乎每个 PaaS 都是通过在预定义的沙盒环境中运行应用来工作的,这是 Docker 擅长的。今天,Docker 让建立一个 PaaS 变得更容易,如果不是简单的话。证明这一点的项目是 Dokku。Dokku 与 Heroku 共享使用模式和术语(如buildpacks
、slug
builder
脚本),这使得它更容易使用。在这一部分,我们将使用 Dokku 设置一个迷你 PaaS,并推送我们的code.it
应用。
接下来的步骤应该在虚拟T3 私有服务器 ( VPS )或虚拟机上完成。您工作的主机应该设置了 git 和 SSH。
有一个脚本将建立道库。在 VPS/虚拟机器中运行以下命令:
$ wget -qO- https://raw.github.com/progrium/dokku/v0.2.3/bootstrap.sh | sudo DOKKU_TAG=v0.2.3 bash
12.04 版本的用户在运行前面的bootstrapper
脚本之前需要运行$ apt-get install -y python-software-properties
命令。
bootstrapper
脚本将下载所有依赖项并设置 Dokku。
步骤 1:克隆〔t0〕doku:
$ git clone https://github.com/progrium/dokku.git
第二步:在/etc/hosts
文件中设置 SSH 主机:
10.0.0.2 dokku.app
第三步:在~/.ssh/config
设置 SSH 配置
Host dokku.app
Port 2222
步骤 4:创建虚拟机
以下是一些要设置的可选环境参数:
# - `BOX_NAME`
# - `BOX_URI`
# - `BOX_MEMORY`
# - `DOKKU_DOMAIN`
# - `DOKKU_IP`.
cd path/to/dokku
vagrant up
第五步:使用以下命令复制你的 SSH 密钥:
$ cat ~/.ssh/id_rsa.pub | pbcopy
将您的 SSH 密钥粘贴到http://dokku.app
处的 dokku-installer 中(指向/etc/hosts
文件中指定的10.0.0.2
)。将 Dokku Setup 屏幕上的主机名字段更改为您的域,然后选中显示使用 虚拟主机 命名的框。然后,点击完成 设置安装钥匙。您将从这里获得应用部署说明。
您现在可以部署应用或安装插件了。
我们的 PaaS 将路由子域到以相同名称部署的应用。这意味着设置了多库的机器必须对您的本地设置以及运行多库的机器可见。
设置指向 Dokku 主机的通配符域。运行bootstrapper
脚本后,检查 Dokku 主机中的/home/dokku/VHOST
文件是否设置为这个域。只有当主机名可以通过 dig 工具解析时,才会创建。
在本例中,我通过将以下配置添加到(本地主机的)/etc/hosts
文件中,将我的 Dokku 主机名设置为dokku.app
:
10.0.0.2 dokku.app
我还在~/.ssh/config
文件(本地主机的)中设置了 SSH 端口转发规则:
Host dokku.app
Port 2222
根据维基百科,域 信息 Groper ( 挖)是一个网络管理命令行工具,用来查询 DNS 名称服务器。这意味着给定一个网址,dig 将返回该网址指向的服务器的 IP 地址。
如果/home/dokku/VHOST
文件还没有自动创建,您将不得不手动创建它并将其设置为您喜欢的域名。如果在部署应用时缺少该文件,Dokku 将使用端口名而不是子域发布应用。
最后要做的是将您的公共ssh
密钥上传到 Dokku 主机,并将其与用户名相关联。为此,请运行以下命令:
$ cat ~/.ssh/id_rsa.pub | ssh dokku.app "sudo sshcommand acl-add dokku shrikrishna"
在前面的命令中,用您的域名替换dokku.app
名称,用您的名称替换shrikrishna
。
太好了。现在我们已经准备就绪,是时候部署我们的应用了。
我们现在有了自己的平台即服务,可以部署我们的应用。让我们在那里部署code.it
文件。您也可以尝试在那里部署自己的应用:
$ cd code.it
$ git remote add dokku dokku@dokku.app:codeit
$ git push dokku master
Counting objects: 456, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (254/254), done.
Writing objects: 100% (456/456), 205.64 KiB, done.
Total 456 (delta 34), reused 454 (delta 12)
-----> Building codeit ...
Node.js app detected
-----> Resolving engine versions
......
......
......
-----> Application deployed:
http://codeit.dokku.app
就这样!我们现在在我们的 PaaS 中有一个工作应用。关于多库的更多细节,你可以在https://github.com/progrium/dokku查看的 GitHub 存储库页面。
如果您想要一个生产就绪的 PaaS,您必须在http://deis.io/查找 Deis,它提供多主机和多租户支持。
虽然 Dokku 很适合部署偶尔的辅助项目,但它可能不适合更大的项目。大规模部署基本上有以下要求:
- 横向 可扩展:单个服务器实例只能完成这么多工作。随着负载的增加,处于曲棍球棒增长曲线上的组织将发现自己不得不在服务器集群之间平衡负载。在早期,这意味着必须设计数据中心。如今,这意味着向云中添加更多实例。
- 故障 宽容:正如道路事故即使在有广泛的交通规则来避免事故发生时也会发生一样,即使在你采取广泛的措施来预防事故后,也可能会发生撞车事故,但是其中一种情况下的撞车事故不得造成服务停机。一个设计良好的架构将处理故障情况,并使另一台服务器代替崩溃的服务器。
- 模块化:虽然看起来不是这样,但是模块化是大规模部署的一个决定性特征。模块化体系结构使其灵活且经得起未来考验(因为模块化体系结构将随着组织范围和范围的扩大而容纳更新的组件)。
这绝不是一个详尽的列表,但它标志着构建和部署一个高可用性服务所需的工作量。然而,正如我们到目前为止所看到的,Docker 在单个主机中使用,并且其中(到目前为止)没有可用的工具来管理运行 Docker 的实例集群。
这就是 CoreOS 的用武之地。这是一个最小化的操作系统,其唯一目的是作为 Docker 上大规模服务部署的构建模块。它附带了一个名为etcd
的高可用性键值配置存储,用于配置管理和服务发现(发现集群中每个其他组件的位置)。 etcd
服务在第 4 章、自动化和最佳实践中进行了探索。它还附带了 fleet,这是一种利用etcd
在整个集群上执行操作的工具,而不是在单个实例上执行操作。
你可以把 fleet 看作是systemd
套件的扩展,它在集群级别而不是机器级别运行。systemd
套件是一个单机初始化系统,而 fleet 是一个集群初始化系统。你可以在https://coreos.com/using-coreos/clustering/找到更多关于舰队的信息。
在本节中,我们将尝试在本地主机的三节点 CoreOS 集群上部署我们的标准示例code.it
。这是一个典型的例子,实际的多主机部署将需要更多的工作,但这是一个很好的起点。它还帮助我们欣赏多年来在硬件和软件方面所做的出色工作,使部署高可用性服务成为可能,甚至变得容易,直到几年前,这项任务还只能在大型数据中心才能完成。
运行前面的示例需要以下依赖关系:
-
VirtualBox:VirtualBox 是一款流行的虚拟机管理软件。您平台的安装可执行文件可以从https://www.virtualbox.org/wiki/Downloads下载。
-
游民:游民是一个开放的源码工具,可以认为是一个虚拟机相当于 Docker。可从https://www.vagrantup.com/downloads.html下载。
-
Fleetctl :简单来说,Fleet 就是一个分布式的 init 系统,这意味着它将允许我们在集群级别管理服务。Fleetctl 是一个命令行界面客户端,用于运行舰队命令。要安装 fleetctl,请运行以下命令:
$ wget \ https://github.com/coreos/fleet/releases/download/v0.3.2/fleet -v0.3.2-darwin-amd64.zip && unzip fleet-v0.3.2-darwin-amd64.zip $ sudo cp fleet-v0.3.2-darwin-amd64/fleetctl /usr/local/bin/
游民相当于 Dockerfiles。游民文件包含详细信息,如要获取的基本虚拟机、要运行的安装命令、要启动的虚拟机映像的实例数等。CoreOS 有一个存储库,其中包含可用于在虚拟机中下载和使用 CoreOS 的游民文件。这是在开发环境中尝试 CoreOS 特性的理想方式:
$ git clone https://github.com/coreos/coreos-vagrant/
$ cd coreos-vagrant
前面的命令克隆了coreos-vagrant
存储库,该存储库包含下载和启动基于 CoreOS 的虚拟机的游民文件。
游民是一款免费开源软件,用于创建和配置虚拟开发环境。它可以被视为虚拟化软件(如 VirtualBox、KVM 或 VMware)和配置管理软件(如 Chef、Salt 或 Puppet)的包装器。你可以从https://www.vagrantup.com/downloads.html下载游民。
在启动虚拟机之前,我们需要做一些配置。
每个 CoreOS 主机运行一个etcd
服务实例,以协调在该机器上运行的服务,并与集群中其他机器上运行的服务进行通信。为此,etcd
实例本身需要相互发现。
CoreOS 团队已经构建了一个发现服务(https://discovery . etcd . io),该服务通过存储对等体信息来提供一个免费服务来帮助etcd
实例相互通信。它通过提供标识集群的唯一令牌来工作。集群中的每个etcd
实例使用发现服务使用该令牌来标识其他每个etcd
实例。生成令牌很简单,只需向discovery.etcd.io/new发送GET
请求即可:
$ curl -s https://discovery.etcd.io/new
https://discovery.etcd.io/5cfcf52e78c320d26dcc7ca3643044ee
现在打开coreos-vagrant
目录中名为user-data.sample
的文件,找到etcd
服务下保存discovery
配置选项的注释行。取消注释并提供从先前运行的curl
命令返回的令牌。完成后,将文件重命名为user-data
。
user-data
文件用于在 CoreOS 实例中为cloud-config
程序设置配置参数。Cloud-config 的灵感来自于cloud-init
项目中的cloud-config
文件,它将自己定义为事实上的多发行版包,处理云实例的早期初始化(cloud-init
文档)。简而言之,它有助于配置各种参数,如要打开的端口,以及在 CoreOS 的情况下,etcd
配置等。您可以在以下网址找到更多信息:
https://coreos . com/docs/cluster-management/setup/cloudinit-cloud-config/和http://cloudinit.readthedocs.org/en/latest/index.html。
以下是 CoreOS 的代码示例:
coreos:
etcd:
# generate a new token for each unique cluster from https://discovery.etcd.io/new
# WARNING: replace each time you 'vagrant destroy'
discovery: https://discovery.etcd.io/5cfcf52e78c320d26dcc7ca3643044ee
addr: $public_ipv4:4001
peer-addr: $public_ipv4:7001
fleet:
public-ip: $public_ipv4
units:
每次运行集群时,您将有生成新令牌。简单地重用令牌是行不通的。
在coreos-vagrant
目录下,还有一个名为config.rb.sample
的文件。在这个文件中找到注释行,上面写着$num_instances=1
。取消注释,并将值设置为3
。这将使游民产生三个 CoreOS 实例。现在将文件保存为config.rb
。
cnfig.rb
文件保存游民环境的配置和集群中的机器数量。
下面是游民实例的代码示例:
# Size of the CoreOS cluster created by Vagrant
$num_instances=3
现在我们已经准备好了配置,是时候看到集群在您的本地机器上运行了:
$ vagrant up
Bringing machine 'core-01' up with 'virtualbox' provider...
Bringing machine 'core-02' up with 'virtualbox' provider...
Bringing machine 'core-03' up with 'virtualbox' provider...
==> core-01: Box 'coreos-alpha' could not be found. Attempting to find and install...
core-01: Box Provider: virtualbox
core-01: Box Version: >= 0
==> core-01: Adding box 'coreos-alpha' (v0) for provider: virtualbox
. . . . .
. . . . .
. . . . .
创建机器后,您可以在其中进行 SSH 来尝试以下命令,但是您需要向您的 SSH 代理添加ssh
密钥。这样做将允许将您的 SSH 会话转发到集群中的其他节点。要添加密钥,请运行以下命令:
$ ssh-add ~/.vagrant.d/insecure_private_key
Identity added: /Users/CoreOS/.vagrant.d/insecure_private_key (/Users/CoreOS/.vagrant.d/insecure_private_key)
$ vagrant ssh core-01 -- -A
现在,让我们验证机器是否启动,并要求 fleet 列出群集中运行的机器:
$ export FLEETCTL_TUNNEL=127.0.0.1:2222
$ fleetctl list-machines
MACHINE IP METADATA
daacff1d... 172.17.8.101 -
20dddafc... 172.17.8.102 -
eac3271e... 172.17.8.103 -
要在新启动的集群中运行服务,您必须编写unit-files
文件。单元文件是配置文件,列出了必须在每台机器上运行的服务以及一些关于如何管理这些服务的规则。
创建三个名为code.it.1.service
、code.it.2.service
和code.it.3.service
的文件。用以下配置填充它们:
code.it.1.service
[Unit]
Description=Code.it 1
Requires=docker.service
After=docker.service
[Service]
ExecStart=/usr/bin/docker run --rm --name=code.it-1 -p 80:8000 shrikrishna/code.it
ExecStartPost=/usr/bin/etcdctl set /domains/code.it-1/%H:%i running
ExecStop=/usr/bin/docker stop code.it-1
ExecStopPost=/usr/bin/etcdctl rm /domains/code.it-1/%H:%i
[X-Fleet]
X-Conflicts=code.it.*.service
code.it.2.service
[Unit]
Description=Code.it 2
Requires=docker.service
After=docker.service
[Service]
ExecStart=/usr/bin/docker run --rm --name=code.it-2 -p 80:8000 shrikrishna/code.it
ExecStartPost=/usr/bin/etcdctl set /domains/code.it-2/%H:%i running
ExecStop=/usr/bin/docker stop code.it-2
ExecStopPost=/usr/bin/etcdctl rm /domains/code.it-2/%H:%i
[X-Fleet]
X-Conflicts=code.it.2.service
code.it.3.service
[Unit]
Description=Code.it 3
Requires=docker.service
After=docker.service
[Service]
ExecStart=/usr/bin/docker run --rm --name=code.it-3 -p 80:8000 shrikrishna/code.it
ExecStartPost=/usr/bin/etcdctl set /domains/code.it-3/%H:%i running
ExecStop=/usr/bin/docker stop code.it-3
ExecStopPost=/usr/bin/etcdctl rm /domains/code.it-3/%H:%i
[X-Fleet]
X-Conflicts=code.it.*.service
你可能已经注意到这些文件中的一个模式。ExecStart
参数保存启动服务必须执行的命令。在我们的例子中,这意味着运行code.it
容器。ExecStartPost
是ExecStart
参数成功后执行的命令。在我们的案例中,服务的可用性在etcd
服务中注册。相反,ExecStop
命令将停止服务,一旦ExecStop
命令成功,则ExecStopPost
命令执行,这意味着从etcd
服务中移除服务的可用性。
X-Fleet
是 CoreOS 特有的语法,告诉 fleet 两个服务不能在同一台机器上运行(因为它们在试图绑定到同一端口时会发生冲突)。现在所有块都已就位,是时候向集群提交作业了:
$ fleetctl submit code.it.1.service code.it.2.service code.it.3.service
让我们验证服务是否已提交给集群:
$ fleetctl list-units
UNIT LOAD ACTIVE SUB DESC MACHINE
code.it.1.service - - - Code.it 1 -
code.it.2.service - - - Code.it 2 -
code.it.3.service - - - Code.it 3 -
机器列为空,未设置激活状态。这意味着我们的服务还没有开始。让我们开始吧:
$ fleetctl start code.it.{1,2,3}.service
Job code.it.1.service scheduled to daacff1d.../172.17.8.101
Job code.it.1.service scheduled to 20dddafc.../172.17.8.102
Job code.it.1.service scheduled to eac3271e.../172.17.8.103
让我们通过再次执行$ fleetctl list-units
文件来验证它们是否正在运行:
$ fleetctl list-units
UNIT LOAD ACTIVE SUB DESC MACHINE
code.it.1.service loaded active running Code.it 1 daacff1d.../172.17.8.101
code.it.1.service loaded active running Code.it 2 20dddafc.../172.17.8.102
code.it.1.service loaded active running Code.it 3 eac3271e.../172.17.8.103
恭喜你!您刚刚建立了自己的集群!现在在网络浏览器中前往172.17.8.101
、172.17.8.102
或172.17.8.103
,并看到code.it
应用正在运行!
在这个例子中,我们只设置了一个运行高可用性服务的机器集群。如果我们添加一个负载平衡器来维护与etcd
服务的连接,以将请求路由到可用的机器,那么我们的系统中将运行一个完整的端到端生产级服务。但是这样做会偏离主题,所以留给你做练习。
就这样,我们走到了最后。Docker 仍在积极开发中,像 CoreOS、Deis、Flynn 等项目也是如此。因此,尽管在过去的几个月里我们已经看到了很棒的东西出现,但接下来会更好。我们生活在激动人心的时代。所以,让我们充分利用它,建造让这个世界变得更美好的东西。航运快乐!
在本章中,我们学习了如何将 Docker 与厨师和木偶一起使用。然后我们设置了一个 apt-cache 来加速包下载。接下来,我们用 Dokku 建立了自己的迷你 PaaS。最后,我们使用 CoreOS 和 Fleet 建立了一个高可用性服务。恭喜你!我们一起获得了 Docker 的必要知识来构建我们的容器,“dockerize”我们的应用,甚至运行集群。我们的旅程到此结束。但是对你来说,亲爱的读者,新的旅程才刚刚开始。这本书旨在为帮助您使用 Docker 构建下一个大项目奠定基础。祝你在这个世界上一切顺利。如果你喜欢这本书,在推特上给我一个爆笑。如果你不喜欢,让我知道我如何能让它变得更好。