Skip to content
View Article Network

Installing Elasticsearch and Kibana using Docker Compose

It has been a month since my last note; I have been focusing on exercise and fitness lately, feeling a bit lazy.

I recently wanted to practice using Elasticsearch, but I didn't want to install these services directly on my local machine. As usual, I used Docker to build the environment. This is a single-node configuration modified from the official Elastic GitHub Docker-Compose example.

Environment Setup

Create Data Directories

First, create the necessary data directories and set the correct permissions to avoid service startup failures due to permission issues later.

bash
# Create data directory
mkdir -p volumes/elasticsearch/data

# Set permissions (1000 is the user ID inside the Elasticsearch container)
sudo chown -R 1000:1000 volumes

TIP

  • I intentionally did not create a volume for logs, as permission issues with log files can cause startup failures when upgrading or migrating Elasticsearch.
  • Kibana does not store critical data itself, so no data volume was created for it.

Configuration Files

Environment Variable Settings (.env)

Create a .env file to manage environment variables:

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

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

# Version of Elastic products
STACK_VERSION=9.1.4

# 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=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)
# 1GB = 1073741824 bytes
MEM_LIMIT=2147483648

Docker Compose Configuration

Create a docker-compose.yml file:

yaml
services:
  elasticsearch:
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: elasticsearch
    restart: always
    environment:
      - node.name=elasticsearch
      - cluster.name=${CLUSTER_NAME}
      - discovery.type=single-node
      - ELASTIC_PASSWORD=${ELASTIC_PASSWORD}
      - bootstrap.memory_lock=true
      - xpack.security.enabled=true
      - xpack.security.http.ssl.enabled=false
      - xpack.security.transport.ssl.enabled=false
      - xpack.license.self_generated.type=${LICENSE}
      - ES_JAVA_OPTS=-Xms512m -Xmx512m -Xlog:gc:stdout:time,level,tags
    volumes:
      - ./volumes/elasticsearch/data:/usr/share/elasticsearch/data
    ports:
      - ${ES_PORT}:9200
    mem_limit: ${MEM_LIMIT}
    ulimits:
      memlock:
        soft: -1
        hard: -1
    healthcheck:
      test: ["CMD-SHELL", "curl -s -u elastic:${ELASTIC_PASSWORD} http://localhost:9200/_cluster/health | grep -q 'yellow\\|green'"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 60s

  kibana:
    depends_on:
      elasticsearch:
        condition: service_healthy
    image: docker.elastic.co/kibana/kibana:${STACK_VERSION}
    container_name: kibana
    restart: always
    environment:
      - SERVER_NAME=kibana
      - ELASTICSEARCH_HOSTS=http://elasticsearch:9200
      - ELASTICSEARCH_USERNAME=kibana_system
      - ELASTICSEARCH_PASSWORD=${KIBANA_PASSWORD}
    ports:
      - ${KIBANA_PORT}:5601
    mem_limit: ${MEM_LIMIT}
    healthcheck:
      test: ["CMD-SHELL", "curl -s -I http://localhost:5601 | grep -q 'HTTP/1.1 302 Found'"]
      interval: 30s
      timeout: 10s
      retries: 5
      start_period: 60s

  setup:
    image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION}
    container_name: elasticsearch-setup
    user: "0"
    command: >
      bash -c '
        echo "Waiting for Elasticsearch to start...";
        until curl -s -u elastic:${ELASTIC_PASSWORD} http://elasticsearch:9200/_cluster/health?pretty | grep -q "yellow\|green"; do
          echo "Elasticsearch is not ready yet, waiting...";
          sleep 10;
        done;
        echo "Setting kibana_system user password...";
        curl -s -X POST -u elastic:${ELASTIC_PASSWORD} -H "Content-Type: application/json" \
          http://elasticsearch:9200/_security/user/kibana_system/_password \
          -d "{\"password\":\"${KIBANA_PASSWORD}\"}";
        echo "Initialization complete!";
      '
    depends_on:
      elasticsearch:
        condition: service_healthy

Configuration Explanation

Configuration Items

  • Single-node mode: discovery.type=single-node is suitable for development environments.
  • SSL Disabled: To simplify the setup, SSL for both HTTP and Transport layers has been disabled.
  • Memory Locking: bootstrap.memory_lock=true prevents the JVM heap from being swapped to disk.
  • Health Check: Ensures that dependent services only start after the service has started successfully.
  • kibana_system password: Elasticsearch automatically creates the kibana_system account, but the password is a random string, so the setup service uses the API to set a specified password.

Common Issues and Solutions

  • Insufficient Memory:

    • Adjust MEM_LIMIT in .env or modify ES_JAVA_OPTS.
    • It is recommended to set the JVM Heap to about 50% of the host's memory.
  • Permission Issues:

    • Confirm that the volumes/elasticsearch/data permission is UID 1000:1000.
    • If errors persist, you can test with sudo chmod -R 777 volumes/elasticsearch/data (development environment only).

Changelog

    • Initial document created.
    • Fixed missing restart configuration in the YAML file that prevented automatic startup on reboot.