Не могу подружить Elasticsearch и Laravel
Есть вот такой метод
public function esSearch() {
$client = ClientBuilder::create()->setHosts(['172.20.0.1:9200'])->build();
$params = [
'index' => 'my_index',
'id' => 'test_id',
'body' => ['testField' => 'abc']
];
$result = $client->index($params);
dd($result);
}
В итоге получаю ошибку 504 Gateway Time-out
Все это дело крутится вертится в докере, у контейнера где Laravel задан статический ip, поэтому метод написал таким образом setHosts(['172.20.0.1:9200']), если заменить ip на localhost, то получаю No alive nodes found in your cluster
version: '3'
services:
#PHP Service
app:
build:
context: .
dockerfile: Dockerfile
image: digitalocean.com/php
container_name: app
restart: unless-stopped
tty: true
environment:
SERVICE_NAME: app
SERVICE_TAGS: dev
working_dir: /var/www
volumes:
- ./:/var/www
- ./docker/php/local.ini:/usr/local/etc/php/conf.d/local.ini
networks:
postgres:
ipv4_address: 172.20.128.2
#Nginx Service
webserver:
image: nginx:alpine
container_name: webserver
restart: unless-stopped
tty: true
ports:
- "80:80"
- "443:443"
volumes:
- ./:/var/www
- ./docker/nginx/conf.d/:/etc/nginx/conf.d/
networks:
- postgres
#Redis
redis:
image: 'redis:alpine'
ports:
- "6379:6379"
#PostgreSQL
postgres:
container_name: postgres_container
image: postgres
hostname: postgres
environment:
POSTGRES_DB: postgres
POSTGRES_USER: postgres
POSTGRES_PASSWORD: secret
PGDATA: /data/postgres
volumes:
- postgres:/data/postgres
ports:
- "5432:5432"
networks:
- postgres
restart: unless-stopped
pgadmin:
container_name: pgadmin_container
image: dpage/pgadmin4
environment:
PGADMIN_DEFAULT_EMAIL: ${PGADMIN_DEFAULT_EMAIL:[email protected]}
PGADMIN_DEFAULT_PASSWORD: ${PGADMIN_DEFAULT_PASSWORD:-admin}
volumes:
- pgadmin:/root/.pgadmin
ports:
- "${PGADMIN_PORT:-5050}:80"
networks:
- postgres
restart: unless-stopped
depends_on:
- postgres
#RabbitMQ
rabbit:
image: "rabbitmq:3-management"
hostname: "rabbit"
environment:
RABBITMQ_ERLANG_COOKIE: "SWQOKODSQALRPCLNMEQG"
RABBITMQ_DEFAULT_USER: "rabbitmq"
RABBITMQ_DEFAULT_PASS: "rabbitmq"
RABBITMQ_DEFAULT_VHOST: "/"
ports:
- "15672:15672"
- "5672:5672"
labels:
NAME: "rabbitmq"
networks:
- postgres
#ElasticSearch
es01:
image: docker.elastic.co/elasticsearch/elasticsearch:7.0.1
container_name: es01
environment:
- cluster.initial_master_nodes=es01
ulimits:
memlock:
soft: -1
hard: -1
ports:
- "9200:9200"
- "9300:9300"
networks:
- postgres
kibana:
image: docker.elastic.co/kibana/kibana:6.2.4
container_name: kibana
ports:
- "5601:5601"
depends_on:
- es01
networks:
- postgres
#Docker Networks
networks:
postgres:
ipam:
config:
- subnet: 172.20.0.0/16
volumes:
postgres:
pgadmin:
Ответы (1 шт):
Небольшое пояснение
docker-compose - это "обертка" над докером, сделана для удобства. В частности, команда создает подсети.
Поднимите ваши контейнеры docker-compose up и выполните docker network list - увидите все подсети докера. В этом списке будут как подсети, созданные из файла docker-compose.yml, так и другие, созданные в других проектах.
Теперь запустите ip route и вы увидите роуты типа br-... - их насоздавал докер.
Затем выполните docker-compose ps - увидите список контейнеров, и порты которые они прослушивают. Если видите 9000/tcp - значит порт виден только внутри подсети докера, и не виден с хост-машины. А если 0.0.0.0:8087->80/tcp - значит порт виден с хост-машины как 8087, и перенаправляется на 80 порт контейнера.
Среди них будет postgres - эта сеть прописана в файле. К ней подключены все ваши контейнеры. Поэтому к эластику можно обратиться как es01:9200 и es01:9300 - то есть прямо по названию контейнера и порта. Но так можно сделать только внутри контейнеров этой подсети, потому что докер имеет свой DNS-резолвер, каждый контейнер имеет свой IP адрес, и поэтому через localhost невозможно обратиться к другому контейнеру. А с хост машины можно подключиться через localhost:9200.
Я постарался расписать как это работает, потому что без понимания механики работы докер выглядит как какое-то волшебство.
Решение
Итак, вам нужно вместо IP адреса использовать название контейнера:
->setHosts(['es01:9200'])
а докер сам разрешит es01в IP адрес.
Можете даже войти в какой-нибудь контейнер и попинговать соседа.
docker-compose exec app bash, и в нем ping es01. Если в контейнере app есть bash, ping и сосед доступен, вы увидите пинги и реальный IP адрес - используйте такой прием для траблшутинга.