How to run Consul on docker with initial key-value pair data?
Compose
Compose doesn't have "tasks" as built in concept, but you can set them up with multiple compose files in a project. A docker-compose-init.yml
could define the tasks, rather than long running services but you need to manage orchestration yourself. I've put an example on my consul demo.
docker-compose up -ddocker-compose -f docker-compose-init.yml run consul_init
Image Build
You can add image build RUN
steps to add the data. The complication here is running the server the same way you normally would, but in the background, and adding the data all in the one RUN
step.
FROM progrium/consul:latestRUN set -uex; \ consul agent -server --bootstrap -data-dir /consul/data & \ let "timeout = $(date +%s) + 15"; \ while ! curl -f -s http://localhost:8500/v1/status/leader | grep "[0-9]:[0-9]"; do\ if [ $(date +%s) -gt $timeout ]; then echo "timeout"; exit 1; fi; \ sleep 1; \ done; \ consul kv put somekey somevalue;
Image Startup
Some databases add a script to the image to populate data at startup. This is normally so users can control setup via environment variables injected at run time, like mysql/postgres/mongo.
FROM progrium/consul:latestENTRYPOINT my-entrypoint.sh
Then your script starts the server, sets up the data, and then at the end continues on as the image would have before.
I couldn't get the accepted solution to work for me. I'm guessing this is because the stub consul that it starts up during build time is somehow overwritten during run time.
Using the accepted answer as a jumping-off point, I instead added a loader script that starts up every time the container starts. The Dockerfile
below adds a "shim" to the Consul entrypoint script (see RUN sed
).
To use this:
- Add the
Dockerfile
below - Add an
init_kv/
directory next to theDockerfile
- Add json files to the
init_kv/
directory, such asyourkey.json
- Use the key as the name of the json file
- In this example, the key is
yourkey
- Run
docker build
/docker run
/docker-compose up
, etc
Of note:
- The loader script runs every time the container starts
- The loader script will refuse to load a key if it already exists
- In the example, if
yourkey
already exists, it will not be reloaded
- In the example, if
Dockerfile
# pull official base imageFROM consul# key-value shim loader# you can override this loader using an empty docker volume:ENV INIT_CONSUL_KV_DIR=/var/local/init_consul_kv.dRUN mkdir -p $INIT_CONSUL_KV_DIRCOPY kv_loader.sh /usr/local/bin/RUN sed -ie 's|^\(set .*\)|\1\n/usr/local/bin/kv_loader.sh \&|' /usr/local/bin/docker-entrypoint.shCOPY init_kv/ $INIT_CONSUL_KV_DIR/
kv_loader.sh
#!/bin/sh# wait until consul is up# then inject all key/value files as found in the init directoryset -uelet "timeout = $(date +%s) + 15"echo "kv_loader waiting for consul"while ! curl -f -s http://localhost:8500/v1/status/leader | grep "[0-9]:[0-9]"; do if [ $(date +%s) -gt $timeout ]; then echo "kv_loader timeout"; exit 1; fi sleep 1 echo "kv_loader still waiting"doneecho "kv_loader get/put from $INIT_CONSUL_KV_DIR"cd $INIT_CONSUL_KV_DIRfor json_file in $(ls *.json); do key=$(echo $json_file | sed -e 's/.json$//') echo "kv_loader loading $key from $json_file" consul kv get $key >/dev/null && echo "kv_loader $key already loaded" || consul kv put $key @$json_filedone