Elasticsearch 已經是現今開發者欲實現搜尋功能的一條捷徑,其易用的框架以及便利的 API(Application Programming Interface) 都十分易於開發與整合,所以許多網頁或 APP 應用中的搜尋功能其實背後都使用 Elasticsearch 進行建構,因此學會如何使用 Elasticsearch 也是相當值回票價的一件事。

本文將利用 Docker 建立 Elasticsearch 的實驗環境,給予初學者一個進入 Elasticsearch 世界的方便之門。

本文環境

  • macOS 10.15
  • Docker Desktop 3.1.0

Single Node Elasticsearch

Docker 官方有提供 Elasticsearch 的映像檔(image),所以透過 Docker 建立 Elasticsearch 相當方便。

如果只是需要一台 Elasticsearch 伺服器的話,可用以下指令架設(需將 <欲安裝的版本> 以及 <container名字> 按照需求更改):

$ docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --name=<container名字> docker.elastic.co/elasticsearch/elasticsearch:<欲安裝的版本號>

例如安裝 7.10.1 版的 Elasticsearch:

$ docker run -p 9200:9200 -p 9300:9300 -e "discovery.type=single-node" --name=myes docker.elastic.co/elasticsearch/elasticsearch:7.10.1

啟動成功的話,用瀏覽器打開 http://localhost:9200 將會看到以下畫面,代表 Elasticsearch 伺服器正在運作:

不過,與 Elasticsearch 伺服器之間的操作大多是透過 RESTful API 的方式進行,如果沒有工具協助的話,其實較為不方便,在此推薦透過 Elastichsearch 官方推薦的 Kibana 作為我們操作 Elasticsearch 的工具。

Kibana

Kibana 同樣可以透過 Docker 安裝,以下 Docker 指令是安裝 Kibana 的範本:

$ docker run --link <Elasticsearch container Id 或名字>:elasticsearch -p 5601:5601 docker.elastic.co/kibana/kibana
:<欲安裝的版本號>

例如以下安裝 7.10.1 版本的 Kibana ,並用 --link 參數將上一章節的 myes 與 Kibana 網路連結在一起,讓 Kibana 能夠存取該 Elasticsearch 伺服器:

$ docker run --link myes:elasticsearch -p 5601:5601 docker.elastic.co/kibana/kibana:7.10.1

成功的話,用瀏覽器打開 http://localhost:5601 將會看到以下畫面,代表 Kibana 已經開始運作,接下來就能夠透過 Kibana 與 Elasticsearch 進行互動。

新增測試資料至 Elasticsearch

順利架設 Kibana 之後,可以使用 Kibana 提供的 DevTool 操作 Elasticsearch:

例如,以下操作 Elasticsearch 在 movies 索引(index)資料庫中新增 3 筆電影資料(左側欄是操作指令的輸入框,右側是執行結果):

POST _bulk
{ "index" : { "_index" : "movies", "_id": 1} }
{"country":"美國","name":"冰雪奇緣2 (英文版)","releaseDate":"2019-11-21T00:00:00","issue":"台灣華特迪士尼股份有限公司","produce":"BUENA VISTA INTERNATIONAL, INC.","theaterCount":2,"tickets":66,"ticketChangeRate":1.4444444444444444,"amounts":7260,"totalTickets":1453910,"totalAmounts":343899138}
{ "index" : { "_index" : "movies", "_id": 2} }
{"country":"日本","name":"天氣之子","releaseDate":"2019-09-12T00:00:00","issue":"車庫娛樂股份有限公司","produce":"TOHO CO., LTD.","theaterCount":1,"tickets":62,"ticketChangeRate":-0.7801418439716312,"amounts":14730,"totalTickets":704769,"totalAmounts":168609995}
{ "index" : { "_index" : "movies", "_id": 3} }
{"country":"日本","name":"我的英雄學院劇場版:英雄新世紀","releaseDate":"2020-04-01T00:00:00","issue":"薩摩亞商羚邦(亞洲)有限公司台灣分公司","produce":"Toho Co., Ltd.","theaterCount":4,"tickets":198,"ticketChangeRate":-0.4277456647398844,"amounts":48700,"totalTickets":64937,"totalAmounts":15901569}

成功後,可以使用以下操作列出目前 Elasticsearch 內的所有索引資料庫:

GET _cat/indices?h=index

最後就能用以下操作進行搜尋「我的英雄」相關的電影:

POST /movies/_search
{
  "query": {
    "query_string": {
      "query": "我的英雄",
      "default_field": "name"
    }
  }
}

截至目前為止,就是 Elasticsearch 非常粗淺的操作初體驗。

p.s. 由於操作 Elasticsearch 相關 API 的說明並非本文重點,建議參閱 官方文件 學習更多相關操作

用 Docker 架設 Elasticsearch cluster

除了架設 Elasticsearch 單一伺服器,我們也能夠透過 Docker Compose 架設 Elasticsearch 叢集(cluster),由多台的 Elasticsearch 伺服器組成一個搜尋服務。

為了架設 Elasticsearch cluster 本章節會用到 2 個檔案,分別是:

  • docker-compose.yml
  • kibana.yml

這 2 個檔案需位於同一個資料夾內:

.
├── docker-compose.yml
└── kibana.yml

docker-compose.yml 內容如下,該檔案修改自官方所提供之範例,再此不多贅述各項設定之意涵。簡而言之,該檔案設定 2 台 Elasticsearch 伺服器(es01, es02) 組成 1 個名稱為 es-docker-cluster 的叢集,同時也架設 1 台 Kibana 與 es01, es02 在同 1 個網路環境內,讓彼此能夠互相存取:

version: '2.2'
services:
  es01:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.10.1
    restart: on-failure
    container_name: es01
    environment:
      - node.name=es01
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es02
      - cluster.initial_master_nodes=es01,es02
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data01:/usr/share/elasticsearch/data
    ports:
      - 9200:9200
    networks:
      - elastic
  es02:
    image: docker.elastic.co/elasticsearch/elasticsearch:7.10.1
    container_name: es02
    restart: on-failure
    environment:
      - node.name=es02
      - cluster.name=es-docker-cluster
      - discovery.seed_hosts=es01
      - cluster.initial_master_nodes=es01,es02
      - bootstrap.memory_lock=true
      - "ES_JAVA_OPTS=-Xms512m -Xmx512m"
    ulimits:
      memlock:
        soft: -1
        hard: -1
    volumes:
      - data02:/usr/share/elasticsearch/data
    networks:
      - elastic
  kibana:
    image: docker.elastic.co/kibana/kibana:7.10.1
    container_name: kibana
    restart: on-failure
    volumes:
      - ./kibana.yml:/usr/share/kibana/config/kibana.yml
    networks:
      - elastic
    ports:
      - 5601:5601

volumes:
  data01:
    driver: local
  data02:
    driver: local

networks:
  elastic:
    driver: bridge

kibana.yml 內容如下,該檔案為 Kibana 之設定檔,設定 Kibana 可以對 es01, es02 進行操作,並將 host IP 設定為 0.0.0.0 讓我們能夠透過網路存取 Docker 內的 Kibana :

server.name: kibana
server.host: 0.0.0.0
elasticsearch.hosts: ["http://es01:9200", "http://es02:9200"]
monitoring.enabled: true

準備好上述 2 個檔案之後,可用以下指令啟動 Elasticsearch 叢集:

$ docker-compose up

順利的話,輸入 docker ps 指令,可以看到 3 個 containers 正在運作:

$ docker ps
CONTAINER ID   IMAGE                                                  COMMAND                  CREATED       STATUS         PORTS                              NAMES
b0c81cbef130   docker.elastic.co/elasticsearch/elasticsearch:7.10.1   "/tini -- /usr/local…"   6 hours ago   Up 9 minutes   9200/tcp, 9300/tcp                 es02
47de8e56d7ad   docker.elastic.co/kibana/kibana:7.10.1                 "/usr/local/bin/dumb…"   6 hours ago   Up 6 hours     0.0.0.0:5601->5601/tcp             kibana
a968ca3812df   docker.elastic.co/elasticsearch/elasticsearch:7.10.1   "/tini -- /usr/local…"   6 hours ago   Up 6 hours     0.0.0.0:9200->9200/tcp, 9300/tcp   es01

也可以用瀏覽器打開 http://localhost:9200/_cat/nodes?v&pretty 看到叢集運作的情況:

如果要使用 Kibana 的話,則是用瀏覽器打開 http://localhost:5601/

結語

以上就是用 Docker 架設 Elasticsearch 環境的方法,但也僅僅只是學習 Elasticsearch 的開始,後續 Elasticsearch 的搜尋精準度、效能等等,事實上都有賴開發者進行調整才能有所改善,並非裝好 Elasticsearch 就等於打造好一套完美的搜尋功能,因為 Elasticsearch 也只是提供框架讓我們可以省去開發搜尋功能路上一些繁瑣的事項而已。

Happy Coding!

References

https://www.elastic.co/guide/en/elasticsearch/reference/current/docker.html#docker

https://www.elastic.co/guide/en/kibana/current/docker.html