Docker Redis - 播种数据 - 无法通过 Docker 文件或 shell 脚本执行 redis-cli
Docker Redis - Seeding Data - Cannot execute redis-cli via Dockerfile or via shell script
通过 docker-compose
(使用我的 Redis Dockerfile
)设置了一个 Redis
实例,一切正常。
现在,我正在尝试在容器启动后为 Redis
实例播种数据。
(1) 试图 运行 redis-cli
直接在 Dockerfile
中(即 运行 by docker-compose
)
FROM redis:6.2.5
COPY ./redis.conf /test_dir/
COPY ./seed.txt /test_dir/
ENTRYPOINT ["redis-server", "/test_dir/redis.conf"]
RUN cat /test_dir/seed.txt | redis-cli -a <password> --pipe
这会抛出 Could not connect to Redis at 127.0.0.1:6379: Connection refused
(2) 略有不同 Dockerfile
,运行 在容器启动后执行的 shell
脚本中使用相同的命令:
FROM redis:6.2.5
COPY ./redis.conf /test_dir/
COPY ./seed.txt /test_dir/
COPY ./init.sh /test_dir/
ENTRYPOINT ["redis-server", "/test_dir/redis.conf"]
RUN . /test_dir/init.sh
# init.sh
sleep 10 # ensure Redis server is up and running
cat /test_dir/seed.txt | redis-cli -a <password> --pipe
执行 shell
脚本,它等待 10 秒,我确认服务器已启动并且 运行ning 在数据导入被触发之前,但 Redis
抛出相同的错误.
备注:
(1) I've also disabled `protected-mode` and removed `requirepass`, but redis-cli can not connect
(2) when I jump into the container and manually execute the command, it DOES WORK !
那么我如何从 Dockerfile
或通过 shell
脚本 运行 redis-cli
或者播种 Docker Redis 实例的推荐方法是什么?
谢谢。
RUN cat /test_dir/seed.txt | redis-cli -a <password> --pipe
将在您执行 docker build
时执行,那时 ENTRYPOINT ["redis-server", "/test_dir/redis.conf"]
仍然不会 运行 因为它仅在容器启动时被调用。所以,你肯定会出错。
因此,您可以使用下一个解决方法:
/test_dir/seed.txt:
/test_dir/init.sh:
while :
do
redis-cli -h redis-svr -p 6379 quit
if [ $? -eq 0 ]; then
cat /test_dir/seed.txt | redis-cli -h redis-svr -p 6379 --pipe
break
else
echo "server not ready, wait then retry..."
sleep 3
fi
done
docker-compose.yaml:
version: '3'
services:
redis-svr:
image: redis
redis-cli:
image: redis
volumes:
- /test_dir:/test_dir
entrypoint: sh -c /test_dir/init.sh
执行:
$ docker-compose up
WARNING: Found orphan containers (20210910_redis_1) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
Starting 20210910_redis-svr_1 ... done
Starting 20210910_redis-cli_1 ... done
Attaching to 20210910_redis-cli_1, 20210910_redis-svr_1
redis-cli_1 | Could not connect to Redis at redis-svr:6379: Connection refused
redis-cli_1 | server not ready, wait then retry...
redis-svr_1 | 1:C 11 Sep 2021 05:55:33.872 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-svr_1 | 1:C 11 Sep 2021 05:55:33.872 # Redis version=6.2.5, bits=64, commit=00000000, modified=0, pid=1, just started
redis-svr_1 | 1:C 11 Sep 2021 05:55:33.872 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.873 * monotonic clock: POSIX clock_gettime
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.879 * Running mode=standalone, port=6379.
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.879 # Server initialized
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.890 * Loading RDB produced by version 6.2.5
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.890 * RDB age 266 seconds
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.890 * RDB memory usage when created 0.77 Mb
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.890 * DB loaded from disk: 0.010 seconds
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.890 * Ready to accept connections
redis-cli_1 | OK
redis-cli_1 | All data transferred. Waiting for the last reply...
redis-cli_1 | Last reply received from server.
redis-cli_1 | errors: 0, replies: 0
20210910_redis-cli_1 exited with code 0
说明:
redis-svr
将在一个容器中启动服务器,redis-cli
将启动另一个容器,它将首先调用 init.sh
,init.sh
将尝试 [= redis-cli -h redis-svr -p 6379 quit
92=] 到redis服务器看服务器是否真的启动了。如果没有,它会等待一段时间并重试,如果服务器已经启动,那么它可以调用客户端命令将初始数据导入服务器。
EDIT20210912 根据 OP 的评论使用一个容器:
文件夹结构:
$ tree
.
├── docker-compose.yaml
├── Dockerfile
├── init.sh
├── my-entrypoint.sh
└── seed.txt
docker-compose.yaml:
version: '3'
services:
redis-svr:
build: ./
Dockerfile:
FROM redis:6.2.5
COPY . /tmp
RUN chmod -R 777 /tmp
ENTRYPOINT ["/tmp/my-entrypoint.sh"]
CMD ["redis-server"]
init.sh:
while :
do
redis-cli quit
if [ $? -eq 0 ]; then
echo "Server ready now, start to import data ..."
cat ./seed.txt | redis-cli --pipe
break
else
echo "Server not ready, wait then retry..."
sleep 3
fi
done
我的-entrypoint.sh:
#!/bin/sh
/tmp/init.sh &
docker-entrypoint.sh
执行:
$ docker-compose up
Recreating test_dir_redis-svr_1 ... done
Attaching to test_dir_redis-svr_1
redis-svr_1 | Could not connect to Redis at 127.0.0.1:6379: Connection refused
redis-svr_1 | Server not ready, wait then retry...
redis-svr_1 | 7:C 12 Sep 2021 08:36:05.512 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-svr_1 | 7:C 12 Sep 2021 08:36:05.512 # Redis version=6.2.5, bits=64, commit=00000000, modified=0, pid=7, just started
redis-svr_1 | 7:C 12 Sep 2021 08:36:05.512 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis-svr_1 | 7:M 12 Sep 2021 08:36:05.513 * monotonic clock: POSIX clock_gettime
redis-svr_1 | 7:M 12 Sep 2021 08:36:05.515 * Running mode=standalone, port=6379.
redis-svr_1 | 7:M 12 Sep 2021 08:36:05.515 # Server initialized
redis-svr_1 | 7:M 12 Sep 2021 08:36:05.515 * Ready to accept connections
redis-svr_1 | OK
redis-svr_1 | Server ready now, start to import data ...
redis-svr_1 | All data transferred. Waiting for the last reply...
redis-svr_1 | Last reply received from server.
redis-svr_1 | errors: 0, replies: 0
这定义自定义入口点让 init.sh
有机会在 redis 服务器 运行.
之前执行
这是另一个有效的解决方案,尽管@atline 解决方案更优雅。
Docker 文件
FROM redis:6.2.5-alpine3.14
RUN mkdir /foo
COPY ./redis.conf /foo/
COPY ./seed.txt /foo/
COPY ./init.sh /foo/
ENTRYPOINT /bin/sh -c "redis-server /foo/redis.conf" & sleep 2s \
&& source /foo/init.sh
init.sh
# seed db
cat /foo/seed.txt | redis-cli -a <pw_if_applicable> --pipe
# save .rdb dump
redis-cli -a <pw_if_applicable> save
# shutdown server
redis-cli -a <pw_if_applicable> shutdown
# restart server
redis-server "/foo/redis.conf"
这有效并使用提供的 redis.conf
,因此它将数据播种到您在配置中定义的 .rdb
。
通过 docker-compose
(使用我的 Redis Dockerfile
)设置了一个 Redis
实例,一切正常。
现在,我正在尝试在容器启动后为 Redis
实例播种数据。
(1) 试图 运行 redis-cli
直接在 Dockerfile
中(即 运行 by docker-compose
)
FROM redis:6.2.5
COPY ./redis.conf /test_dir/
COPY ./seed.txt /test_dir/
ENTRYPOINT ["redis-server", "/test_dir/redis.conf"]
RUN cat /test_dir/seed.txt | redis-cli -a <password> --pipe
这会抛出 Could not connect to Redis at 127.0.0.1:6379: Connection refused
(2) 略有不同 Dockerfile
,运行 在容器启动后执行的 shell
脚本中使用相同的命令:
FROM redis:6.2.5
COPY ./redis.conf /test_dir/
COPY ./seed.txt /test_dir/
COPY ./init.sh /test_dir/
ENTRYPOINT ["redis-server", "/test_dir/redis.conf"]
RUN . /test_dir/init.sh
# init.sh
sleep 10 # ensure Redis server is up and running
cat /test_dir/seed.txt | redis-cli -a <password> --pipe
执行 shell
脚本,它等待 10 秒,我确认服务器已启动并且 运行ning 在数据导入被触发之前,但 Redis
抛出相同的错误.
备注:
(1) I've also disabled `protected-mode` and removed `requirepass`, but redis-cli can not connect
(2) when I jump into the container and manually execute the command, it DOES WORK !
那么我如何从 Dockerfile
或通过 shell
脚本 运行 redis-cli
或者播种 Docker Redis 实例的推荐方法是什么?
谢谢。
RUN cat /test_dir/seed.txt | redis-cli -a <password> --pipe
将在您执行 docker build
时执行,那时 ENTRYPOINT ["redis-server", "/test_dir/redis.conf"]
仍然不会 运行 因为它仅在容器启动时被调用。所以,你肯定会出错。
因此,您可以使用下一个解决方法:
/test_dir/seed.txt:
/test_dir/init.sh:
while :
do
redis-cli -h redis-svr -p 6379 quit
if [ $? -eq 0 ]; then
cat /test_dir/seed.txt | redis-cli -h redis-svr -p 6379 --pipe
break
else
echo "server not ready, wait then retry..."
sleep 3
fi
done
docker-compose.yaml:
version: '3'
services:
redis-svr:
image: redis
redis-cli:
image: redis
volumes:
- /test_dir:/test_dir
entrypoint: sh -c /test_dir/init.sh
执行:
$ docker-compose up
WARNING: Found orphan containers (20210910_redis_1) for this project. If you removed or renamed this service in your compose file, you can run this command with the --remove-orphans flag to clean it up.
Starting 20210910_redis-svr_1 ... done
Starting 20210910_redis-cli_1 ... done
Attaching to 20210910_redis-cli_1, 20210910_redis-svr_1
redis-cli_1 | Could not connect to Redis at redis-svr:6379: Connection refused
redis-cli_1 | server not ready, wait then retry...
redis-svr_1 | 1:C 11 Sep 2021 05:55:33.872 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-svr_1 | 1:C 11 Sep 2021 05:55:33.872 # Redis version=6.2.5, bits=64, commit=00000000, modified=0, pid=1, just started
redis-svr_1 | 1:C 11 Sep 2021 05:55:33.872 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.873 * monotonic clock: POSIX clock_gettime
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.879 * Running mode=standalone, port=6379.
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.879 # Server initialized
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.890 * Loading RDB produced by version 6.2.5
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.890 * RDB age 266 seconds
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.890 * RDB memory usage when created 0.77 Mb
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.890 * DB loaded from disk: 0.010 seconds
redis-svr_1 | 1:M 11 Sep 2021 05:55:33.890 * Ready to accept connections
redis-cli_1 | OK
redis-cli_1 | All data transferred. Waiting for the last reply...
redis-cli_1 | Last reply received from server.
redis-cli_1 | errors: 0, replies: 0
20210910_redis-cli_1 exited with code 0
说明:
redis-svr
将在一个容器中启动服务器,redis-cli
将启动另一个容器,它将首先调用 init.sh
,init.sh
将尝试 [= redis-cli -h redis-svr -p 6379 quit
92=] 到redis服务器看服务器是否真的启动了。如果没有,它会等待一段时间并重试,如果服务器已经启动,那么它可以调用客户端命令将初始数据导入服务器。
EDIT20210912 根据 OP 的评论使用一个容器:
文件夹结构:
$ tree
.
├── docker-compose.yaml
├── Dockerfile
├── init.sh
├── my-entrypoint.sh
└── seed.txt
docker-compose.yaml:
version: '3'
services:
redis-svr:
build: ./
Dockerfile:
FROM redis:6.2.5
COPY . /tmp
RUN chmod -R 777 /tmp
ENTRYPOINT ["/tmp/my-entrypoint.sh"]
CMD ["redis-server"]
init.sh:
while :
do
redis-cli quit
if [ $? -eq 0 ]; then
echo "Server ready now, start to import data ..."
cat ./seed.txt | redis-cli --pipe
break
else
echo "Server not ready, wait then retry..."
sleep 3
fi
done
我的-entrypoint.sh:
#!/bin/sh
/tmp/init.sh &
docker-entrypoint.sh
执行:
$ docker-compose up
Recreating test_dir_redis-svr_1 ... done
Attaching to test_dir_redis-svr_1
redis-svr_1 | Could not connect to Redis at 127.0.0.1:6379: Connection refused
redis-svr_1 | Server not ready, wait then retry...
redis-svr_1 | 7:C 12 Sep 2021 08:36:05.512 # oO0OoO0OoO0Oo Redis is starting oO0OoO0OoO0Oo
redis-svr_1 | 7:C 12 Sep 2021 08:36:05.512 # Redis version=6.2.5, bits=64, commit=00000000, modified=0, pid=7, just started
redis-svr_1 | 7:C 12 Sep 2021 08:36:05.512 # Warning: no config file specified, using the default config. In order to specify a config file use redis-server /path/to/redis.conf
redis-svr_1 | 7:M 12 Sep 2021 08:36:05.513 * monotonic clock: POSIX clock_gettime
redis-svr_1 | 7:M 12 Sep 2021 08:36:05.515 * Running mode=standalone, port=6379.
redis-svr_1 | 7:M 12 Sep 2021 08:36:05.515 # Server initialized
redis-svr_1 | 7:M 12 Sep 2021 08:36:05.515 * Ready to accept connections
redis-svr_1 | OK
redis-svr_1 | Server ready now, start to import data ...
redis-svr_1 | All data transferred. Waiting for the last reply...
redis-svr_1 | Last reply received from server.
redis-svr_1 | errors: 0, replies: 0
这定义自定义入口点让 init.sh
有机会在 redis 服务器 运行.
这是另一个有效的解决方案,尽管@atline 解决方案更优雅。
Docker 文件
FROM redis:6.2.5-alpine3.14
RUN mkdir /foo
COPY ./redis.conf /foo/
COPY ./seed.txt /foo/
COPY ./init.sh /foo/
ENTRYPOINT /bin/sh -c "redis-server /foo/redis.conf" & sleep 2s \
&& source /foo/init.sh
init.sh
# seed db
cat /foo/seed.txt | redis-cli -a <pw_if_applicable> --pipe
# save .rdb dump
redis-cli -a <pw_if_applicable> save
# shutdown server
redis-cli -a <pw_if_applicable> shutdown
# restart server
redis-server "/foo/redis.conf"
这有效并使用提供的 redis.conf
,因此它将数据播种到您在配置中定义的 .rdb
。