【问题标题】:How to run Consul on docker with initial key-value pair data?如何使用初始键值对数据在 docker 上运行 Consul?
【发布时间】:2017-04-24 21:27:16
【问题描述】:

我正在尝试在 docker 容器上运行 Consul 服务器并将其用作我的 SpringBoot 云应用程序的配置服务器。为此,我想在 Consul 中有一些预先配置的数据(键值对)。

我在 docker-compose.yml 中的当前配置是:

  consul:
    image: "progrium/consul:latest"
    container_name: "consul"
    ports:
      - '9330:8300'
      - '9400:8400'
      - '9500:8500'
      - '9600:53'
    command: "-server -bootstrap -ui-dir /ui"

有没有办法预填充键值对?

【问题讨论】:

标签: docker docker-compose consul


【解决方案1】:

撰写

Compose 没有内置概念中的“任务”,但您可以在一个项目中使用多个撰写文件来设置它们。 docker-compose-init.yml 可以定义任务,而不是长时间运行的服务,但您需要自己管理编排。我已经输入了example on my consul demo

docker-compose up -d
docker-compose -f docker-compose-init.yml run consul_init

图像构建

您可以添加镜像构建RUN 步骤来添加数据。这里的复杂之处在于以与通常相同的方式运行服务器,但在后台运行,并在一个 RUN 步骤中添加所有数据。

FROM progrium/consul:latest
RUN 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;

图像启动

某些数据库会在图像中添加脚本以在启动时填充数据。这通常是为了让用户可以通过在运行时注入的环境变量来控制设置,例如mysql/postgres/mongo

FROM progrium/consul:latest
ENTRYPOINT my-entrypoint.sh

然后您的脚本启动服务器,设置数据,然后在最后继续像之前的图像一样。

【讨论】:

    【解决方案2】:

    我无法获得适用于我的公认解决方案。我猜这是因为它在构建时启动的存根 consul 在运行时以某种方式被覆盖。

    使用接受的答案作为起点,我添加了一个加载程序脚本,该脚本在每次容器启动时启动。下面的 Dockerfile 向 Consul 入口点脚本添加了一个“shim”(参见 RUN sed)。

    要使用这个:

    • 在下方添加Dockerfile
    • Dockerfile 旁边添加一个init_kv/ 目录
    • init_kv/目录下添加json文件,如yourkey.json
      • 使用key作为json文件名
      • 在本例中,密钥为yourkey
    • 运行docker build/docker run/docker-compose up

    注意:

    • 加载器脚本运行每次容器启动
    • 如果密钥已经存在,加载器脚本将拒绝加载它
      • 在示例中,如果yourkey已经存在,则不会重新加载

    Dockerfile

    # pull official base image
    FROM 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.d
    RUN mkdir -p $INIT_CONSUL_KV_DIR
    COPY kv_loader.sh /usr/local/bin/
    RUN sed -ie 's|^\(set .*\)|\1\n/usr/local/bin/kv_loader.sh \&|' /usr/local/bin/docker-entrypoint.sh
    COPY 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 directory
    set -ue
    
    let "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"
    done
    
    echo "kv_loader get/put from $INIT_CONSUL_KV_DIR"
    cd $INIT_CONSUL_KV_DIR
    for 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_file
    done
    

    【讨论】:

    • 您可以通过将-cas-modify-index=0 一起使用来删除put 之前的kv get 操作。 consul kv put -cas -modify-index=0 new_key new_value 用于现有密钥会导致 Consul 返回“错误!未写入 new_key:CAS 执行时使用 index=0 且密钥已存在。”
    • @BlakeCovarrubias 感谢您的补充!我尝试了这种方法,但是我找不到一个好的机制来在sh 中使用它来肯定地确认密钥存在。使用consul kv put -cas -modify-index=0 $key @$json_file || echo "failure code: $?",错误代码是一个通用的1,所以它可能是由于任何领事错误。这也会输出一个看起来很吓人的“错误!没有写”消息,即使“失败”实际上是需要的。如果有更简洁的方法可以肯定地确认密钥存在,我肯定也会试一试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-10-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-29
    相关资源
    最近更新 更多