如何不使用卷将RDB文件加载到Docker Redis容器并解决删除权限问题
问题解决:无需挂载卷加载Redis RDB文件并避免删除权限问题
问题原因
当你用--volume直接挂载单个RDB文件到Docker容器时,Redis容器内的redis用户会对该文件进行读写操作,可能修改了文件权限或添加了不可删除属性,导致宿主系统的ec2-user无法删除该文件。
解决方案
放弃直接挂载文件的方式,改用docker cp命令将本地下载的RDB文件复制到Redis容器内部的/data目录(Redis默认加载dump.rdb的路径),再启动容器。这样宿主系统的RDB文件不会被容器挂载,权限保持初始状态,后续删除时不会遇到权限问题。
修改后的完整脚本
#!/usr/bin/env bash set -e set -E set -o pipefail set -u set -x IFS=$'\n\t' log="/tmp/restore-elasticache-to-docker.log" exec 2>"$log" handle_error() { log_message="$(< "$log")" local from; local to; local subject; local text; from="cron@ch.com" to="ch@gmail.com" subject="Elasticache restore encountered an error at $(date)" text="Elasticache restore encountered an error at line:$(caller) while running:${BASH_COMMAND} due to the error:${log_message}" aws ses send-email --from "${from}" --subject "${subject}" --text "${text}" --to "${to}" echo "subject: ${subject}" echo "text: ${text}" exit 1 } handle_exit() { if [ $? -eq 0 ]; then log_message="$(< "$log")" local from; local to; local subject; local text; from="cron@ch.com" to="ch@gmail.com" subject="Elasticache restore completed successfully at $(date)" text="Elasticache restore completed successfully ${log_message} ${result}" aws ses send-email --from "${from}" --subject "${subject}" --text "${text}" --to "${to}" echo "subject: ${subject}" echo "text: ${text}" fi # 停止并删除容器,兼容容器不存在的情况 docker stop "${container_name}" >/dev/null 2>&1 || true docker rm "${container_name}" >/dev/null 2>&1 || true # 删除本地RDB文件和日志,此时文件权限未被容器修改,可正常删除 rm -f "${dump_file_directory}/${dump_file_name}" rm -f /tmp/restore-elasticache-to-docker.log } trap 'handle_exit $?' EXIT trap 'handle_error $?' ERR bucket='something-something' container_name="my_redis_container" dump_file_directory="/tmp" host="localhost" port="6379" result="" # 下载最新的RDB文件到本地 dump_file_name=$(aws s3 ls $bucket --recursive | sort | tail -n 1 | awk '{print $4}') aws s3 cp "s3://${bucket}/${dump_file_name}" "${dump_file_directory}/${dump_file_name}" # 清理旧容器(如果存在) docker ps -aq --filter "name=${container_name}" | grep -q . && docker stop "${container_name}" && docker rm -fv "${container_name}" # 关键修改:创建容器但不启动,复制RDB文件到容器内部,再启动 docker create --name "${container_name}" --publish "${port}:${port}" redis docker cp "${dump_file_directory}/${dump_file_name}" "${container_name}:/data/dump.rdb" docker start "${container_name}" # 等待Redis启动完成 until docker exec "${container_name}" redis-cli -h "${host}" -p "${port}" ping; do sleep 1 done # 获取所有密钥列表 result=$(docker exec "${container_name}" redis-cli -h "${host}" -p "${port}" keys '*')
修改说明
- 替换容器启动方式:将原来的
docker run挂载卷命令,拆分为docker create(创建容器)、docker cp(复制文件到容器)、docker start(启动容器)三步,彻底避免挂载文件导致的权限问题。 - 优化清理逻辑:在容器停止/删除命令后添加
>/dev/null 2>&1 || true,避免容器不存在时命令报错中断流程。 - 保留原有核心流程:S3文件下载、错误处理、邮件通知、密钥获取等逻辑均保持不变,仅调整RDB文件加载到容器的方式。
内容的提问来源于stack exchange,提问作者PirateApp
相关产品推荐
相关产品推荐

