执行docker exec导出MySQL数据时报‘failed to start io pipe copy’错误求助
解决Docker Exec导出MySQL数据时的containerd-shim stdout错误
这个问题大概率是Docker exec命令与管道的交互方式在containerd作为runtime时出现了兼容性冲突,再加上你脚本里多余的管道转义写法,进一步触发了报错。结合你的Ubuntu 18.04 + Docker 19.03.6环境,这里有几个实用的解决办法:
方法1:修正管道写法,让宿主机处理压缩
你脚本里的\ |是多余的转义符号,这会导致管道被当作参数传递给容器内的mysqldump命令,而非在宿主机端处理输出流。去掉反斜杠,让容器只负责输出原始备份数据,宿主机完成压缩操作:
dbPassword="password" sourceDb="production" localFile="$sourceDb.sql.gz" dbContainer=$(docker-compose ps -q db) docker exec "$dbContainer" /usr/bin/mysqldump -u root --password="$dbPassword" "$sourceDb" | gzip > db/"$localFile"
这个改动能避免容器内管道处理与containerd-shim的stdout管理冲突,是最直接的修复方式。
方法2:在容器内完成压缩,再拷贝文件
如果方法1仍报错,可以把压缩逻辑放到容器内部,通过docker cp将压缩好的文件拷贝到宿主机,彻底绕开跨容器的管道流问题:
dbPassword="password" sourceDb="production" localFile="$sourceDb.sql.gz" dbContainer=$(docker-compose ps -q db) # 容器内执行mysqldump并压缩到临时文件 docker exec "$dbContainer" /bin/bash -c "/usr/bin/mysqldump -u root --password='$dbPassword' '$sourceDb' | gzip > /tmp/$localFile" # 拷贝压缩文件到宿主机指定目录 docker cp "$dbContainer:/tmp/$localFile" db/"$localFile" # 清理容器内的临时文件 docker exec "$dbContainer" rm /tmp/"$localFile"
这种方式完全避免了stdout管道的跨进程传递,能有效解决containerd-shim无法打开stdout文件的报错。
方法3:调整Docker Runtime配置(可选)
如果前两种方法都无效,可以检查Docker是否使用了containerd作为默认runtime:
- 运行
docker info | grep Runtime查看当前runtime类型 - 如果是
containerd,可以尝试临时切换回runc:
编辑/etc/docker/daemon.json,添加或修改配置:{ "default-runtime": "runc" } - 重启Docker服务:
sudo systemctl restart docker
不过这个方法属于调整底层运行时,建议优先尝试前两种更轻量的解决方案。
内容的提问来源于stack exchange,提问作者slhck
相关产品推荐
相关产品推荐

