Docker Compose: Connecting to an Elasticsearch Container with Django

Article by Wayne Fagan. Published on 23 Feb, 2020.

This guide is to help others who are interested in connecting **Django** to a **Elasticsearch** container with **Docker Compose**. Assuming both Docker and Docker Compose have been installed on your local system, you will then need to create both a **Dockerfile** and **docker-compose.yml** file in the project root. After you have built your **Dockerfile** you will need to focus on building the **docker-compose.yml** file, which is what we will focus on now. A typical layout may look something like the following:

version: '3.7'

services:
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    tty: true
    volumes:
      - .:/app
    ports:
      - "8000:8000"
    stdin_open: true
    depends_on:
      - postgresql
    env_file:
      - base/.env
  postgresql:
    image: postgres:12
    environment:
      POSTGRES_DB: example-db
      POSTGRES_USER: example-user
      POSTGRES_PASSWORD: example-password
    ports:
      - "54321:5432"
    volumes:
      - ./postgres-data:/var/lib/postgresql/data

In the above we are creating 2 containers, one for the web server and the other for the PostgreSQL database. Next we will update the above to include an Elasticsearch container.

elasticsearch:
  image: elasticsearch:2.4
  environment:
    discovery-type: "single-node"
    ES_JAVA_OPTS: "-Xms512m -Xmx512m"
  ports:
    - "9200:9200"
    - "9300:9300"

The above is basically saying that the container name is **elasticsearch**, and we are going to use version 2.4 of Elasticsearch (Django requirement). Set the discovery type to **single-node** which means that it will be the master node which also restricts it from joining a cluster. Next **ES_JAVA_OPTS** sets the memory requirements, 512 megabytes. And finally, the container will be bound to ports 9200 and 9300 and we going to mount a persistent volume.

Once you've added the new container the **docker-compose.yml** file will look like the following:

version: '3.7'

services:
  web:
    build: .
    command: python manage.py runserver 0.0.0.0:8000
    tty: true
    volumes:
      - .:/app
    ports:
      - "8000:8000"
    stdin_open: true
    depends_on:
      - postgresql
    env_file:
      - base/.env
  postgresql:
    image: postgres:12
    environment:
      POSTGRES_DB: example-db
      POSTGRES_USER: example-user
      POSTGRES_PASSWORD: example-password
    ports:
      - "54321:5432"
    volumes:
      - ./postgres-data:/var/lib/postgresql/data
  elasticsearch:
    image: elasticsearch:2.4
    environment:
      discovery-type: "single-node"
      ES_JAVA_OPTS: "-Xms512m -Xmx512m"
    ports:
      - "9200:9200"
      - "9300:9300"

Next we will need to update **settings.py** in the Django project to include the following:

ELASTICSEARCH_DSL = {
    'default': {
        'hosts': 'elasticsearch:9200'
    },
}

Notice that in the string value of the key **hosts** in the dictionary object we are referring to the container name for Elasticsearch. If you change the container name from **elasticsearch** in **docker-compose.yml** you will also need to change it in **settings.py**.

Now run **docker-compose up -d** to start your containers, then run **docker ps** to view your started containers. You should now see 3 containers, one for each of the services listed in **docker-compose.yml**: web, postgresql, and elasticsearch.