Using the Docker images in production
Self Managed
The following requirements and recommendations apply when running Elasticsearch in Docker in production, including some guidelines outlined in Important system configuration.
The following requirements and recommendations apply when running Elasticsearch in Docker in production.
The vm.max_map_count
kernel setting must be set to at least 262144
for production use.
How you set vm.max_map_count
depends on your platform.
Linux
To view the current value for the vm.max_map_count
setting, run:
grep vm.max_map_count /etc/sysctl.conf
vm.max_map_count=262144
To apply the setting on a live system, run:
sysctl -w vm.max_map_count=262144
To permanently change the value for the vm.max_map_count
setting, update the value in /etc/sysctl.conf
.
macOS with Docker for Mac
The vm.max_map_count
setting must be set within the xhyve virtual machine:
From the command line, run:
screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
Press enter and use
sysctl
to configurevm.max_map_count
:sysctl -w vm.max_map_count=262144
To exit the
screen
session, typeCtrl a d
.
Windows and macOS with Docker Desktop
The vm.max_map_count
setting must be set via docker-machine:
docker-machine ssh
sudo sysctl -w vm.max_map_count=262144
Windows with Docker Desktop WSL 2 backend
The vm.max_map_count
setting must be set in the "docker-desktop" WSL instance before the Elasticsearch container will properly start. There are several ways to do this, depending on your version of Windows and your version of WSL.
If you are on Windows 10 before version 22H2, or if you are on Windows 10 version 22H2 using the built-in version of WSL, you must either manually set it every time you restart Docker before starting your Elasticsearch container, or (if you do not wish to do so on every restart) you must globally set every WSL2 instance to have the vm.max_map_count
changed. This is because these versions of WSL do not properly process the /etc/sysctl.conf file.
To manually set it every time you reboot, you must run the following commands in a command prompt or PowerShell window every time you restart Docker:
wsl -d docker-desktop -u root
sysctl -w vm.max_map_count=262144
If you are on these versions of WSL and you do not want to have to run those commands every time you restart Docker, you can globally change every WSL distribution with this setting by modifying your %USERPROFILE%.wslconfig as follows:
[wsl2]
kernelCommandLine = "sysctl.vm.max_map_count=262144"
This will cause all WSL2 VMs to have that setting assigned when they start.
If you are on Windows 11, or Windows 10 version 22H2 and have installed the Microsoft Store version of WSL, you can modify the /etc/sysctl.conf within the "docker-desktop" WSL distribution, perhaps with commands like this:
wsl -d docker-desktop -u root
vi /etc/sysctl.conf
and appending a line which reads:
vm.max_map_count = 262144
By default, Elasticsearch runs inside the container as user elasticsearch
using uid:gid 1000:0
.
If you are bind-mounting a local directory or file, it must be readable by the elasticsearch
user. In addition, this user must have write access to the config, data and log dirs (Elasticsearch needs write access to the config
directory so that it can generate a keystore). A good strategy is to grant group access to gid 0
for the local directory.
One exception is Openshift, which runs containers using an arbitrarily assigned user ID. Openshift presents persistent volumes with the gid set to 0
, which works without any adjustments.
For example, to prepare a local directory for storing data through a bind-mount:
mkdir esdatadir
chmod g+rwx esdatadir
chgrp 0 esdatadir
You can also run an Elasticsearch container using both a custom UID and GID. You must ensure that file permissions will not prevent Elasticsearch from executing. You can use one of two options:
- Bind-mount the
config
,data
andlogs
directories. If you intend to install plugins and prefer not to create a custom Docker image, you must also bind-mount theplugins
directory. - Pass the
--group-add 0
command line option todocker run
. This ensures that the user under which Elasticsearch is running is also a member of theroot
(GID 0) group inside the container.
Increased ulimits for nofile and nproc must be available for the Elasticsearch containers. Verify the init system for the Docker daemon sets them to acceptable values.
To check the Docker daemon defaults for ulimits, run:
docker run --rm docker.elastic.co/elasticsearch/elasticsearch:9.0.0 /bin/bash -c 'ulimit -Hn && ulimit -Sn && ulimit -Hu && ulimit -Su'
If needed, adjust them in the Daemon or override them per container. For example, when using docker run
, set:
--ulimit nofile=65535:65535
Swapping needs to be disabled for performance and node stability. For information about ways to do this, see Disable swapping.
If you opt for the bootstrap.memory_lock: true
approach, you also need to define the memlock: true
ulimit in the Docker Daemon, or explicitly set for the container as shown in the sample compose file. When using docker run
, you can specify:
-e "bootstrap.memory_lock=true" --ulimit memlock=-1:-1
The image exposes TCP ports 9200 and 9300. For production clusters, randomizing the published ports with --publish-all
is recommended, unless you are pinning one container per host.
By default, Elasticsearch automatically sizes JVM heap based on a nodes’s roles and the total memory available to the node’s container. We recommend this default sizing for most production environments. If needed, you can override default sizing by manually setting JVM heap size.
To manually set the heap size in production, bind mount a JVM options file under /usr/share/elasticsearch/config/jvm.options.d
that includes your desired heap size settings.
For testing, you can also manually set the heap size using the ES_JAVA_OPTS
environment variable. For example, to use 1GB, use the following command.
docker run -e ES_JAVA_OPTS="-Xms1g -Xmx1g" -e ENROLLMENT_TOKEN="<token>" --name es01 -p 9200:9200 --net elastic -it docker.elastic.co/elasticsearch/elasticsearch:9.0.0
The ES_JAVA_OPTS
variable overrides all other JVM options. We do not recommend using ES_JAVA_OPTS
in production.
Pin your deployments to a specific version of the Elasticsearch Docker image. For example:
docker.elastic.co/elasticsearch/elasticsearch:9.0.0
You should use a volume bound on /usr/share/elasticsearch/data
for the following reasons:
- The data of your Elasticsearch node won’t be lost if the container is killed.
- Elasticsearch is I/O sensitive and the Docker storage driver is not ideal for fast I/O.
- It allows the use of advanced Docker volume plugins.
If you are using the devicemapper storage driver, do not use the default loop-lvm
mode. Configure docker-engine to use direct-lvm.
Consider centralizing your logs by using a different logging driver. Also note that the default json-file logging driver is not ideally suited for production use.