1

My development environment consists of a local consul server in one container, and my application (with consul-template running) in another, all linked with docker-compose. I want for everything to spin up seamlessly and without manual intervention in development (security is not an issue), and so I'd like to programatically add default key/value pairs to consul at startup by mounting a particular file.

I keep running into this issue where whenever I try to add k/v pairs to consul at startup using the API, it fails with an error 2016/06/03 21:10:15 [ERR] http: Request PUT /v1/kv/app/secret_key, error: No cluster leader from=[::1]:58888. If I add a sleep command before hand, giving consul enough time to elect a leader, it works. But, there must be a better way to do this synchronously, right? Especially when there's only ever one node in the cluster anyways.

This is what I have so far.

Dockerfile

FROM voxxit/consul

ARG REFRESHED_AT="2016-06-01"
ARG DOCKERIZE_VERSION="v0.2.0"
ENV CONSUL_ADDR="http://localhost:8500"

ADD "https://github.com/jwilder/dockerize/releases/download/${DOCKERIZE_VERSION}/dockerize-linux-amd64-${DOCKERIZE_VERSION}.tar.gz" /tmp
RUN set -x && \
    apk add --update curl jq && \
    cd /tmp && \
    tar -C /usr/local/bin -xzvf dockerize-linux-amd64-${DOCKERIZE_VERSION}.tar.gz && \
    rm -rf /var/cache/apk/* /tmp/*

RUN mkdir -p /etc/consul.d/data
COPY ./consul.json /etc/consul.d/
COPY ./entrypoint.sh /
RUN chmod +x /entrypoint.sh

WORKDIR /etc/consul.d/data
VOLUME ["/etc/consul.d/data"]

ENTRYPOINT ["/entrypoint.sh"]
CMD ["dockerize", "-stdout", "/var/log/consul.out", "-stderr", "/var/log/consul.err"]

entrypoint.sh

#!/bin/bash -e

# Start consul server and wait for it
nohup consul agent -config-file=/etc/consul.d \
    >/var/log/consul.out 2>/var/log/consul.err &
dockerize -wait "${CONSUL_ADDR}" # <-- Not working as I'd hoped

DEFAULT_CONFIG="/etc/consul.d/data/default.json"

if [ -f $DEFAULT_CONFIG ]; then
    # Bulk upload default k/v pairs
    while IFS=" " read -r key value; do
        prefix="${APP_NAME}"
        result=$(curl -s -X PUT -d "$value" "${CONSUL_ADDR}/v1/kv/${prefix}/${key}")
        if [ "$result" != "true" ]; then
            echo "ERROR loading $value into $key for $prefix"
            exit 1
        fi
    done < <(jq -r 'to_entries|map("\(.key) \(.value|tostring)")|.[]' $DEFAULT_CONFIG)
fi

echo "init complete - ready for start up"
exec "$@"

consul.json

{
"bootstrap": true,
"client_addr": "0.0.0.0",
"data_dir": "/data",
"enable_syslog": false,
"log_level": "INFO",
"server": true,
"ui_dir": "/ui",
"http_api_response_headers": {
    "Access-Control-Allow-Origin": "*"
}
}

There has to be some way I can pause the bulk upload until after I know for sure consul is up and running.

BDuelz
  • 3,890
  • 7
  • 39
  • 62
  • Can you share ur consul docker-compose? are you not setting -bootstrap-expect=1? – Shibashis Jun 05 '16 at 19:24
  • I didn't try that. I was under the impression that `bootstrap-expect` was for clusters > 1. – BDuelz Jun 05 '16 at 19:51
  • @Shibashis I just tried adding `"bootstrap_expect": 1` to the above config and I got this error `==> Bootstrap cannot be provided with an expected server count` – BDuelz Jun 05 '16 at 20:01
  • yes. Do you have docker consul server elsewhere? or is this local setup where you want to run one instance of consul? – Shibashis Jun 05 '16 at 20:02
  • The latter. This is a development setup I'm working on. – BDuelz Jun 05 '16 at 20:02
  • where are you setting expected server count? the yml does not have it – Shibashis Jun 05 '16 at 20:03
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/113865/discussion-between-bduelz-and-shibashis). – BDuelz Jun 05 '16 at 20:06

1 Answers1

0

I got a similar problem and I solved my problem (Bootstrap cannot be provided with an expected server count) by specifying the number of expected Consul nodes (using command line argument -bootstrap-expect=5) instead of simply -boostrap on a single node.

Nicolas Henneaux
  • 11,507
  • 11
  • 57
  • 82