如何在远程Docker容器中rsync时抑制stdout输出
问题描述
我在远程Docker服务器上托管了个人服务,数据存储在Docker卷中,通过家里的NAS使用rsync做备份,命令如下:
rsync --recursive --archive --stats \ --rsync-path="docker run -v my_vol:/my/path rsync-image rsync --quiet --log-file=/dev/null" \ -e ssh user@host:/my/path /local/directory
备份功能正常,但rsync会向容器stdout输出大量内容,这些日志被转发到我的Datadog账号,导致存储量超标。我不想直接禁用容器日志采集(担心错过潜在错误),因此希望让rsync减少冗余输出。
rsync镜像的Dockerfile很基础:
FROM alpine:latest # Install Rsync and SSH. RUN apk update \ && apk upgrade \ && apk add --no-cache \ rsync \ openssh-client-default \ sshpass \ ca-certificates tzdata \ && update-ca-certificates \ && rm -rf /var/cache/apk/* # The UID:GID for www-data in Debian/Ubuntu doesn't match with the IDs in Alpine: # # | user : group | Debian/Ubuntu (uid:gid) | Alpine (uid:gid) | # | www-data : www-data | 33 : 33 | 82 : 82 | # | xfs : xfs | - | 33 : 33 | RUN addgroup nobody xfs # Run unprivileged USER nobody
我已经在--rsync-path和主rsync命令里加了--quiet参数,但完全没用,请问我忽略了什么?
解决方案
问题根源
你当前的冗余日志不全是rsync产生的——docker run命令本身会输出容器启动相关的日志(比如镜像拉取提示、容器初始化信息),这些日志和rsync的输出混在一起,而rsync的--quiet只能控制自身输出,无法抑制容器启动日志。
具体解决方法
抑制
docker run的输出
在docker run命令中添加--quiet(或-q)参数,抑制容器启动时的非必要日志;如果想彻底丢弃容器内rsync的冗余输出,可以把stdout重定向到/dev/null,同时保留stderr用于错误排查:rsync --recursive --archive --stats \ --rsync-path="docker run -v my_vol:/my/path --quiet rsync-image rsync --quiet --no-motd --log-file=/dev/null >/dev/null" \ -e ssh user@host:/my/path /local/directory其中
--no-motd可以避免rsync输出欢迎信息,进一步减少冗余。用
docker exec替代docker run(更高效)
每次备份都启动新容器会产生额外开销和启动日志,不如提前在服务器上运行一个长期挂卷的辅助容器:docker run -d -v my_vol:/my/path --name rsync-helper rsync-image sleep infinity之后修改rsync命令,通过
docker exec执行容器内的rsync:rsync --recursive --archive --stats \ --rsync-path="docker exec rsync-helper rsync --quiet --no-motd --log-file=/dev/null" \ -e ssh user@host:/my/path /local/directory这种方式完全避免了
docker run的启动日志,同时docker exec本身输出极少,只有rsync的必要日志。验证日志输出
可以单独在服务器上测试容器内的rsync命令,确认输出是否符合预期:docker run -v my_vol:/my/path rsync-image rsync --quiet --no-motd --log-file=/dev/null /my/path /tmp/test执行后如果没有输出,说明参数生效,再整合到rsync备份命令中即可。
内容的提问来源于stack exchange,提问作者themouette

