Deploying TDengine with Docker

This chapter describes how to start the TDengine service in a container and access it. Users can control the behavior of the service in the container by using environment variables on the docker run command-line or in the docker-compose file.

Starting TDengine

The TDengine image starts with the HTTP service activated by default, using the following command:

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

The above command starts a container named “tdengine” and maps the HTTP service port 6041 to the host port 6041. You can verify that the HTTP service provided in this container is available using the following command.

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

The TDengine client taos can be executed in this container to access TDengine using the following command.

  1. $ docker exec -it tdengine taos
  2. Welcome to the TDengine shell from Linux, Client Version:2.4.0.0
  3. Copyright (c) 2020 by TAOS Data, Inc.
  4. taos> show databases;
  5. name | created_time | ntables | vgroups | replica | quorum | days | keep | cache(MB) | blocks | minrows | maxrows | wallevel | fsync | comp | cachelast | precision | update | status | status precision | update | status |
  6. ================================================================================================================================== ================================================================================================================================== ================
  7. log | 2022-01-17 13:57:22.270 | 10 | 1 | 1 | 1 | 10 | 30 | 1 | 3 | 100 | 4096 | 1 | 3000 | 2 | 0 | us | 0 | ready |
  8. Query OK, 1 row(s) in set (0.002843s)

The TDengine server running in the container uses the container’s hostname to establish a connection. Using TDengine CLI or various connectors (such as JDBC-JNI) to access the TDengine inside the container from outside the container is more complicated. So the above is the simplest way to access the TDengine service in the container and is suitable for some simple scenarios. Please refer to the next section if you want to access the TDengine service in the container from outside the container using TDengine CLI or various connectors for complex scenarios.

Start TDengine on the host network

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

The above command starts TDengine on the host network and uses the host’s FQDN to establish a connection instead of the container’s hostname. It is the equivalent of using systemctl to start TDengine on the host. If the TDengine client is already installed on the host, you can access it directly with the following command.

  1. $ taos
  2. Welcome to the TDengine shell from Linux, Client Version:2.4.0.0
  3. Copyright (c) 2020 by TAOS Data, Inc.
  4. taos> show dnodes;
  5. id | end_point | vnodes | cores | status | role | create_time | offline reason |
  6. ================================================================================================================================== ====
  7. 1 | myhost:6030 | 1 | 8 | ready | any | 2022-01-17 22:10:32.619 | |
  8. Query OK, 1 row(s) in set (0.003233s)

Start TDengine with the specified hostname and port

The TAOS_FQDN environment variable or the fqdn configuration item in taos.cfg allows TDengine to establish a connection at the specified hostname. This approach provides greater flexibility for deployment.

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

The above command starts a TDengine service in the container, which listens to the hostname tdengine, and maps the container’s port segment 6030 to 6049 to the host’s port segment 6030 to 6049 (both TCP and UDP ports need to be mapped). If the port segment is already occupied on the host, you can modify the above command to specify a free port segment on the host. If rpcForceTcp is set to 1, you can map only the TCP protocol.

Next, ensure the hostname “tdengine” is resolvable in /etc/hosts.

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

Finally, the TDengine service can be accessed from the taos shell or any connector with “tdengine” as the server address.

  1. taos -h tdengine -P 6030

If set TAOS_FQDN to the same hostname, the effect is the same as “Start TDengine on host network”.

Start TDengine on the specified network

You can also start TDengine on a specific network.

  1. First, create a docker network named td-net

    1. docker network create td-net
    2. ``` Create td-net
  2. Start TDengine

    Start the TDengine service on the td-net network with the following command:

    1. docker run -d --name tdengine --network td-net \
    2. -e TAOS_FQDN=tdengine \
    3. tdengine/tdengine
  3. Start the TDengine client in another container on the same network

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

Launching a client application in a container

If you want to start your application in a container, you need to add the corresponding dependencies on TDengine to the image as well, e.g.

  1. FROM ubuntu:20.04
  2. RUN apt-get update && apt-get install -y wget
  3. ENV TDENGINE_VERSION=2.4.0.0
  4. RUN wget -c https://www.taosdata.com/assets-download/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"]

Here is an example GO program:

  1. /*
  2. * In this test program, we'll create a database and insert 4 records then select out.
  3. */
  4. package main
  5. import (
  6. "database/sql"
  7. "flag"
  8. "fmt"
  9. "time"
  10. _ "github.com/taosdata/driver-go/v2/taosSql"
  11. )
  12. type config struct {
  13. hostName string
  14. serverPort string
  15. user string
  16. password string
  17. }
  18. var configPara config
  19. var taosDriverName = "taosSql"
  20. var url string
  21. func init() {
  22. flag.StringVar(&configPara.hostName, "h", "", "The host to connect to TDengine server.")
  23. flag.StringVar(&configPara.serverPort, "p", "", "The TCP/IP port number to use for the connection to TDengine server.")
  24. flag.StringVar(&configPara.user, "u", "root", "The TDengine user name to use when connecting to the server.")
  25. flag.StringVar(&configPara.password, "P", "taosdata", "The password to use when connecting to the server.")
  26. flag.Parse()
  27. }
  28. func printAllArgs() {
  29. fmt.Printf("============= args parse result: =============\n")
  30. fmt.Printf("hostName: %v\n", configPara.hostName)
  31. fmt.Printf("serverPort: %v\n", configPara.serverPort)
  32. fmt.Printf("usr: %v\n", configPara.user)
  33. fmt.Printf("password: %v\n", configPara.password)
  34. fmt.Printf("================================================\n")
  35. }
  36. func main() {
  37. printAllArgs()
  38. url = "root:taosdata@/tcp(" + configPara.hostName + ":" + configPara.serverPort + ")/"
  39. taos, err := sql.Open(taosDriverName, url)
  40. checkErr(err, "open database error")
  41. defer taos.Close()
  42. taos.Exec("create database if not exists test")
  43. taos.Exec("use test")
  44. taos.Exec("create table if not exists tb1 (ts timestamp, a int)")
  45. _, err = taos.Exec("insert into tb1 values(now, 0)(now+1s,1)(now+2s,2)(now+3s,3)")
  46. checkErr(err, "failed to insert")
  47. rows, err := taos.Query("select * from tb1")
  48. checkErr(err, "failed to select")
  49. defer rows.Close()
  50. for rows.Next() {
  51. var r struct {
  52. ts time.Time
  53. a int
  54. }
  55. err := rows.Scan(&r.ts, &r.a)
  56. if err != nil {
  57. fmt.Println("scan error:\n", err)
  58. return
  59. }
  60. fmt.Println(r.ts, r.a)
  61. }
  62. }
  63. func checkErr(err error, prompt string) {
  64. if err != nil {
  65. fmt.Println("ERROR: %s\n", prompt)
  66. panic(err)
  67. }
  68. }

Here is the full Dockerfile:

  1. FROM golang:1.17.6-buster as builder
  2. ENV TDENGINE_VERSION=2.4.0.0
  3. RUN wget -c https://www.taosdata.com/assets-download/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
  15. FROM ubuntu:20.04
  16. RUN apt-get update && apt-get install -y wget
  17. ENV TDENGINE_VERSION=2.4.0.0
  18. RUN wget -c https://www.taosdata.com/assets-download/TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \
  19. && tar xvf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz \
  20. && cd TDengine-client-${TDENGINE_VERSION} \
  21. && ./install_client.sh \
  22. && cd ../ \
  23. && rm -rf TDengine-client-${TDENGINE_VERSION}-Linux-x64.tar.gz TDengine-client-${TDENGINE_VERSION}
  24. ## add your application next, eg. go, build it in builder stage, copy the binary to the runtime
  25. COPY --from=builder /usr/src/app/app /usr/bin/
  26. CMD ["app"]

Now that we have main.go, go.mod, go.sum, app.dockerfile, we can build the application and start it on the td-net network.

  1. $ docker build -t app -f app.dockerfile
  2. $ docker run --rm --network td-net app -h tdengine -p 6030
  3. ============= args parse result: =============
  4. hostName: tdengine
  5. serverPort: 6030
  6. usr: root
  7. password: taosdata
  8. ================================================
  9. 2022-01-17 15:56:55.48 +0000 UTC 0
  10. 2022-01-17 15:56:56.48 +0000 UTC 1
  11. 2022-01-17 15:56:57.48 +0000 UTC 2
  12. 2022-01-17 15:56:58.48 +0000 UTC 3
  13. 2022-01-17 15:58:01.842 +0000 UTC 0
  14. 2022-01-17 15:58:02.842 +0000 UTC 1
  15. 2022-01-17 15:58:03.842 +0000 UTC 2
  16. 2022-01-17 15:58:04.842 +0000 UTC 3
  17. 2022-01-18 01:43:48.029 +0000 UTC 0
  18. 2022-01-18 01:43:49.029 +0000 UTC 1
  19. 2022-01-18 01:43:50.029 +0000 UTC 2
  20. 2022-01-18 01:43:51.029 +0000 UTC 3

Start the TDengine cluster with docker-compose

  1. The following docker-compose file starts a TDengine cluster with two replicas, two management nodes, two data nodes, and one arbitrator.

    1. version: "3"
    2. services:
    3. arbitrator:
    4. image: tdengine/tdengine:$VERSION
    5. command: tarbitrator
    6. td-1:
    7. image: tdengine/tdengine:$VERSION
    8. environment:
    9. TAOS_FQDN: "td-1"
    10. TAOS_FIRST_EP: "td-1"
    11. TAOS_NUM_OF_MNODES: "2"
    12. TAOS_REPLICA: "2"
    13. TAOS_ARBITRATOR: arbitrator:6042
    14. volumes:
    15. - taosdata-td1:/var/lib/taos/
    16. - taoslog-td1:/var/log/taos/
    17. td-2:
    18. image: tdengine/tdengine:$VERSION
    19. environment:
    20. TAOS_FQDN: "td-2"
    21. TAOS_FIRST_EP: "td-1"
    22. TAOS_NUM_OF_MNODES: "2"
    23. TAOS_REPLICA: "2"
    24. TAOS_ARBITRATOR: arbitrator:6042
    25. volumes:
    26. - taosdata-td2:/var/lib/taos/
    27. - taoslog-td2:/var/log/taos/
    28. volumes:
    29. taosdata-td1:
    30. taoslog-td1:
    31. taosdata-td2:
    32. taoslog-td2:
TDengine Docker images - 图1note
  • The VERSION environment variable is used to set the tdengine image tag

    • TAOS_FIRST_EP must be set on the newly created instance so that it can join the TDengine cluster; if there is a high availability requirement, TAOS_SECOND_EP needs to be used at the same time
    • TAOS_REPLICA is used to set the default number of database replicas. Its value range is [1,3] We recommend setting it with TAOS_ARBITRATOR to use arbitrator in a two-nodes environment.

    :::

  1. Start the cluster

    1. $ VERSION=2.4.0.0 docker-compose up -d
    2. Creating network "test_default" with the default driver
    3. Creating volume "test_taosdata-td1" with default driver
    4. Creating volume "test_taoslog-td1" with default driver
    5. Creating volume "test_taosdata-td2" with default driver
    6. Creating volume "test_taoslog-td2" with default driver
    7. Creating test_td-1_1 ... done
    8. Creating test_arbitrator_1 ... done
    9. Creating test_td-2_1 ... done
  2. Check the status of each node

    1. $ docker-compose ps
    2. Name Command State Ports
    3. ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    4. test_arbitrator_1 /usr/bin/entrypoint.sh tar ... Up 6030/tcp, 6031/tcp, 6032/tcp, 6033/tcp, 6034/tcp, 6035/tcp, 6036/tcp, 6037/tcp, 6038/tcp, 6039/tcp, 6040/tcp, 6041/tcp, 6042/tcp
    5. test_td-1_1 /usr/bin/entrypoint.sh taosd Up 6030/tcp, 6031/tcp, 6032/tcp, 6033/tcp, 6034/tcp, 6035/tcp, 6036/tcp, 6037/tcp, 6038/tcp, 6039/tcp, 6040/tcp, 6041/tcp, 6042/tcp
    6. test_td-2_1 /usr/bin/entrypoint.sh taosd Up 6030/tcp, 6031/tcp, 6032/tcp, 6033/tcp, 6034/tcp, 6035/tcp, 6036/tcp, 6037/tcp, 6038/tcp, 6039/tcp, 6040/tcp, 6041/tcp, 6042/tcp
  3. Show dnodes via TDengine CLI

    1. $ docker-compose exec td-1 taos -s "show dnodes"
    2. Welcome to the TDengine shell from Linux, Client Version:2.4.0.0
    3. Copyright (c) 2020 by TAOS Data, Inc. All rights reserved.
    4. taos> show dnodes
    5. id | end_point | vnodes | cores | status | role | create_time | offline reason |
    6. ======================================================================================================================================
    7. 1 | td-1:6030 | 1 | 8 | ready | any | 2022-01-18 02:47:42.871 | |
    8. 2 | td-2:6030 | 0 | 8 | ready | any | 2022-01-18 02:47:43.518 | |
    9. 0 | arbitrator:6042 | 0 | 0 | ready | arb | 2022-01-18 02:47:43.633 | - |
    10. Query OK, 3 row(s) in set (0.000811s)

taosAdapter

  1. taosAdapter is enabled by default in the TDengine container. If you want to disable it, specify the environment variable TAOS_DISABLE_ADAPTER=true at startup

  2. At the same time, for flexible deployment, taosAdapter can be started in a separate container

    1. services:
    2. # ...
    3. adapter:
    4. image: tdengine/tdengine:$VERSION
    5. command: taosadapter

    Suppose you want to deploy multiple taosAdapters to improve throughput and provide high availability. In that case, the recommended configuration method uses a reverse proxy such as Nginx to offer a unified access entry. For specific configuration methods, please refer to the official documentation of Nginx. Here is an example:

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

Deploy with docker swarm

If you want to deploy a container-based TDengine cluster on multiple hosts, you can use docker swarm. First, to establish a docker swarm cluster on these hosts, please refer to the official docker documentation.

The docker-compose file can refer to the previous section. Here is the command to start TDengine with docker swarm:

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

Checking status:

  1. $ docker stack ps taos
  2. ID NAME IMAGE NODE DESIRED STATE CURRENT STATE ERROR PORTS
  3. 79ni8temw59n taos_nginx.1 nginx:latest TM1701 Running Running about a minute ago
  4. 3e94u72msiyg taos_adapter.1 tdengine/tdengine:2.4.0 TM1702 Running Running 56 seconds ago
  5. 100amjkwzsc6 taos_td-2.1 tdengine/tdengine:2.4.0 TM1703 Running Running about a minute ago
  6. pkjehr2vvaaa taos_td-1.1 tdengine/tdengine:2.4.0 TM1704 Running Running 2 minutes ago
  7. tpzvgpsr1qkt taos_arbitrator.1 tdengine/tdengine:2.4.0 TM1705 Running Running 2 minutes ago
  8. rvss3g5yg6fa taos_adapter.2 tdengine/tdengine:2.4.0 TM1706 Running Running 56 seconds ago
  9. i2augxamfllf taos_adapter.3 tdengine/tdengine:2.4.0 TM1707 Running Running 56 seconds ago
  10. lmjyhzccpvpg taos_adapter.4 tdengine/tdengine:2.4.0 TM1708 Running Running 56 seconds ago
  11. $ docker service ls
  12. ID NAME MODE REPLICAS IMAGE PORTS
  13. 561t4lu6nfw6 taos_adapter replicated 4/4 tdengine/tdengine:2.4.0
  14. 3hk5ct3q90sm taos_arbitrator replicated 1/1 tdengine/tdengine:2.4.0
  15. d8qr52envqzu taos_nginx replicated 1/1 nginx:latest *:6041->6041/tcp, *:6044->6044/udp
  16. 2isssfvjk747 taos_td-1 replicated 1/1 tdengine/tdengine:2.4.0
  17. 9pzw7u02ichv taos_td-2 replicated 1/1 tdengine/tdengine:2.4.0

From the above output, you can see two dnodes, two taosAdapters, and one Nginx reverse proxy service.

Next, we can reduce the number of taosAdapter services.

  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
  6. $ docker service ls -f name=taos_adapter
  7. ID NAME MODE REPLICAS IMAGE PORTS
  8. 561t4lu6nfw6 taos_adapter replicated 1/1 tdengine/tdengine:2.4.0