使用 Docker 部署 Elasticsearch & Kibana

本文介绍如何使用 Docker 部署 Elasticsearch & Kibana

如果您是第一次阅读该系列文章,建议优先阅读 Docker 部署项目说明及索引

ElasticSearch 是一款开源的分布式搜索与分析引擎,专为速度、可扩展性和 AI 应用而设计。

Kibana 是一款开源的数据可视化工具,用于查看和分析 Elasticsearch 中的数据。

注意:群晖 NAS 暂时无法部署 Elasticsearch 8.0 以上版本,请基于其他系统部署。

前置准备

.env

1
2
3
4
5
6
7
8
9
# Project namespace
COMPOSE_PROJECT_NAME=elastic-stack

# Elastic Stack Version
STACK_VERSION=9.5.2

# 密码
ELASTIC_PASSWORD=your_elastic_password
KIBANA_PASSWORD=your_kibana_password

配置文件

准备 elasticsearch.ymlkibana.yml 配置文件,并修改其中的参数。文件内容参考如下:

elasticsearch.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
cluster.name: docker-cluster
node.name: es-node-1
node.roles: [ master, data, ingest ]
path.data: /usr/share/elasticsearch/data
path.logs: /usr/share/elasticsearch/logs
network.host: 0.0.0.0
http.port: 9200
transport.port: 9300
discovery.type: single-node
bootstrap.memory_lock: false
xpack.security.enabled: false
xpack.security.transport.ssl.enabled: false
xpack.security.http.ssl.enabled: false
http.cors.enabled: true
http.cors.allow-origin: "*"

kibana.yml

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
server.host: "0.0.0.0"
server.port: 5601
elasticsearch.hosts: ["http://es:9200"]
elasticsearch.username: kibana_system
elasticsearch.password: your_kibana_password
telemetry.enabled: false
telemetry.optIn: false
xpack.encryptedSavedObjects.encryptionKey: df8af2e337e15895b9f212de5e56702408de70325233874492a04405d5ae5f22
xpack.reporting.encryptionKey: 39539df1484f0e5e51521be72b64b86814a9bee4f49ecf7f5659117c49f28ed0
xpack.security.encryptionKey: 19b0330d867e2d0c7b584956ec3a97bdb839f2aa741334b390e38ff339b84fae

Docker Compose

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
name: ${COMPOSE_PROJECT_NAME}

services:
  es:
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: es
    hostname: es
    restart: unless-stopped
    ports:
      - "9200:9200"
    volumes:
      - ./elasticsearch/config/elasticsearch.yml:/usr/share/elasticsearch/config/elasticsearch.yml
      - ./elasticsearch/data:/usr/share/elasticsearch/data
      - ./elasticsearch/logs:/usr/share/elasticsearch/logs
    environment:
      - TZ=Asia/Shanghai
      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
      - discovery.type=single-node
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s http://localhost:9200 | grep -q 'missing authentication credentials'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120
  es-init:
    image: curlimages/curl:latest
    container_name: es-init
    hostname: es-init
    restart: no
    command: >
      sh -c '
        if [ x${ELASTIC_PASSWORD} == x ]; then
          echo "ERROR: ELASTIC_PASSWORD is empty, check .env";
          exit 1;
        fi
        if [ x${KIBANA_PASSWORD} == x ]; then
          echo "ERROR: KIBANA_PASSWORD is empty, check .env";
          exit 1;
        fi;

        echo "Waiting for Elasticsearch availability";
        until curl -s http://es:9200 | grep -q "missing authentication credentials"; do sleep 10; done;
        echo "Setting kibana_system password";
        until curl -s -X POST http://es:9200/_security/user/kibana_system/_password -u "elastic:${ELASTIC_PASSWORD}" -H "Content-Type: application/json" -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;

        echo "All done!";
      '
    depends_on:
      es:
        condition: service_healthy
  kibana:
    image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
    container_name: kibana
    hostname: kibana
    restart: unless-stopped
    ports:
      - "5601:5601"
    volumes:
      - ./kibana/config/kibana.yml:/usr/share/kibana/config/kibana.yml
      - ./kibana/data:/usr/share/kibana/data
    environment:
      - TZ=Asia/Shanghai
    depends_on:
      es:
        condition: service_healthy
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120
networks:
  default:
    external: true
    name: rod

容器使用 elasticsearch 作为用户,uid:gid 为 1000:0。绑定本地目录时,注意权限设置。

测试

elasticsearch

访问 http://localhost:9200

用户名:elastic,密码:your_elastic_password

返回类似如下内容:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
{
    "name": "es-node-1",
    "cluster_name": "docker-cluster",
    "cluster_uuid": "v_NcfXkCQWOqjtiPLTY1bA",
    "version": {
        "number": "9.5.2",
        "build_flavor": "default",
        "build_type": "docker",
        "build_hash": "b42549c72e6e040825b13e5d8ebf7ff63886b24d",
        "build_date": "2026-08-18T10:07:58.745010960Z",
        "build_snapshot": false,
        "lucene_version": "10.5.1",
        "minimum_wire_compatibility_version": "8.19.0",
        "minimum_index_compatibility_version": "8.0.0"
    },
    "tagline": "You Know, for Search"
}

Kibana

访问 http://localhost:5601

用户名:elastic,密码:your_elastic_password

注意:不要使用 kibana_system 登录。

常见问题

Elasticsearch: seccomp unavailable

在 Synology NAS 上启动时可能遇到如下报错:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
{
  "@timestamp": "2026-08-26T05:56:35.252Z",
  "log.level": "ERROR",
  "message": "fatal exception while booting Elasticsearch",
  "ecs.version": "1.2.0",
  "service.name": "ES_ECS",
  "event.dataset": "elasticsearch.server",
  "process.thread.name": "main",
  "log.logger": "org.elasticsearch.bootstrap.Elasticsearch",
  "elasticsearch.node.name": "elasticsearch",
  "elasticsearch.cluster.name": "docker-cluster",
  "error.type": "java.lang.UnsupportedOperationException",
  "error.message": "seccomp unavailable: CONFIG_SECCOMP not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed",
  "error.stack_trace": "java.lang.UnsupportedOperationException: seccomp unavailable: CONFIG_SECCOMP not compiled into kernel, CONFIG_SECCOMP and CONFIG_SECCOMP_FILTER are needed\n\tat org.elasticsearch.nativeaccess@8.19.20/org.elasticsearch.nativeaccess.LinuxNativeAccess.tryInstallExecSandbox(LinuxNativeAccess.java:255)\n\tat org.elasticsearch.server@8.19.20/org.elasticsearch.bootstrap.Elasticsearch.initializeNatives(Elasticsearch.java:495)\n\tat org.elasticsearch.server@8.19.20/org.elasticsearch.bootstrap.Elasticsearch.initPhase2(Elasticsearch.java:188)\n\tat org.elasticsearch.server@8.19.20/org.elasticsearch.bootstrap.Elasticsearch.main(Elasticsearch.java:100)\n"
}

这是由于 DSM 内核未编译 seccomp 的原因,暂时无法解决。可尝试降低 Elasticsearch 版本 (8.0 以下) 并添加如下配置解决:

1
2
# 禁用系统调用过滤器
bootstrap.system_call_filter: false

Elasticsearch 8.0 版本以上该配置已失效不可使用。

Kibana: 无法检索检测引擎权限

1
Unable to create actions client because the Encrypted Saved Objects plugin is missing encryption key. Please set xpack.encryptedSavedObjects.encryptionKey in the kibana.yml or use the bin/kibana-encryption-keys command. (500)

kibana.yml 配置文件中缺少加密密钥,在文件中添加以下配置:

1
2
3
xpack.encryptedSavedObjects.encryptionKey: df8af2e337e15895b9f212de5e56702408de70325233874492a04405d5ae5f22
xpack.reporting.encryptionKey: 39539df1484f0e5e51521be72b64b86814a9bee4f49ecf7f5659117c49f28ed0
xpack.security.encryptionKey: 19b0330d867e2d0c7b584956ec3a97bdb839f2aa741334b390e38ff339b84fae

上述密钥可通过 Kibana 指令快速生成:

1
docker exec -it kibana bin/kibana-encryption-keys generate

参考网址

附录:集群部署

.env

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# Project namespace (defaults to the current folder name if not set)
COMPOSE_PROJECT_NAME=elastic-stack-cluster

# Version of Elastic products
STACK_VERSION=9.5.2

# Password for the 'elastic' user (at least 6 characters)
ELASTIC_PASSWORD=your_elastic_password

# Password for the 'kibana_system' user (at least 6 characters)
KIBANA_PASSWORD=your_kibana_password

# Set the cluster name
CLUSTER_NAME=docker-cluster

# Set to 'basic' or 'trial' to automatically start the 30-day trial
LICENSE=basic
#LICENSE=trial

# Port to expose Elasticsearch HTTP API to the host
ES_PORT=9200
#ES_PORT=127.0.0.1:9200

# Port to expose Kibana to the host
KIBANA_PORT=5601
#KIBANA_PORT=80

# Increase or decrease based on the available host memory (in bytes)
MEM_LIMIT=1073741824

# Kibana encryption keys
KIBANA_ENCRYPTED_SAVED_OBJECTS_ENCRYPTION_KEY=df8af2e337e15895b9f212de5e56702408de70325233874492a04405d5ae5f22
KIBANA_REPORTING_ENCRYPTION_KEY=39539df1484f0e5e51521be72b64b86814a9bee4f49ecf7f5659117c49f28ed0
KIBANA_SECURITY_ENCRYPTION_KEY=19b0330d867e2d0c7b584956ec3a97bdb839f2aa741334b390e38ff339b84fae

docker-compose.yml

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
name: ${COMPOSE_PROJECT_NAME}

services:
  elastic-stack-cluster-setup:
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: elastic-stack-cluster-setup
    hostname: elastic-stack-cluster-setup
    restart: no
    volumes:
      - elastic-stack-certs:/usr/share/elasticsearch/config/certs
    user: "0"
    command: >
      bash -c '
        if [ x${ELASTIC_PASSWORD} == x ]; then
          echo "Set the ELASTIC_PASSWORD environment variable in the .env file";
          exit 1;
        elif [ x${KIBANA_PASSWORD} == x ]; then
          echo "Set the KIBANA_PASSWORD environment variable in the .env file";
          exit 1;
        fi;
        if [ ! -f config/certs/ca.zip ]; then
          echo "Creating CA";
          bin/elasticsearch-certutil ca --silent --pem -out config/certs/ca.zip;
          unzip config/certs/ca.zip -d config/certs;
        fi;
        if [ ! -f config/certs/certs.zip ]; then
          echo "Creating certs";
          echo -ne \
          "instances:\n"\
          "  - name: es01\n"\
          "    dns:\n"\
          "      - es01\n"\
          "      - localhost\n"\
          "    ip:\n"\
          "      - 127.0.0.1\n"\
          "  - name: es02\n"\
          "    dns:\n"\
          "      - es02\n"\
          "      - localhost\n"\
          "    ip:\n"\
          "      - 127.0.0.1\n"\
          "  - name: es03\n"\
          "    dns:\n"\
          "      - es03\n"\
          "      - localhost\n"\
          "    ip:\n"\
          "      - 127.0.0.1\n"\
          > config/certs/instances.yml;
          bin/elasticsearch-certutil cert --silent --pem -out config/certs/certs.zip --in config/certs/instances.yml --ca-cert config/certs/ca/ca.crt --ca-key config/certs/ca/ca.key;
          unzip config/certs/certs.zip -d config/certs;
        fi;
        echo "Setting file permissions"
        chown -R root:root config/certs;
        find . -type d -exec chmod 750 \{\} \;;
        find . -type f -exec chmod 640 \{\} \;;
        echo "Waiting for Elasticsearch availability";
        until curl -s --cacert config/certs/ca/ca.crt https://es01:9200 | grep -q "missing authentication credentials"; do sleep 30; done;
        echo "Setting kibana_system password";
        until curl -s -X POST --cacert config/certs/ca/ca.crt -u "elastic:${ELASTIC_PASSWORD}" -H "Content-Type: application/json" https://es01:9200/_security/user/kibana_system/_password -d "{\"password\":\"${KIBANA_PASSWORD}\"}" | grep -q "^{}"; do sleep 10; done;
        echo "All done!";
      '
    healthcheck:
      test: [ "CMD-SHELL", "[ -f config/certs/es01/es01.crt ]" ]
      interval: 1s
      timeout: 5s
      retries: 120

  es01:
    depends_on:
      elastic-stack-cluster-setup:
        condition: service_healthy
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: es01
    hostname: es01
    restart: unless-stopped
    volumes:
      - elastic-stack-certs:/usr/share/elasticsearch/config/certs
      - elastic-stack-es01:/usr/share/elasticsearch/data
    ports:
      - ${ES_PORT}:9200
    environment:
      - node.name=es01
      - cluster.name=${CLUSTER_NAME}
      - cluster.initial_master_nodes=es01,es02,es03
      - discovery.seed_hosts=es02,es03
      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
      - bootstrap.memory_lock=true
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=true
      - xpack.security.http.ssl.key=certs/es01/es01.key
      - xpack.security.http.ssl.certificate=certs/es01/es01.crt
      - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.transport.ssl.enabled=true
      - xpack.security.transport.ssl.key=certs/es01/es01.key
      - xpack.security.transport.ssl.certificate=certs/es01/es01.crt
      - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.transport.ssl.verification_mode=certificate
      - xpack.license.self_generated.type=${LICENSE}
      - xpack.ml.use_auto_machine_memory_percent=true
    mem_limit: ${MEM_LIMIT}
    ulimits:
      memlock:
        soft: -1
        hard: -1
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120

  es02:
    depends_on:
      - es01
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: es02
    hostname: es02
    restart: unless-stopped
    volumes:
      - elastic-stack-certs:/usr/share/elasticsearch/config/certs
      - elastic-stack-es02:/usr/share/elasticsearch/data
    environment:
      - node.name=es02
      - cluster.name=${CLUSTER_NAME}
      - cluster.initial_master_nodes=es01,es02,es03
      - discovery.seed_hosts=es01,es03
      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
      - bootstrap.memory_lock=true
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=true
      - xpack.security.http.ssl.key=certs/es02/es02.key
      - xpack.security.http.ssl.certificate=certs/es02/es02.crt
      - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.transport.ssl.enabled=true
      - xpack.security.transport.ssl.key=certs/es02/es02.key
      - xpack.security.transport.ssl.certificate=certs/es02/es02.crt
      - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.transport.ssl.verification_mode=certificate
      - xpack.license.self_generated.type=${LICENSE}
      - xpack.ml.use_auto_machine_memory_percent=true
    mem_limit: ${MEM_LIMIT}
    ulimits:
      memlock:
        soft: -1
        hard: -1
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120

  es03:
    depends_on:
      - es02
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: es03
    hostname: es03
    restart: unless-stopped
    volumes:
      - elastic-stack-certs:/usr/share/elasticsearch/config/certs
      - elastic-stack-es03:/usr/share/elasticsearch/data
    environment:
      - node.name=es03
      - cluster.name=${CLUSTER_NAME}
      - cluster.initial_master_nodes=es01,es02,es03
      - discovery.seed_hosts=es01,es02
      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
      - bootstrap.memory_lock=true
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=true
      - xpack.security.http.ssl.key=certs/es03/es03.key
      - xpack.security.http.ssl.certificate=certs/es03/es03.crt
      - xpack.security.http.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.transport.ssl.enabled=true
      - xpack.security.transport.ssl.key=certs/es03/es03.key
      - xpack.security.transport.ssl.certificate=certs/es03/es03.crt
      - xpack.security.transport.ssl.certificate_authorities=certs/ca/ca.crt
      - xpack.security.transport.ssl.verification_mode=certificate
      - xpack.license.self_generated.type=${LICENSE}
      - xpack.ml.use_auto_machine_memory_percent=true
    mem_limit: ${MEM_LIMIT}
    ulimits:
      memlock:
        soft: -1
        hard: -1
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s --cacert config/certs/ca/ca.crt https://localhost:9200 | grep -q 'missing authentication credentials'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120

  kibana:
    depends_on:
      es01:
        condition: service_healthy
      es02:
        condition: service_healthy
      es03:
        condition: service_healthy
    image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
    container_name: kibana
    hostname: kibana
    restart: unless-stopped
    volumes:
      - elastic-stack-certs:/usr/share/kibana/config/certs
      - elastic-stack-kibana:/usr/share/kibana/data
    ports:
      - ${KIBANA_PORT}:5601
    environment:
      - SERVERNAME=kibana
      - ELASTICSEARCH_HOSTS=https://es01:9200
      - ELASTICSEARCH_USERNAME=kibana_system
      - ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
      - ELASTICSEARCH_SSL_CERTIFICATEAUTHORITIES=config/certs/ca/ca.crt
      - xpack.encryptedSavedObjects.encryptionKey=${KIBANA_ENCRYPTED_SAVED_OBJECTS_ENCRYPTION_KEY}
      - xpack.reporting.encryptionKey=${KIBANA_REPORTING_ENCRYPTION_KEY}
      - xpack.security.encryptionKey=${KIBANA_SECURITY_ENCRYPTION_KEY}
    mem_limit: ${MEM_LIMIT}
    healthcheck:
      test:
        [
          "CMD-SHELL",
          "curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'",
        ]
      interval: 10s
      timeout: 10s
      retries: 120

volumes:
  elastic-stack-certs:
    driver: local
  elastic-stack-es01:
    driver: local
  elastic-stack-es02:
    driver: local
  elastic-stack-es03:
    driver: local
  elastic-stack-kibana:
    driver: local

networks:
  default:
    external: true
    name: rod

如果本文对您有所帮助,欢迎打赏支持作者!

Licensed under CC BY-NC-SA 4.0
最后更新于 2026-08-26 08:52
使用 Hugo 构建
主题 StackJimmy 设计