Single Node Elasticsearch
GitHubDeploy a single Elasticsearch node using Docker Compose.
30m5m reading25m lab
Project Files
elasticsearch-single
Explorer
elasticsearch-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
services: elasticsearch: image: docker.elastic.co/elasticsearch/elasticsearch:${STACK_VERSION} container_name: elasticsearch volumes: - esdata:/usr/share/elasticsearch/data ports: - 9200:9200 - 9300:9300 env_file: - .env environment: - "ES_JAVA_OPTS=-Xms512m -Xmx512m" - network.host=0.0.0.0 - transport.host=0.0.0.0 - node.name=algo-es-node - cluster.name=${CLUSTER_NAME} - discovery.type=single-node - bootstrap.memory_lock=true - xpack.security.enabled=false - xpack.license.self_generated.type=${LICENSE} mem_limit: ${MEM_LIMIT} ulimits: memlock: soft: -1 hard: -1 healthcheck: test: ["CMD-SHELL", "curl --silent --fail localhost:9200/_cluster/health || exit 1"] interval: 10s timeout: 10s retries: 120 volumes: esdata: # driver: local # driver_opts: # o: bind # type: none # device: /mt/sda/es-data
YAMLUTF-8
Ln 392 files
Configuration
Download both files into a new folder — they work together. See Docker Compose environment variables and Elasticsearch important settings for full reference.elasticsearch-compose.yml — environment
environment:
- "ES_JAVA_OPTS=-Xms512m -Xmx512m" # JVM heap — set to half of MEM_LIMIT
- network.host=0.0.0.0 # bind REST API to all interfaces
- transport.host=0.0.0.0 # bind inter-node transport to all interfaces
- node.name=algo-es-node # node label shown in cluster stats
- cluster.name=${CLUSTER_NAME} # nodes with the same name form a cluster
- discovery.type=single-node # skip master election for one-node setup
- bootstrap.memory_lock=true # pin JVM heap in RAM — prevent OS swap
- xpack.security.enabled=false # no TLS/auth — development only
- xpack.license.self_generated.type=${LICENSE}
.env
STACK_VERSION=9.3.0
CLUSTER_NAME=vbv-ec-cluster
LICENSE=basic # trial = 30-day enterprise features
MEM_LIMIT=1073741824 # bytes — set to 50% of your available RAM (1 GB shown)
ES_PORT=9200 # change if port is in use
KIBANA_PORT=5601 # used by Kibana — change if port is in use
💡
Tip: MEM_LIMIT is in bytes. 2 GB = 2147483648, 4 GB = 4294967296, 8 GB = 8589934592.
Deploy
-
1
Use Download All in the Project Files section above to save both files into a new folder, e.g.
elasticsearch-single/ -
2
Open
.envand updateMEM_LIMITto 50% of your available RAM - 3 Open a terminal in that folder
# Linux only — macOS Docker Desktop handles this internally
sudo sysctl -w vm.max_map_count=262144
docker compose -f elasticsearch-compose.yml up -d
Watch the container start:
watch docker ps
Expected when healthy:
CONTAINER ID IMAGE STATUS
abc123 elasticsearch:9.3.0 Up 2 min (healthy)
Verify
curl -X GET "localhost:9200/_cluster/health?pretty"
Expected response:
{
"cluster_name" : "vbv-ec-cluster",
"status" : "green", # green = all shards assigned | yellow = replicas unassigned | red = data missing
"number_of_nodes" : 1, # 1 = one node, as configured
"number_of_data_nodes" : 1,
"unassigned_shards" : 0 # 0 = nothing waiting for placement
}
Common Issues
max_map_count error (Linux only)
# Error
max virtual memory areas vm.max_map_count [65530] is too low
# Fix
sudo sysctl -w vm.max_map_count=262144
echo "vm.max_map_count=262144" | sudo tee -a /etc/sysctl.conf
ℹ️
Note: Only happens on Linux. Elasticsearch uses mmap for index segments — the Linux default (65530) is too low. Docs
Memory lock warning
# Warning in logs
Unable to lock JVM Memory: error=12, reason=Cannot allocate memory
# Fix — lower MEM_LIMIT in .env to free up headroom, then restart
docker compose -f elasticsearch-compose.yml down && docker compose -f elasticsearch-compose.yml up -d
Port already in use
# Check what's using it
lsof -i :9200
# Or change ES_PORT in .env
ES_PORT=9201
Next Steps
- Kibana Setup — connect a UI to your running node