使用 Docker 运行 TICK Stack 的技巧
作者:Noah Crowley / 产品,用例,开发者
2018年6月29日
导航至
Docker?Docker docker docker。
尽管 Docker 的热潮已经减退,取而代之的是“Kubernetes”和“无服务器”等新词,但不可否认的是,对于想要开始使用 Linux 容器的开发者来说,Docker 仍然是默认的工具链,因为它相当普遍,并且与各种平台紧密集成。
Linux 容器是由底层 Linux 功能抽象而成的,如 命名空间 和 cgroups,这些功能结合在一起提供了一种操作系统级别的虚拟化;对于您的应用程序来说,似乎它们每一个都在自己的操作系统副本上独立运行。因此,Docker 在直接在宿主机上运行软件之上提供了各种好处;它将您的应用程序与系统中的其余部分以及其他应用程序隔离开,并使得在不同操作系统上部署应用程序变得更加容易。总的来说,它使事物保持整洁、有序和分区良好。
如果您想了解更多关于容器的内容,我强烈推荐阅读 Julia Evans 的 "容器究竟是什么"。
我个人在桌面上运行 Docker,并尽可能多地部署我的应用程序;这不仅清除了我的宿主机上的冗余——我经常需要启动一个新的堆栈来测试特定问题、开发新功能或展示演示,而 Docker 使这变得异常简单。
我还在一个 Raspberry Pi 上运行了 24/7 的 TICK Stack 实例,收集我公寓周围各种传感器的数据。Docker 使保持我的系统清洁以及部署和升级软件变得容易。
Linux 容器和 Docker 是每个开发人员工具箱中应该包含的强大工具。那么我们如何使用它们来运行 TICK Stack 呢?
组件
您需要在您的本地计算机上安装 Docker 和 Docker Compose。Docker 网站提供了关于 macOS 和 Windows 安装的文档,两者都包含 Docker Compose 作为安装的一部分。在 Docker CE 安装文档 中也有关于几种 Linux 变种的说明。在 Linux 上,Docker Compose 是一个独立的安装。
由于 Docker 是 Linux 容器的一种实现,因此它需要 Linux 操作系统来运行。当您在 Windows 或 macOS 上安装 Docker 时,它将设置并管理一个带有 Linux 内核的虚拟机,该虚拟机将运行所有您的容器。在 macOS 上,虚拟机是通过 HyperKit 设置的,而在 Windows 上,虚拟化由 Hyper-V 提供。不幸的是,Hyper-V 只受 Windows 10 企业版、专业版和教育版的支持;运行 Windows 家庭版的用户需要使用传统的 Docker Toolbox。
您可以在 Docker Hub 上找到完整的 TICK Stack 的官方镜像:Telegraf、InfluxDB、Chronograf 和 Kapacitor。与我们在下载页面发布软件包的速度相比,有时镜像出现可能需要更长的时间,所以如果您的时间紧迫,您可能需要维护自己的管道来构建 Docker 镜像,但这超出了本文的范围。
运行容器
有几种方法可以与 Docker 交互并管理您的容器。第一种是使用 docker
可执行文件来发出像 docker run 和 docker stop 这样的命令。第二种方法,我们将在本文的后面部分介绍,是使用 Docker Compose。
如果您已经按照Docker的安装说明完成安装,那么您应该已经使用以下命令启动了hello-world
容器:
$ docker run hello-world
当运行更复杂的软件时,我们通常需要向docker run
命令提供额外的参数来配置容器环境。这可能包括将容器中的端口暴露给Docker主机,或者挂载卷进行持久存储。
Docker网络
首先,我们将设置一个新的Docker网络。Docker自带了一个内置网络,默认情况下所有容器都会连接到这个网络,但为我们的TICK部署创建一个新的网络可以保持它们隔离,同时允许它们相互通信。隔离在很多方面都有好处,但这对进行测试或开发时启动多个堆栈实例特别有帮助。您可以在文档中了解更多关于默认网络和用户定义网络之间的区别[链接]。
我们将使用以下命令创建一个新的网络:
$ docker network create --driver bridge tick-net
该命令使用bridge驱动程序创建一个新的网络,并将其命名为tick-net
。
当我们执行docker run
命令来启动容器时,我们将添加以下参数来将其连接到我们新创建的网络:
--network tick-net
我们还想从容器中公开一些端口到Docker主机,这样我们就可以从外部世界与容器中的应用程序通信。我们将以InfluxDB为例。数据库通过六个不同的端口进行通信,其中两个是默认启用的(用*标记):
端口 | 用途 |
---|---|
8086* | HTTP服务 |
8088* | RPC备份/还原 |
2003 | Graphite服务 |
4242 | OpenTSDB服务 |
8089 | UDP服务 |
25826 | Collectd服务 |
我们不会运行任何禁用的服务,这些服务提供了将数据写入InfluxDB的额外方法,但我们想使其他两个可用。我们将使用publish标志,即--publish
或-p
,并在docker run
命令中添加以下两行:
-p 8086:8086
-p 8088:8088
持久存储
接下来,我们需要决定我们的配置文件要存储在哪里,以及我们将存储需要它的容器的容器数据。
继续构建我们的InfluxDB运行命令,数据库期望在Linux上有两个文件位置,即它存储数据的/var/lib/influxdb
,以及它查找配置的/etc/influxdb
。这些位置可以自定义,但对我们来说,默认设置就足够了。
我们将通过添加volumes标志,即--volume
或-v
,将本地文件夹挂载到这些位置,在docker run
中。如果您愿意,可以让Docker为您管理一个卷,但将本地机器上的文件夹绑定确保我们可以从主机操作系统访问数据。
在Docker主机上的绑定点将根据您运行的机器而有所不同。为了举例,我们假设在fprefect
用户的家目录中有一个名为influxdb
的文件夹,其中包含两个子文件夹,分别名为data
和config
。我们将提供以下参数,将这些两个文件夹挂载到容器内部
-v /Users/fprefect/influxdb/data/:/var/lib/influxdb
-v /Users/fprefect/influxdb/config:/etc/influxdb
整合所有内容
我们几乎准备好启动我们的第一个容器了。我们只需要在我们的docker run
命令中添加一些额外的参数。我们将使用-d
标志以“分离”模式启动容器,这样它就会在后台运行,并且我们将使用--name
参数给它命名。最后,我们将运行标记为1.5.4
的influxdb
容器的最新版本。
这就是它的整体样子
$ docker run -d \
--network tick-net \
-p 8086:8086 \
-p 8082:8082 \
-p 8089:8089 \
-v /Users/fprefect/influxdb/data/:/var/lib/influxdb \
-v /Users/fprefect/influxdb/config:/etc/influxdb \
--name influxdb \
influxdb:1.5.4
请在命令行中运行它。如果成功,它应该返回一个唯一的哈希值,用于标识正在运行的容器。
操作容器
现在我们有一个正在运行的容器了,让我们来谈谈一些额外的操作细节。我们首先通常需要检查的是我们的容器是否正在运行。为此,我们可以使用docker ps
命令
$ docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
d20b788291ea influxdb:1.5.4 "/entrypoint.sh infl
" 3 seconds ago Up 1 second 0.0.0.0:8086->8086/tcp, 0.0.0.0:8088->8088/tcp influxdb
太棒了!我们的容器正在运行。但是,它可能并没有按照我们的预期表现?我们可能想深入查看日志。我们可以使用docker logs
命令和容器的名称来获取这些日志。我们还将添加一个--tail=5
参数来限制输出只显示最后5行。如果没有这个参数,我们会得到自程序启动以来输出的所有日志,这可能会非常多!
docker logs influxdb --tail=5
ts=2018-06-28T21:43:26.862912Z lvl=info msg="Compacted file" log_id=08z5Suul000 engine=tsm1 tsm1_strategy=full tsm1_optimize=false trace_id=08z5T3NG000 op_name=tsm1_compact_group tsm1_index=0 tsm1_file=/var/lib/influxdb/data/_internal/monitor/4/000000005-000000002.tsm.tmp
ts=2018-06-28T21:43:26.863008Z lvl=info msg="Finished compacting files" log_id=08z5Suul000 engine=tsm1 tsm1_strategy=full tsm1_optimize=false trace_id=08z5T3NG000 op_name=tsm1_compact_group groups=2 files=1 duration=49.357ms
ts=2018-06-28T21:43:26.863071Z lvl=info msg="TSM compaction (end)" log_id=08z5Suul000 engine=tsm1 tsm1_strategy=full tsm1_optimize=false trace_id=08z5T3NG000 op_name=tsm1_compact_group op_event=end op_elapsed=49.407ms
ts=2018-06-28T21:43:40.037174Z lvl=info msg="Post http://a7a2fee5bc09:80/write?consistency=&db=_internal&precision=ns&rp=monitor: dial tcp: lookup a7a2fee5bc09 on 127.0.0.11:53: no such host" log_id=08z5Suul000 service=subscriber
ts=2018-06-28T21:43:50.024014Z lvl=info msg="Post http://a7a2fee5bc09:80/write?consistency=&db=_internal&precision=ns&rp=monitor: dial tcp: lookup a7a2fee5bc09 on 127.0.0.11:53: no such host" log_id=08z5Suul000 service=subscriber
看起来InfluxDB容器一切正常,那么我们来看看是否能使用Influx CLI连接到数据库。我们可以在本地主机上使用CLI的副本来连接,但是如果我们想在容器内部启动CLI怎么办呢?
Docker也为此提供了一个命令:docker exec
。为了运行一个交互会话,我们还想提供-io
和-t
参数,它们分别创建一个交互会话并分配一个伪TTY。
所以,让我们在我们的influxdb
容器中执行influx
CLI。
$ docker exec -it influxdb influx
Connected to https://127.0.0.1:8086 version 1.5.4
InfluxDB shell version: 1.5.4
>
但是,你可能注意到,在CLI中箭头键并没有按预期工作。例如,当按上箭头键时,屏幕上会打印出^]]A
。这是由于influx
CLI检测和与终端环境交互的方式有问题。但是,如果你首先执行bash shell,然后再运行influx
CLI,箭头键应该会按预期工作。
$ docker exec -it influxdb /bin/bash
root@f7f7292006d0:/# influx
Connected to https://127.0.0.1:8086 version 1.5.4
InfluxDB shell version: 1.5.4
>
在我们继续到下一节之前,让我们停止并删除我们的容器。你可以使用docker stop
和docker rm
命令,以及容器标识的唯一哈希值或容器名称,如下所示
$ docker stop influxdb
influxdb
$ docker rm influxdb
influxdb
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
Docker Compose
Docker Compose 是“一个用于定义多容器 Docker 应用程序的工具”。它允许我们自动启动多个容器并将它们连接在一起,我们可以用它来帮助我们更轻松地推出和管理完整的 TICK Stack。我们将从在 docker-compose.yml
文件中定义构成 TICK Stack 的各种服务开始,然后使用 Compose 命令行工具部署这些服务。
下面是一个示例 docker-compose.yml
(使用 Compose 文件格式版本 3),它定义了两个服务: influxdb
和 chronograf
version: '3'
services:
influxdb:
image: influxdb:latest
volumes:
# Mount for influxdb data directory
- ./influxdb/data:/var/lib/influxdb
# Mount for influxdb configuration
- ./influxdb/config/:/etc/influxdb/
ports:
# The API for InfluxDB is served on port 8086
- "8086:8086"
- "8082:8082"
chronograf:
image: chronograf:latest
volumes:
# Mount for chronograf database
- ./chronograf/data/:/var/lib/chronograf/
ports:
# The WebUI for Chronograf is served on port 8888
- "8888:8888"
depends_on:
- influxdb
该文件还定义了我们想要发布到 Docker 主机的挂载点和端口。 chronograf
服务还有一个有用的部分:depends_on
。这将确保在启动 chronograf
容器之前,influxdb
容器已经启动并运行。
要部署这些服务,运行 docker-compose up -d
(类似于 docker run
,-d
参数以无头“分离”模式启动容器)。docker-compose
使用其执行目录来命名它管理的各种组件,因此将您的 docker-compose.yml
文件放入一个命名良好的目录是个好主意。对于这个例子,我们将我们的 docker-compose.yml
文件放在一个名为 tick
的目录中。
运行 docker-compose up -d
将执行多项操作:首先,它将创建一个名为 tick_network
的新 Docker 网络,然后为定义的每个服务启动一个容器,分别命名为 tick_influxdb_1
和 tick_chronograf_1
。
$ docker-compose up -d
Creating network "tick_default" with the default driver
Creating tick_influxdb_1 ... done
Creating tick_chronograf_1 ... done
$ docker ps -a
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
88b0263b7e74 chronograf:latest "/entrypoint.sh chro
" 11 seconds ago Up 9 seconds 0.0.0.0:8888->8888/tcp tick_chronograf_1
dcfa7a03eccb influxdb:latest "/entrypoint.sh infl
" 11 seconds ago Up 9 seconds 0.0.0.0:8082->8082/tcp, 0.0.0.0:8086->8086/tcp tick_influxdb_1
您应该可以通过访问 https://127.0.0.1:8888
来导航到 Chronograf GUI,并使用地址 http://influxdb:8086
连接到 InfluxDB,它使用 Docker Compose 内置的 DNS 解析来连接到 influxdb
容器。
获取日志的功能与使用 Docker 不带 Compose 时大致相同。您可以通过使用 docker-compose logs servicename
命令来访问单个服务的日志,用您服务的名称替换 servicename
。您可以使用 --tail=5
限制日志数量,如下所示
$ docker-compose logs --tail=5 influxdb
Attaching to tick_influxdb_1
influxdb_1 | ts=2018-06-28T22:30:01.069954Z lvl=info msg="Listening on HTTP" log_id=08z87b10000 service=httpd addr=[::]:8086 https=false
influxdb_1 | ts=2018-06-28T22:30:01.070023Z lvl=info msg="Starting retention policy enforcement service" log_id=08z87b10000 service=retention check_interval=30m
influxdb_1 | ts=2018-06-28T22:30:01.070057Z lvl=info msg="Storing statistics" log_id=08z87b10000 service=monitor db_instance=_internal db_rp=monitor interval=10s
influxdb_1 | ts=2018-06-28T22:30:01.070263Z lvl=info msg="Listening for signals" log_id=08z87b10000
influxdb_1 | ts=2018-06-28T22:30:01.070313Z lvl=info msg="Sending usage statistics to usage.influxdata.com" log_id=08z87b10000
您还可以通过在命令末尾省略容器名称来获取所有服务的日志
$ docker-compose logs --tail=2
Attaching to tick_chronograf_1, tick_influxdb_1
chronograf_1 | time="2018-06-28T22:30:01Z" level=info msg="Serving chronograf at http://[::]:8888" component=server
chronograf_1 | time="2018-06-28T22:30:01Z" level=info msg="Reporting usage stats" component=usage freq=24h reporting_addr="https://usage.influxdata.com" stats="os,arch,version,cluster_id,uptime"
influxdb_1 | ts=2018-06-28T22:30:01.070263Z lvl=info msg="Listening for signals" log_id=08z87b10000
influxdb_1 | ts=2018-06-28T22:30:01.070313Z lvl=info msg="Sending usage statistics to usage.influxdata.com" log_id=08z87b10000
使用 Docker Compose 执行命令略为容易,因为它将自动分配伪 TTY 并提供交互式会话,但其他方面看起来与标准 Docker 命令非常相似
$ docker-compose exec influxdb /bin/bash
root@dcfa7a03eccb:/#
要拆除一切,我们只需要从适当的目录执行 docker-compose down
。
TICK 沙盒
InfluxData 提供了一个名为“Sandbox”的 TICK Stack 的“发行版”。它提供了一个包含所有最新组件的 docker-compose.yml
文件,包括仍在开发中的组件,如 Flux。它还包含一对辅助脚本,以帮助那些不熟悉 Docker Compose 的人快速启动。由于它使用 Docker Compose,因此将拥有自己的网络和容器,不会与其他 Docker 中运行的 TICK Stack 实例冲突。
总结
在跟随本博客文章操作时,不要忘记清理你创建的任何容器!在使用Docker时,还需要注意容器镜像本身;镜像不会自动删除,因此随着时间的推移,当你升级使用的软件版本时,旧容器可能会积累并开始消耗磁盘空间。有一些脚本可以帮你管理这个问题,但大多数情况下,只要意识到潜在的问题,偶尔手动清理一下就足够了。
一如既往,如果您有任何问题或评论,请随时通过Twitter联系我 @noahcrowley 或在我们的社区网站上发表评论 community.influxdata.com。如果您用Influx构建了令人惊叹的东西,不要犹豫,告诉我们,您可能还能得到一件hoodie!