Type to search.

Configure Elasticsearch Docker images in production

Self-managed

Self-managed deployments are Elastic Stack deployments managed without the assistance of an orchestrator.

Availability

  • Generally available

    This functionality is generally available and ready for production usage.

This documentation corresponds to the latest patch available for each minor version. If you're not using the latest patch, check the release notes for changes.

The following requirements and recommendations apply when running Elasticsearch in Docker in production, including some guidelines outlined in Important system configuration for Elasticsearch.

The vm.max_map_count kernel setting must be set to 1048576.

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:

Shell
grep vm.max_map_count /etc/sysctl.conf
vm.max_map_count=1048576

To apply the setting on a live system, run:

Shell
sysctl -w vm.max_map_count=1048576

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:

  1. From the command line, run:

    Shell
    screen ~/Library/Containers/com.docker.docker/Data/vms/0/tty
    
  2. Press enter and use sysctl to configure vm.max_map_count:

    Shell
    sysctl -w vm.max_map_count=1048576
    
  3. To exit the screen session, type Ctrl a d.

Windows and macOS with Docker Desktop

The vm.max_map_count setting must be set via docker-machine:

Shell
docker-machine ssh
sudo sysctl -w vm.max_map_count=1048576
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:

Shell
wsl -d docker-desktop -u root
sysctl -w vm.max_map_count=1048576

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:

Text
[wsl2]
kernelCommandLine = "sysctl.vm.max_map_count=1048576"

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:

Shell
wsl -d docker-desktop -u root
vi /etc/sysctl.conf

and appending a line which reads:

Text
vm.max_map_count = 1048576

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.

Important

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:

Shell
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 and logs directories. If you intend to install plugins and prefer not to create a custom Docker image, you must also bind-mount the plugins directory.
  • Pass the --group-add 0 command line option to docker run. This ensures that the user under which Elasticsearch is running is also a member of the root (GID 0) group inside the container.

Increased ulimits for open files and user process limits 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:

Shell
docker run --rm docker.elastic.co/elasticsearch/elasticsearch:9.5.6 /bin/bash -c 'ulimit -Hn && ulimit -Sn && ulimit -Hu && ulimit -Su'

Replace <SPECIFIC.VERSION.NUMBER> with the version of the Docker image you downloaded.

Shell
docker run --rm docker.elastic.co/elasticsearch/elasticsearch:<SPECIFIC.VERSION.NUMBER> /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:

Shell
--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:

Shell
-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.

Shell
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.5.6

Replace <SPECIFIC.VERSION.NUMBER> with the version of the Docker image you downloaded.

Shell
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:<SPECIFIC.VERSION.NUMBER>

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:

Shell
docker.elastic.co/elasticsearch/elasticsearch:9.5.6

Replace <SPECIFIC.VERSION.NUMBER> with the version of the Docker image you downloaded.

Shell
docker.elastic.co/elasticsearch/elasticsearch:<SPECIFIC.VERSION.NUMBER>

You should use a volume bound to /usr/share/elasticsearch/data for the following reasons:

  1. The data of your Elasticsearch node won’t be lost if the container is deleted.
  2. Elasticsearch is I/O sensitive and the Docker storage driver is not ideal for fast I/O.
  3. It allows the use of advanced Docker volume plugins.

We recommend you configure docker-engine to use the overlay2 storage driver for your workloads.

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.