用 Docker 部署 TDengine

本章主要介绍如何在容器中启动 TDengine 服务并访问它。可以在 docker run 命令行中或者 docker-compose 文件中使用环境变量来控制容器中服务的行为。

启动 TDengine

TDengine 镜像启动时默认激活 HTTP 服务,使用下列命令

1. docker run -d --name tdengine -p 6041:6041 tdengine/tdengine

以上命令启动了一个名为“tdengine”的容器,并把其中的 HTTP 服务的端 6041 映射到了主机端口 6041。使用如下命令可以验证该容器中提供的 HTTP 服务是否可用:

1. curl -u root:taosdata -d "show databases" localhost:6041/rest/sql

使用如下命令可以在该容器中执行 TDengine 的客户端 taos 对 TDengine 进行访问:

1. $ docker exec -it tdengine taos

3. taos> show databases;
4. name              |
5. =================================
6. information_schema             |
7. performance_schema             |
8. Query OK, 2 rows in database (0.033802s)

因为运行在容器中的 TDengine 服务端使用容器的 hostname 建立连接,使用 TDengine CLI 或者各种连接器(例如 JDBC-JNI)从容器外访问容器内的 TDengine 比较复杂,所以上述方式是访问容器中 TDengine 服务的最简单的方法,适用于一些简单场景。如果在一些复杂场景下想要从容器化使用 TDengine CLI 或者各种连接器访问容器中的 TDengine 服务,请参考下一节。

在 host 网络上启动 TDengine

1. docker run -d --name tdengine --network host tdengine/tdengine

上面的命令在 host 网络上启动 TDengine,并使用主机的 FQDN 建立连接而不是使用容器的 hostname 。这种方式和在主机上使用 systemctl 启动 TDengine 效果相同。在主机已安装 TDengine 客户端情况下,可以直接使用下面的命令访问它。

1. $ taos

3. taos> show dnodes;
4. id      |            endpoint            | vnodes | support_vnodes |   status   |       create_time       |              note              |
5. =================================================================================================================================================
6. 1 | vm98:6030                      |      0 |             32 | ready      | 2022-08-19 14:50:05.337 |                                |
7. Query OK, 1 rows in database (0.010654s)

以指定的 hostname 和 port 启动 TDengine

利用 TAOS_FQDN 环境变量或者 taos.cfg 中的 fqdn 配置项可以使 TDengine 在指定的 hostname 上建立连接。这种方式可以为部署提供更大的灵活性。

1. docker run -d \
2. --name tdengine \
3. -e TAOS_FQDN=tdengine \
4. -p 6030:6030 \
5. -p 6041-6049:6041-6049 \
6. -p 6041-6049:6041-6049/udp \
7. tdengine/tdengine

上面的命令在容器中启动一个 TDengine 服务,其所监听的 hostname 为 tdengine ,并将容器的 6030 端口映射到主机的 6030 端口(TCP,只能映射主机 6030 端口),6041-6049 端口段映射到主机 6041-6049 端口段(tcp 和 udp 都需要映射,如果主机上该端口段已经被占用,可以修改上述命令指定一个主机上空闲的端口段)。

接下来,要确保 “tdengine” 这个 hostname 在 /etc/hosts 中可解析。

1. echo 127.0.0.1 tdengine |sudo tee -a /etc/hosts

最后,可以从 TDengine CLI 或者任意连接器以 “tdengine” 为服务端地址访问 TDengine 服务。

1. taos -h tdengine -P 6030

如果 TAOS_FQDN 被设置为与所在主机名相同,则效果与 “在 host 网络上启动 TDengine” 相同。

在指定网络上启动 TDengine

也可以在指定的特定网络上启动 TDengine。下面是详细步骤:

  1. 首先,创建一个 docker 网络,命名为 td-net

1. docker network create td-net 2. 启动 TDengine

以下命令在 td-net 网络上启动 TDengine 服务

1. docker run -d --name tdengine --network td-net \ 2. -e TAOS_FQDN=tdengine \ 3. tdengine/tdengine 3. 在同一网络上的另一容器中启动 TDengine 客户端

1. docker run --rm -it --network td-net -e TAOS_FIRST_EP=tdengine --entrypoint=taos tdengine/tdengine 2. # or 3. #docker run --rm -it --network td-net --entrypoint=taos tdengine/tdengine -h tdengine

在容器中启动客户端应用

如果想在容器中启动自己的应用的话,需要将相应的对 TDengine 的依赖也要加入到镜像中,例如:

1. FROM ubuntu:20.04
2. RUN apt-get update && apt-get install -y wget
3. ENV TDENGINE_VERSION=3.0.0.0
4. RUN wget -c https://www.tdengine.com/assets-download/3.0/TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \
5. && tar xvf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \
6. && cd TDengine-client-${TDENGINE_VERSION} \
7. && ./install_client.sh \
8. && cd ../ \
9. && rm -rf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz TDengine-client-${TDENGINE_VERSION}
10. ## add your application next, eg. go, build it in builder stage, copy the binary to the runtime
11. #COPY --from=builder /path/to/build/app /usr/bin/
12. #CMD ["app"]

以下是一个 go 应用程序的示例:

  • 创建 go mod 项目:
1. go mod init app
  • 创建 main.go:
1. /*
2. * In this test program, we'll create a database and insert 4 records then select out.
3. */
4. package main

6. import (
7. "database/sql"
8. "flag"
9. "fmt"
10. "time"

12. _ "github.com/taosdata/driver-go/v3/taosSql"
13. )

15. type config struct {
16. hostName   string
17. serverPort string
18. user       string
19. password   string
20. }

22. var configPara config
23. var taosDriverName = "taosSql"
24. var url string

26. func init() {
27. flag.StringVar(&configPara.hostName, "h", "", "The host to connect to TDengine server.")
28. flag.StringVar(&configPara.serverPort, "p", "", "The TCP/IP port number to use for the connection to TDengine server.")
29. flag.StringVar(&configPara.user, "u", "root", "The TDengine user name to use when connecting to the server.")
30. flag.StringVar(&configPara.password, "P", "taosdata", "The password to use when connecting to the server.")
31. flag.Parse()
32. }

34. func printAllArgs() {
35. fmt.Printf("============= args parse result: =============\n")
36. fmt.Printf("hostName:             %v\n", configPara.hostName)
37. fmt.Printf("serverPort:           %v\n", configPara.serverPort)
38. fmt.Printf("usr:                  %v\n", configPara.user)
39. fmt.Printf("password:             %v\n", configPara.password)
40. fmt.Printf("================================================\n")
41. }

43. func main() {
44. printAllArgs()

46. url = "root:taosdata@/tcp(" + configPara.hostName + ":" + configPara.serverPort + ")/"

48. taos, err := sql.Open(taosDriverName, url)
49. checkErr(err, "open database error")
50. defer taos.Close()

52. taos.Exec("create database if not exists test")
53. taos.Exec("use test")
54. taos.Exec("create table if not exists tb1 (ts timestamp, a int)")
55. _, err = taos.Exec("insert into tb1 values(now, 0)(now+1s,1)(now+2s,2)(now+3s,3)")
56. checkErr(err, "failed to insert")
57. rows, err := taos.Query("select * from tb1")
58. checkErr(err, "failed to select")

60. defer rows.Close()
61. for rows.Next() {
62. var r struct {
63. ts time.Time
64. a  int
65. }
66. err := rows.Scan(&r.ts, &r.a)
67. if err != nil {
68. fmt.Println("scan error:\n", err)
69. return
70. }
71. fmt.Println(r.ts, r.a)
72. }
73. }

75. func checkErr(err error, prompt string) {
76. if err != nil {
77. fmt.Println("ERROR: %s\n", prompt)
78. panic(err)
79. }
80. }
  • 更新 go mod
1. go mod tidy

如下是完整版本的 dockerfile:

1. FROM golang:1.19.0-buster as builder
2. ENV TDENGINE_VERSION=3.0.0.0
3. RUN wget -c https://www.tdengine.com/assets-download/3.0/TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \
4. && tar xvf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \
5. && cd TDengine-client-${TDENGINE_VERSION} \
6. && ./install_client.sh \
7. && cd ../ \
8. && rm -rf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz TDengine-client-${TDENGINE_VERSION}
9. WORKDIR /usr/src/app/
10. ENV GOPROXY="https://goproxy.io,direct"
11. COPY ./main.go ./go.mod ./go.sum /usr/src/app/
12. RUN go env
13. RUN go mod tidy
14. RUN go build

16. FROM ubuntu:20.04
17. RUN apt-get update && apt-get install -y wget
18. ENV TDENGINE_VERSION=3.0.0.0
19. RUN wget -c https://www.tdengine.com/assets-download/3.0/TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \
20. && tar xvf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \
21. && cd TDengine-client-${TDENGINE_VERSION} \
22. && ./install_client.sh \
23. && cd ../ \
24. && rm -rf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz TDengine-client-${TDENGINE_VERSION}

26. ## add your application next, eg. go, build it in builder stage, copy the binary to the runtime
27. COPY --from=builder /usr/src/app/app /usr/bin/
28. CMD ["app"]

目前我们已经有了 main.go, go.mod, go.sum, app.dockerfile, 现在可以构建出这个应用程序并在 td-net 网络上启动它

1. $ docker build -t app -f app.dockerfile .
2. $ docker run --rm --network td-net app app -h tdengine -p 6030
3. ============= args parse result: =============
4. hostName:             tdengine
5. serverPort:           6030
6. usr:                  root
7. password:             taosdata
8. ================================================
9. 2022-08-19 07:43:51.68 +0000 UTC 0
10. 2022-08-19 07:43:52.68 +0000 UTC 1
11. 2022-08-19 07:43:53.68 +0000 UTC 2
12. 2022-08-19 07:43:54.68 +0000 UTC 3

用 docker-compose 启动 TDengine 集群

  1. 如下 docker-compose 文件启动一个 三节点 TDengine 集群。
1. version: "3"
2. services:
3. td-1:
4. image: tdengine/tdengine:$VERSION
5. environment:
6. TAOS_FQDN: "td-1"
7. TAOS_FIRST_EP: "td-1"
8. volumes:
9. - taosdata-td1:/var/lib/taos/
10. - taoslog-td1:/var/log/taos/
11. td-2:
12. image: tdengine/tdengine:$VERSION
13. environment:
14. TAOS_FQDN: "td-2"
15. TAOS_FIRST_EP: "td-1"
16. volumes:
17. - taosdata-td2:/var/lib/taos/
18. - taoslog-td2:/var/log/taos/
19. td-3:
20. image: tdengine/tdengine:$VERSION
21. environment:
22. TAOS_FQDN: "td-3"
23. TAOS_FIRST_EP: "td-1"
24. volumes:
25. - taosdata-td3:/var/lib/taos/
26. - taoslog-td3:/var/log/taos/
27. volumes:
28. taosdata-td1:
29. taoslog-td1:
30. taosdata-td2:
31. taoslog-td2:
32. taosdata-td3:
33. taoslog-td3:
TDengine Docker 镜像 - 图1note
  • VERSION 环境变量被用来设置 tdengine image tag
  • 在新创建的实例上必须设置 TAOS_FIRST_EP 以使其能够加入 TDengine 集群;如果有高可用需求,则需要同时使用 TAOS_SECOND_EP

  • 启动集群

1. $ VERSION=3.0.0.0 docker-compose up -d
2. Creating network "test-docker_default" with the default driver
3. Creating volume "test-docker_taosdata-td1" with default driver
4. Creating volume "test-docker_taoslog-td1" with default driver
5. Creating volume "test-docker_taosdata-td2" with default driver
6. Creating volume "test-docker_taoslog-td2" with default driver
7. Creating volume "test-docker_taosdata-td3" with default driver
8. Creating volume "test-docker_taoslog-td3" with default driver

10. Creating test-docker_td-3_1 ... done
11. Creating test-docker_td-1_1 ... done
12. Creating test-docker_td-2_1 ... done
  1. 查看节点状态
1. docker-compose ps
2. Name                     Command               State   Ports

4. -------------------------------------------------------------------
5. test-docker_td-1_1   /tini -- /usr/bin/entrypoi ...   Up
6. test-docker_td-2_1   /tini -- /usr/bin/entrypoi ...   Up
7. test-docker_td-3_1   /tini -- /usr/bin/entrypoi ...   Up
  1. 用 TDengine CLI 查看 dnodes
2. $ docker-compose exec td-1 taos -s "show dnodes"

4. taos> show dnodes

6. id      |            endpoint            | vnodes | support_vnodes |   status   |       create_time       |              note              |
7. =================================================================================================================================================

9. 1 | td-1:6030                      |      0 |             32 | ready      | 2022-08-19 07:57:29.971 |                                |
10. 2 | td-2:6030                      |      0 |             32 | ready      | 2022-08-19 07:57:31.415 |                                |
11. 3 | td-3:6030                      |      0 |             32 | ready      | 2022-08-19 07:57:31.417 |                                |
12. Query OK, 3 rows in database (0.021262s)

taosAdapter

  1. taosAdapter 在 TDengine 容器中默认是启动的。如果想要禁用它,在启动时指定环境变量 TAOS_DISABLE_ADAPTER=true
  2. 同时为了部署灵活起见,可以在独立的容器中启动 taosAdapter
1. services:
2. # ...
3. adapter:
4. image: tdengine/tdengine:$VERSION
5. command: taosadapter

如果要部署多个 taosAdapter 来提高吞吐量并提供高可用性,推荐配置方式为使用 nginx 等反向代理来提供统一的访问入口。具体配置方法请参考 nginx 的官方文档。如下是示例:

1. version: "3"

3. networks:
4. inter:

6. services:
7. td-1:
8. image: tdengine/tdengine:$VERSION
9. networks:
10. - inter
11. environment:
12. TAOS_FQDN: "td-1"
13. TAOS_FIRST_EP: "td-1"
14. volumes:
15. - taosdata-td1:/var/lib/taos/
16. - taoslog-td1:/var/log/taos/
17. td-2:
18. image: tdengine/tdengine:$VERSION
19. networks:
20. - inter
21. environment:
22. TAOS_FQDN: "td-2"
23. TAOS_FIRST_EP: "td-1"
24. volumes:
25. - taosdata-td2:/var/lib/taos/
26. - taoslog-td2:/var/log/taos/
27. adapter:
28. image: tdengine/tdengine:$VERSION
29. entrypoint: "taosadapter"
30. networks:
31. - inter
32. environment:
33. TAOS_FIRST_EP: "td-1"
34. TAOS_SECOND_EP: "td-2"
35. deploy:
36. replicas: 4
37. nginx:
38. image: nginx
39. depends_on:
40. - adapter
41. networks:
42. - inter
43. ports:
44. - 6041:6041
45. - 6044:6044/udp
46. command: [
47. "sh",
48. "-c",
49. "while true;
50. do curl -s http://adapter:6041/-/ping >/dev/null && break;
51. done;
52. printf 'server{listen 6041;location /{proxy_pass http://adapter:6041;}}'
53. > /etc/nginx/conf.d/rest.conf;
54. printf 'stream{server{listen 6044 udp;proxy_pass adapter:6044;}}'
55. >> /etc/nginx/nginx.conf;cat /etc/nginx/nginx.conf;
56. nginx -g 'daemon off;'",
57. ]
58. volumes:
59. taosdata-td1:
60. taoslog-td1:
61. taosdata-td2:
62. taoslog-td2:

使用 docker swarm 部署

如果要想将基于容器的 TDengine 集群部署在多台主机上,可以使用 docker swarm。首先要在这些主机上建立 docke swarm 集群,请参考 docker 官方文档。

docker-compose 文件可以参考上节。下面是使用 docker swarm 启动 TDengine 的命令:

1. $ VERSION=3.0.0.0 docker stack deploy -c docker-compose.yml taos
2. Creating network taos_inter
3. Creating service taos_nginx
4. Creating service taos_td-1
5. Creating service taos_td-2
6. Creating service taos_adapter

查看和管理

1. $ docker stack ps taos
2. ID             NAME             IMAGE                       NODE      DESIRED STATE   CURRENT STATE                ERROR     PORTS
3. 7m3sbf532bqp   taos_adapter.1   tdengine/tdengine:3.0.0.0   vm98      Running         Running about a minute ago
4. pj403n6ofmmh   taos_adapter.2   tdengine/tdengine:3.0.0.0   vm98      Running         Running about a minute ago
5. rxqfwsyk5q1h   taos_adapter.3   tdengine/tdengine:3.0.0.0   vm98      Running         Running about a minute ago
6. qj40lpxr40oc   taos_adapter.4   tdengine/tdengine:3.0.0.0   vm98      Running         Running about a minute ago
7. oe3455ulxpze   taos_nginx.1     nginx:latest                vm98      Running         Running about a minute ago
8. o0tsg70nrrc6   taos_td-1.1      tdengine/tdengine:3.0.0.0   vm98      Running         Running about a minute ago
9. q5m1oxs589cp   taos_td-2.1      tdengine/tdengine:3.0.0.0   vm98      Running         Running about a minute ago
10. $ docker service ls
11. ID             NAME           MODE         REPLICAS   IMAGE                       PORTS
12. ozuklorgl8bs   taos_adapter   replicated   4/4        tdengine/tdengine:3.0.0.0
13. crmhdjw6vxw0   taos_nginx     replicated   1/1        nginx:latest                *:6041->6041/tcp, *:6044->6044/udp
14. o86ngy7csv5n   taos_td-1      replicated   1/1        tdengine/tdengine:3.0.0.0
15. rma040ny4tb0   taos_td-2      replicated   1/1        tdengine/tdengine:3.0.0.0

从上面的输出可以看到有两个 dnode, 和四个 taosAdapter,以及一个 nginx 反向代理服务。

接下来,我们可以减少 taosAdapter 服务的数量

1. $ docker service scale taos_adapter=1
2. taos_adapter scaled to 1
3. overall progress: 1 out of 1 tasks
4. 1/1: running   [==================================================>]
5. verify: Service converged

7. $ docker service ls -f name=taos_adapter
8. ID             NAME           MODE         REPLICAS   IMAGE                       PORTS
9. ozuklorgl8bs   taos_adapter   replicated   1/1        tdengine/tdengine:3.0.0.0