如何 运行 Consul on docker 使用初始键值对数据?
How to run Consul on docker with initial key-value pair data?
我正在尝试在 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"
有没有办法预填充键值对?
撰写
Compose 没有 "tasks" 作为内置概念,但您可以在一个项目中使用多个 compose 文件来设置它们。 docker-compose-init.yml
可以定义任务,而不是长 运行ning 服务,但您需要自己管理编排。我放了一个 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
然后您的脚本启动服务器,设置数据,然后在最后像图像之前那样继续。
我无法获得为我工作的公认解决方案。我猜这是因为它在构建期间启动的存根领事在 运行 时间内以某种方式被覆盖。
使用已接受的答案作为起点,我添加了一个每次容器启动时都会启动的加载程序脚本。下面的 Dockerfile
向 Consul 入口点脚本添加了一个“垫片”(参见 RUN sed
)。
要使用这个:
- 在下方添加
Dockerfile
- 在
Dockerfile
旁边添加一个 init_kv/
目录
- 在
init_kv/
目录下添加json个文件,如yourkey.json
- 使用密钥作为 json 文件的名称
- 在这个例子中,键是
yourkey
- 运行
docker build
/docker run
/docker-compose up
, 等等
注意事项:
- 加载器脚本运行s 每次容器启动
- 加载程序脚本将拒绝加载已存在的密钥
- 例子中,如果
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 .*\)|\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
这是一个非常相似的方法,但可能更简单并且有效。不需要合成,只需要 Docker 就可以在图像中完成。
这个目录结构:
bootstrap/values.json
bootstrap/start.sh
bootstrap/init.sh
Dockerfile
Docker文件
FROM consul
RUN mkdir /tmp/bootstrap
COPY bootstrap/* /tmp/bootstrap/
RUN chmod 755 /tmp/bootstrap/*
RUN dos2unix /tmp/bootstrap/*
CMD /tmp/bootstrap/start.sh
bootstrap/start.sh
#!/bin/sh
/tmp/bootstrap/init.sh &
consul agent -dev -client=0.0.0.0
bootstrap/init.sh
#!/bin/sh
echo "bootstrap values - wait until port is available"
while ! nc -z localhost 8500; do
sleep 1
done
echo "executing consul kv command"
consul kv import @/tmp/bootstrap/values.json
bootstrap/values.json
[
{
"key": "config/",
"flags": 0,
"value": ""
},
{
"key": "config/yoursoftware/",
"flags": 0,
"value": ""
},
]
主要挑战是 运行 无法处理后台任务,而 CMD 是唯一必须 运行 最后的主要可执行文件。因此可以通过 CMD 启动后台进程,这里使用 shell 脚本 (start.sh)。在该脚本中,& 符号在 linux 下提供了一种启动进程并将其扔到后台的方法。它将执行 init.sh。因为它现在必须等到端口准备就绪,然后它才能使用导入。
我正在尝试在 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"
有没有办法预填充键值对?
撰写
Compose 没有 "tasks" 作为内置概念,但您可以在一个项目中使用多个 compose 文件来设置它们。 docker-compose-init.yml
可以定义任务,而不是长 运行ning 服务,但您需要自己管理编排。我放了一个 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
然后您的脚本启动服务器,设置数据,然后在最后像图像之前那样继续。
我无法获得为我工作的公认解决方案。我猜这是因为它在构建期间启动的存根领事在 运行 时间内以某种方式被覆盖。
使用已接受的答案作为起点,我添加了一个每次容器启动时都会启动的加载程序脚本。下面的 Dockerfile
向 Consul 入口点脚本添加了一个“垫片”(参见 RUN sed
)。
要使用这个:
- 在下方添加
Dockerfile
- 在
Dockerfile
旁边添加一个 - 在
init_kv/
目录下添加json个文件,如yourkey.json
- 使用密钥作为 json 文件的名称
- 在这个例子中,键是
yourkey
- 运行
docker build
/docker run
/docker-compose up
, 等等
init_kv/
目录
注意事项:
- 加载器脚本运行s 每次容器启动
- 加载程序脚本将拒绝加载已存在的密钥
- 例子中,如果
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 .*\)|\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
这是一个非常相似的方法,但可能更简单并且有效。不需要合成,只需要 Docker 就可以在图像中完成。
这个目录结构:
bootstrap/values.json
bootstrap/start.sh
bootstrap/init.sh
Dockerfile
Docker文件
FROM consul
RUN mkdir /tmp/bootstrap
COPY bootstrap/* /tmp/bootstrap/
RUN chmod 755 /tmp/bootstrap/*
RUN dos2unix /tmp/bootstrap/*
CMD /tmp/bootstrap/start.sh
bootstrap/start.sh
#!/bin/sh
/tmp/bootstrap/init.sh &
consul agent -dev -client=0.0.0.0
bootstrap/init.sh
#!/bin/sh
echo "bootstrap values - wait until port is available"
while ! nc -z localhost 8500; do
sleep 1
done
echo "executing consul kv command"
consul kv import @/tmp/bootstrap/values.json
bootstrap/values.json
[
{
"key": "config/",
"flags": 0,
"value": ""
},
{
"key": "config/yoursoftware/",
"flags": 0,
"value": ""
},
]
主要挑战是 运行 无法处理后台任务,而 CMD 是唯一必须 运行 最后的主要可执行文件。因此可以通过 CMD 启动后台进程,这里使用 shell 脚本 (start.sh)。在该脚本中,& 符号在 linux 下提供了一种启动进程并将其扔到后台的方法。它将执行 init.sh。因为它现在必须等到端口准备就绪,然后它才能使用导入。