'Docker secrets in ELK stack
I have been struggling for the last few days to set up the ELK stack on Docker. I would appreciate your help.
Problem
docker-compose.yml file that I'm using is from the official repo
Instead of using .env file for sensitive data such as passwords or API keys, I'm trying to use Docker secrets. However, unfortunately, the official image of elasticsearch:8.0.0 does not provide _FILE postfix for its environment variables (e.g. ELASTIC_PASSWORD_FILE).
After some research, I found this Medium article where the author shows a trick how to "expand" env variables from Docker secrets. Basically, to turn:
ELASTIC_PASSWORD={{DOCKER-SECRET:elk-elastic-password}} into ELASTIC_PASSWORD=pass4elastic
Considering that our Docker secret has the name elk-elastic-password and content pass4elastic. To use it, the author recommends adding the env_secrets_expand.sh script file to container ENTRYPOINT and invoking it with source env_secrets_expand.sh.
I noticed that overriding the default ENTRYPOINT of the elasticsearch:8.0.0 image is not a good idea as it doesn't behave correctly. Instead, I've tried to "extend" it by creating my own docker-entrypoint.sh where I will first expand env variables and second call parent entrypoint script.
Files & testing setup
docker-compose.yml
version: "3.8"
services:
setup:
build: .
secrets:
- elk-elastic-password
environment:
- ELASTIC_PASSWORD={{DOCKER-SECRET:elk-elastic-password}}
secrets:
elk-elastic-password:
file: ./elk-elastic-password.txt
Dockerfile
FROM docker.elastic.co/elasticsearch/elasticsearch:8.0.0
COPY env_secrets_expand.sh /env_secrets_expand.sh
COPY docker-entrypoint.sh /docker-entrypoint.sh
ENTRYPOINT ["/docker-entrypoint.sh"]
docker-entrypoint.sh
#!/bin/bash
source /env_secrets_expand.sh
exec /bin/tini -- /usr/local/bin/docker-entrypoint.sh "$@"
docker-entrypoint.sh Same as in the original repo
All the files are also located in my testing repo
Steps to reproduce
docker compose build
docker compose up -d
docker exec -it elk-secrets-setup-1 bash
# In container
printenv | grep ELASTIC_PASSWORD
# output: ELASTIC_PASSWORD={{DOCKER-SECRET:elk-elastic-password}} (Incorrect)
# After manually "expanding" vars:
source /env_secrets_expand.sh
printenv | grep ELASTIC_PASSWORD
# output: ELASTIC_PASSWORD=pass4elastic (Correct)
Conclusions
Expansion of variables in docker-entrypoint.sh doesn't affect variables inside the container. However, calling docker-entrypoint.sh manually has the correct effect.
My main objective is to replace .env with docker secrets I would appreciate it if you could provide fixes to my current approach or suggest something better.
Solution 1:[1]
My task was similar; I wanted to map the ELASTICSEARCH_SERVICEACCOUNTTOKEN variable, which contains the token that Kibana should use to connect to Elasticsearch.
I solved this by using the following entrypoint, which achieves a similar thing to yours – it can expand arbitrary environment variables based on their _FILE counterparts:
#!/usr/bin/env sh
: "${ENV_SECRETS_DIR:=/run/secrets}"
env_secret_debug()
{
if [ -n "$ENV_SECRETS_DEBUG" ]; then
echo "$@"
fi
}
# expand known _FILE overrides
for env_var in \
ELASTICSEARCH_SERVICEACCOUNTTOKEN
do
file_env_var="${env_var}_FILE"
secret_file=$(printenv "$file_env_var")
if [ -n "$secret_file" ]; then
env_secret_debug "Expanding $env_var from contents of $secret_file"
if [ -f "$secret_file" ]; then
export "${env_var}=$(cat "$secret_file")"
else
echo "Error in entrypoint.sh: File '$secret_file' mapped by $env_var does not exist or is not readable!"
fi
unset $file_env_var
fi
done
exec /bin/tini -- /usr/local/bin/kibana-docker "$@"
Note the actual executable for Kibana is /usr/local/bin/kibana-docker – the original entrypoint does not really do more than that.
The entrypoint can expand the environment variable ELASTICSEARCH_SERVICEACCOUNTTOKEN based on the contents of the ELASTICSEARCH_SERVICEACCOUNTTOKEN_FILE environment variable, which you can point to a mounted secrets file.
My corresponding Dockerfile looks like this:
FROM docker.elastic.co/kibana/kibana:8.1.1
USER root
COPY --chown=1000:0 entrypoint.sh /usr/share/kibana/entrypoint.sh
USER kibana
ENTRYPOINT [ "/usr/share/kibana/entrypoint.sh" ]
Here's the snipped from the respective compose file:
kibana:
build:
- ./kibana_test_file:/run/secrets/kibana_test_file:ro
environment:
ELASTICSEARCH_SERVICEACCOUNTTOKEN_FILE: /run/secrets/kibana_test_file
ENV_SECRETS_DEBUG: 1
Now, this adds some maintenance effort. But you can find the original Dockerfiles here: https://github.com/elastic/dockerfiles
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
