create an official docker image based on a well-accepted, open OS

Author: bean5Created Jan 11, 2017Updated Jul 24, 2024

https://github.com/krizsan/elastalert-docker exists, but it depends on iron/python:2 which on dockerhub doesn't like to a repository, meaning that we can't prove what is in it without manually inspection.

An official container based on this would be very helpful, more trustworthy, and more robust in environments. I build my own in a way similar to krizsan, but I base it on python:2.7.12-alpine:

Since I am new to python, I don't know a better way to reliably install requirements than to call pip install -r requirements.txt || pip install -r requirements.txt || pip install -r requirements.txt. Krizsan does pip install -e ., but I found that sometimes a dependency (stomp) ended up missing in the final container.

Note: https://github.com/Yelp/elastalert/pull/408 might help fulfill this request.

bash
# Elastalert Docker image running on Alpine Linux.

FROM python:2.7.12-alpine

RUN apk update && apk upgrade && apk add bash

# Set this environment variable to true to set timezone on container start.
ENV SET_CONTAINER_TIMEZONE false
# Default container timezone as found under the directory /usr/share/zoneinfo/.
ENV CONTAINER_TIMEZONE Europe/Stockholm

# Install software required for Elastalert and NTP for time synchronization.
RUN apk add python-dev gcc musl-dev tzdata openntpd

RUN apk add ca-certificates wget && update-ca-certificates
# Install pip - required for installation of Elastalert.
RUN \
	wget https://bootstrap.pypa.io/get-pip.py \
	&& python get-pip.py \
	&& rm get-pip.py

WORKDIR /opt
# URL from which to download Elastalert.
ENV ELASTALERT_URL https://github.com/Yelp/elastalert/archive/master.zip
# Elastalert home directory name.
ENV ELASTALERT_DIRECTORY_NAME elastalert
# Download and unpack Elastalert.
RUN \
	wget ${ELASTALERT_URL} \
	&& unzip *.zip \
	&& rm *.zip \
	&& mv e* ${ELASTALERT_DIRECTORY_NAME}

# Elastalert home directory full path.
ENV ELASTALERT_HOME /opt/${ELASTALERT_DIRECTORY_NAME}
WORKDIR ${ELASTALERT_HOME}

# Install Elastalert (use `-r requirements.txt` with 3 times more tries than default for resiliency instead of -e)
RUN \
	python setup.py install \
	&& (pip install -r requirements.txt || pip install -r requirements.txt || pip install -r requirements.txt) \
# Install Supervisor.
	&& easy_install supervisor

# Create directories. The /var/empty directory is used by openntpd.
RUN \
	mkdir -p /opt/config \
	&& mkdir -p /opt/rules \
	&& mkdir -p /opt/logs \
	&& mkdir -p /var/empty

ENV ELASTICSEARCH_HOST elasticsearch
# Port on above Elasticsearch host. Set in default Elasticsearch configuration file.
ENV ELASTICSEARCH_PORT 9200

# Clean up.
RUN \
 	apk del python-dev \
	&& apk del musl-dev \
	&& apk del gcc

# Copy the script used to launch the Elastalert when a container is started.
ADD ./command.sh /opt/
# Make the start-script executable.
RUN chmod +x /opt/command.sh

# Launch Elastalert when a container is started.
CMD ["/opt/command.sh"]

Contents of command.sh:

bash
#!/bin/sh

set -e

# Set the timezone.
if [ "$SET_CONTAINER_TIMEZONE" = "true" ]; then
	setup-timezone -z ${CONTAINER_TIMEZONE} && \
	echo "Container timezone set to: $CONTAINER_TIMEZONE"
else
	echo "Container timezone not modified"
fi

# Force immediate synchronisation of the time and start the time-synchronization service.
# In order to be able to use ntpd in the container, it must be run with the SYS_TIME capability.
# In addition you may want to add the SYS_NICE capability, in order for ntpd to be able to modify its priority.
ntpd -s

# Wait until Elasticsearch is online since otherwise Elastalert will fail.
echo "Checking whether elasticsearch is up."

rm -f garbage_file
while ! wget -O garbage_file ${ELASTICSEARCH_PROTOCOL}://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT} 2>/dev/null
do
	echo "Waiting for Elasticsearch...${ELASTICSEARCH_PROTOCOL}://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}"
	rm -f garbage_file
	sleep 1
done
rm -f garbage_file
echo "Sleeping for 5s to ensure that elasticsearch comes up."
sleep 5

# Check if the Elastalert index exists in Elasticsearch and create it if it does not.
if ! wget -O garbage_file ${ELASTICSEARCH_PROTOCOL}://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}/${ELASTICSEARCH_INDEX} 2>/dev/null
then
	echo "Creating Elastalert index in Elasticsearch...${ELASTICSEARCH_PROTOCOL}://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}/${ELASTICSEARCH_INDEX}"
    # elastalert-create-index --index ${ELASTICSEARCH_INDEX} --old-index ""
	apk add curl; curl -X PUT ${ELASTICSEARCH_PROTOCOL}://${ELASTICSEARCH_HOST}:${ELASTICSEARCH_PORT}/${ELASTICSEARCH_INDEX}; apk del curl
else
	echo "Elastalert index already exists in Elasticsearch."
fi

echo "Starting Elastalert..."
# Following the help mentioned at http://stackoverflow.com/questions/35779450/how-to-run-elastalert-with-supervisor
python /opt/elastalert/elastalert/elastalert.py --config /opt/config/config.yaml --verbose