How to run Consul on docker with initial key-value pair data? How to run Consul on docker with initial key-value pair data? docker docker

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 the Dockerfile
  • Add json files to the init_kv/ directory, such as yourkey.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

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