A single-node Elasticsearch in Docker is the standard dev setup: one container, dev-mode discovery, modest JVM heap, persistent volume. The image is from docker.elastic.co, not Docker Hub, and there are three things that catch first-time users — a Linux kernel setting, the JVM heap default, and the security defaults that turned on in 8.0.
How do I run Elasticsearch in Docker?
docker run -d --name es \
-e discovery.type=single-node \
-e xpack.security.enabled=false \
-e ES_JAVA_OPTS="-Xms512m -Xmx512m" \
-p 9200:9200 \
-v es-data:/usr/share/elasticsearch/data \
docker.elastic.co/elasticsearch/elasticsearch:8.16.0Single-node mode, security disabled (dev only), 512 MB JVM heap, port 9200 published, data volume mounted. Test it:
curl http://127.0.0.1:9200The cluster info JSON comes back.
Configure version, ports, heap, and volume.
On Linux: fix vm.max_map_count first
Elasticsearch uses memory-mapped files heavily and needs a higher vm.max_map_count than the Linux default. Without this, the container starts but logs an error and refuses to serve requests.
sudo sysctl -w vm.max_map_count=262144Make it persistent across reboots:
echo 'vm.max_map_count=262144' | sudo tee /etc/sysctl.d/99-elasticsearch.confOn Docker Desktop (Mac and Windows), this is handled inside Docker's VM — you don't need to set it on the host.
The basic run command
docker run -d --name :container_name \
-e discovery.type=single-node \
-e xpack.security.enabled=false \
-e ES_JAVA_OPTS="-Xms:heap -Xmx:heap" \
-p :host_port:9200 \
-v :volume:/usr/share/elasticsearch/data \
docker.elastic.co/elasticsearch/elasticsearch::es_versionThree env vars to know:
discovery.type=single-node— tells ES not to look for cluster peers. Required for one-container setups.xpack.security.enabled=false— disables the auth/TLS features turned on by default in 8.0+. For dev only. With it enabled, the first start prints a generatedelasticuser password and you need it to connect; convenient for production-shaped local setups, friction for quick experiments.ES_JAVA_OPTS="-Xms512m -Xmx512m"— sets the JVM heap (initial = max = 512 MB). The image's default heap can easily eat 1-2 GB on a host that didn't ask for it; pin the size.
Why mount /usr/share/elasticsearch/data
ES stores all indices, shard data, and the cluster state under /usr/share/elasticsearch/data inside the container. Same pattern as the other databases — without a volume, that data is in the container's writable layer and dies with docker rm.
docker stop :container_name && docker rm :container_name
docker run -d --name :container_name \
-e discovery.type=single-node \
-e xpack.security.enabled=false \
-e ES_JAVA_OPTS="-Xms:heap -Xmx:heap" \
-p :host_port:9200 \
-v :volume:/usr/share/elasticsearch/data \
docker.elastic.co/elasticsearch/elasticsearch::es_version
# Indices are still there.Practical usage: connecting and indexing
Health check:
curl http://127.0.0.1::host_port/_cluster/health?prettyCreate an index, post a document, search:
curl -X POST http://127.0.0.1::host_port/articles/_doc -H 'Content-Type: application/json' -d '{
"title": "Hello Elasticsearch",
"body": "First document"
}'
curl 'http://127.0.0.1::host_port/articles/_search?pretty&q=Hello'Pair with Kibana for a UI:
services:
es:
image: docker.elastic.co/elasticsearch/elasticsearch::es_version
environment:
discovery.type: single-node
xpack.security.enabled: "false"
ES_JAVA_OPTS: "-Xms:heap -Xmx:heap"
volumes:
- :volume:/usr/share/elasticsearch/data
ports:
- "::host_port:9200"
kibana:
image: docker.elastic.co/kibana/kibana::es_version
depends_on:
- es
ports:
- "5601:5601"
volumes:
:volume:Kibana on http://127.0.0.1:5601 after both containers start.
Common pitfalls
vm.max_map_count too low— set it (see Linux section above). Docker Desktop handles this; bare-metal Linux does not.- OOM kills. Set
ES_JAVA_OPTS="-Xms512m -Xmx512m"(or larger for real workloads). Without the cap, the JVM can grab gigabytes. - Security blocking connections in 8.x. Either set
xpack.security.enabled=falsefor dev, or accept the generated password from the first-start logs. - Pulling from Docker Hub instead of
docker.elastic.co. The Hub still has an oldelasticsearchmirror; the current ES is only ondocker.elastic.co. Same with Kibana. - Apple Silicon and older ES. The arm64 image arrived in 7.17+; pre-7.17 ES on Apple Silicon needs
--platform linux/amd64and emulation.
What to do next
- How to Use ElasticPress with WP_Query — pair this with WordPress.
- Elasticsearch Cheat Sheet — once it's running, the query-side reference.
- Elasticsearch vs OpenSearch for ElasticPress — if you were considering OpenSearch instead.
FAQ
Sources
Authoritative references this article was fact-checked against.
- Elastic's official Docker registrydocker.elastic.co
- Elasticsearch Docker — official guideelastic.co

