我已经设置了elasticsearch / kibana docker配置,并且我想使用@ elastic / elasticsearch客户端节点从docker容器内部连接到elasticsearch。但是,连接正在“定时”。
该项目的灵感来自Patrick Triest:https://blog.patricktriest.com/text-search-docker-elasticsearch/
但是,为了连接kibana,使用更新的ES映像和新的Elasticsearch节点客户端,我进行了一些修改。
我正在使用以下docker-compose文件:
version: "3"
services:
api:
container_name: mp-backend
build: .
ports:
- "3000:3000"
- "9229:9229"
environment:
- NODE_ENV=local
- ES_HOST=elasticsearch
- PORT=3000
elasticsearch:
image: docker.elastic.co/elasticsearch/elasticsearch:7.5.1
container_name: elasticsearch
environment:
- node.name=elasticsearch
- cluster.name=es-docker-cluster
- discovery.type=single-node
- bootstrap.memory_lock=true
- "ES_JAVA_OPTS=-Xms512m -Xmx512m"
- "http.cors.allow-origin=*"
- "http.cors.enabled=true"
- "http.cors.allow-headers=X-Requested-With,X-Auth-Token,Content-Type,Content-Length,Authorization"
- "http.cors.allow-credentials=true"
ulimits:
memlock:
soft: -1
hard: -1
volumes:
- data01:/usr/share/elasticsearch/data
ports:
- 9200:9200
networks:
- elastic
kibana:
image: docker.elastic.co/kibana/kibana:7.5.1
ports:
- "5601:5601"
links:
- elasticsearch
networks:
- elastic
depends_on:
- elasticsearch
volumes:
data01:
driver: local
networks:
elastic:
driver: bridge
建立/启动容器时,我能够从ES处获得响应:curl -XGET“ localhost:9200”,“您知道,用于搜索” ...并且kibana正在运行并能够连接到索引
我在后端容器(connection.js)中有以下文件:
const { Client } = require("@elastic/elasticsearch");
const client = new Client({ node: "http://localhost:9200" });
/*Check the elasticsearch connection */
async function health() {
let connected = false;
while (!connected) {
console.log("Connecting to Elasticsearch");
try {
const health = await client.cluster.health({});
connected = true;
console.log(health.body);
return health;
} catch (err) {
console.log("ES Connection Failed", err);
}
}
}
health();
如果我在容器外部运行它,则会得到预期的响应:
节点服务器/connection.js
Connecting to Elasticsearch
{
cluster_name: 'es-docker-cluster',
status: 'yellow',
timed_out: false,
number_of_nodes: 1,
number_of_data_nodes: 1,
active_primary_shards: 7,
active_shards: 7,
relocating_shards: 0,
initializing_shards: 0,
unassigned_shards: 3,
delayed_unassigned_shards: 0,
number_of_pending_tasks: 0,
number_of_in_flight_fetch: 0,
task_max_waiting_in_queue_millis: 0,
active_shards_percent_as_number: 70
}
但是,如果我在容器中运行它:
docker exec mp后端“节点”“ server / connection.js”
然后我得到以下答复:
Connecting to Elasticsearch
ES Connection Failed ConnectionError: connect ECONNREFUSED 127.0.0.1:9200
at onResponse (/usr/src/app/node_modules/@elastic/elasticsearch/lib/Transport.js:214:13)
at ClientRequest.<anonymous> (/usr/src/app/node_modules/@elastic/elasticsearch/lib/Connection.js:98:9)
at ClientRequest.emit (events.js:223:5)
at Socket.socketErrorListener (_http_client.js:415:9)
at Socket.emit (events.js:223:5)
at emitErrorNT (internal/streams/destroy.js:92:8)
at emitErrorAndCloseNT (internal/streams/destroy.js:60:3)
at processTicksAndRejections (internal/process/task_queues.js:81:21) {
name: 'ConnectionError',
meta: {
body: null,
statusCode: null,
headers: null,
warnings: null,
meta: {
context: null,
request: [Object],
name: 'elasticsearch-js',
connection: [Object],
attempts: 3,
aborted: false
}
}
}
因此,我尝试将客户端连接更改为(我读过一些可能有所帮助的地方):
const client = new Client({节点:“ http://172.24.0.1:9200”});
然后,我只是“卡住”了,等待响应。 “连接到Elasticsearch”只有一个console.log
我正在使用以下版本:
"@elastic/elasticsearch": "7.5.1"
您可能会看到,我对这里发生的事情不完全了解...我也尝试添加:
links:
- elasticsearch
networks:
- elastic
到api服务,没有任何运气。
有人知道我在做什么错吗?预先谢谢你:)
编辑:
我使用* _elastic在网络上进行了“ docker网络检查”。在那里,我看到以下内容:
"IPAM": {
"Driver": "default",
"Options": null,
"Config": [
{
"Subnet": "172.22.0.0/16",
"Gateway": "172.22.0.1"
}
]
},
更改客户端以连接到“ GateWay” IP:
const client = new Client({ node: "http://172.22.0.1:9200" });
然后它起作用了!我仍然想知道为什么这只是“尝试和错误”,是否有任何方法无需检查网络即可获取此Ip?
答案 0 :(得分:1)
在Docker中,localhost
(或相应的IPv4地址127.0.0.1,或相应的IPv6地址::: 1)通常表示“此容器”;您不能使用该主机名来访问在另一个容器中运行的服务。
在基于Compose的设置中,services:
块的名称(api
,elasticsearch
,kibana
)可用作主机名。需要注意的是,所有服务都必须位于同一Docker内部网络上。 Compose会为您创建一个容器,默认情况下会将容器附加到该容器。 (在您的示例中,api
位于default
网络上,而其他两个容器位于单独的elastic
网络上。)Docker文档中的Networking in Compose具有更多详细信息。 / p>
因此,要执行此操作,您需要告诉您的客户端代码以兑现您所设置的指向Elasticsearch的环境变量
const esHost = process.env.ES_HOST || 'localhost';
const esUrl = 'http://' + esHost + ':9200';
const client = new Client({ node: esUrl });
在您的docker-compose.yml
文件中,删除所有networks:
块以使用提供的default
网络。 (虽然您在那里,links:
是不必要的,并且Compose为您提供合理的container_name:
; api
可以合理地depends_on: [elasticsearch]
。)
由于我们为$ES_HOST
提供了一个后备选项,因此如果您在主机开发环境中工作,它将默认使用localhost
;在Docker外部,它表示“当前主机”,它将到达Elasticsearch容器的已发布端口。