NetWorker:Docker 容器 NetWorker 客户端备份失败,并显示错误“savefs: fail”

Summary: NetWorker:Docker 容器 NetWorker 客户端备份失败,并显示错误“savefs: fail”

This article applies to This article does not apply to This article is not tied to any specific product. Not all product versions are identified in this article.

Symptoms

NetWorker 客户端软件安装在 docker 容器内。
docker 客户端的基于客户端的备份失败,并显示以下错误:

<client name>:savefs failed.
<client name>:savefs See the file '/nsr/logs/policy/<policy>/<workflow/backup_<jobid>_logs/<jobid>.log' for command output.
Stopped processing of the save set <cleint name>:<save set> because the savefs job job terminated with an error.
Job <jobid> host: <client name> savepoint: <save set> had ERROR indication(s) at completion
<client name>:<save set> abandoned.
Client '<client name>' is being skipped because no savesets of this client have been backed up as part of the backup action.
Action backup traditional 'backup' with job id <job id> is exiting with status 'failed', exit code 1

Cause

在当前版本中,不正式支持在 Docker 容器内运行的 NetWorker 客户端。Docker 使用覆盖文件系统,不依赖于传统的磁盘布局,因此不存在 /etc/fstab 等路径。

Resolution

目前没有支持的方法将 docker 容器备份为 NetWorker 客户端。如果您希望 NetWorker 中存在此功能,请联系您的戴尔客户或销售代表咨询增强请求 (RFE)。

 

要防止 NetWorker 客户端备份 Docker 数据,您必须在 NetWorker 客户端上对 Docker 文件/文件夹结构使用 skip 指令。

示例(根据您的系统和 Docker 配置修改路径和进程):

<< /var/lib/docker >>
skip: *
<< /var/lib/containers >>
skip: *
<< /run >>
skip: docker docker.sock containers podman crun

有关 NetWorker 指令的更多信息,请参阅 NetWorker Administration Guide。NetWorker 文档可通过以下方式获得:适用于NetWorker的支持 |手册和文档 

 

要备份 docker 容器数据,请使用以下解决方法之一:

解决方法一: 

  1. 通过 SSH 访问 docker 主机。
  2. 通过 SSH 会话,连接到 docker 容器。使用的确切语法取决于容器平台:
  • Docker: docker exec -it CONTAINER_NAME sh
  • Podman: podman exec -it CONTAINER_NAME sh
  1. 创建 fstab 文件,使用 mtab 文件中标识的: cp /etc/mtab /etc/fstab
  2. 退出容器: exit
  3. 从 NetWorker 备份容器客户端。

解决方法二:

在 docker 主机上创建 docker 容器数据的“归档”,从 docker 主机将数据备份为文件系统存储集。此方法可能需要一些脚本编制和使用 cron 工作。

警告:NetWorker 支持不提供脚本编制支持或与作系统脚本相关的问题支持。以下示例仅用于概念验证。该脚本提供常规优化功能,可能满足您的需求,但仅在您完全了解其行为时才使用它。您必须与 docker 主机的系统管理员协调,以查看他们是否接受此方法。与系统和 Docker 管理员合作,使用此处概述的一般过程概述来制定适合您需求的脚本。NetWorker 支持只能帮助解决由 NetWorker 备份的“归档”tarball 的一般 NetWorker 备份/恢复问题。
  1. 创建执行以下作的 bash 脚本:
    1. 暂时停止 docker 容器。这是为了确保 docker 容器中的数据库一致性。
    2. 压缩 docker 容器的文件夹内容。
    3. 启动 docker 容器
    4. (可选)清理早于 X 天的归档。
#!/usr/bin/env bash
set -euo pipefail
# ===== Config (tunable) =====
CONTAINER_TOOL="podman"                  # container platform (podman or docker)
CONTAINER_NAME="npm"                     # the container name to verify after restart
COMPOSE_DIR="/root/docker/nginx"         # directory containing docker-compose.yaml/podman-compose.yaml
BACKUP_ROOT="/root/docker/backups"       # where backups are stored on the host
RETENTION_DAYS=3                         # delete archives older than N days
TIMESTAMP="$(date +%F_%H%M%S)"
ARCHIVE="${BACKUP_ROOT}/${CONTAINER_NAME}-backup-${TIMESTAMP}.tar.gz"
LOCK_FILE="/var/lock/${CONTAINER_NAME}_backup.lock"
# ========================================
mkdir -p "$BACKUP_ROOT" /var/lock
# --- Handle stale lock files (if previous run crashed) ---
if [[ -f "$LOCK_FILE" ]]; then
  # Try to find an owning process; if none, remove the stale lock
  LOCK_FD_OWNER="$(lsof -t -- "$LOCK_FILE" 2>/dev/null || true)"
  if [[ -z "$LOCK_FD_OWNER" || ! -d "/proc/$LOCK_FD_OWNER" ]]; then
    echo "[INFO] Removing stale lock file: $LOCK_FILE"
    rm -f "$LOCK_FILE"
  fi
fi
# --- Simple lock to avoid overlapping runs ---
exec 9>"$LOCK_FILE"
if ! flock -n 9; then
  echo "[INFO] Another backup is running. Exiting."
  exit 0
fi
# --- Safety checks ---
if [[ ! -d "$COMPOSE_DIR" ]]; then
  echo "[ERROR] Compose directory not found: $COMPOSE_DIR" >&2
  exit 1
fi
if [[ ! -f "${COMPOSE_DIR}/docker-compose.yaml" && ! -f "${COMPOSE_DIR}/podman-compose.yaml" ]]; then
  echo "[ERROR] No compose file found in ${COMPOSE_DIR}" >&2
  exit 1
fi
# --- Functions ---
prune_backups() {
  local root="$1" days="$2"
  echo "[INFO] Pruning backups older than ${days} days in ${root}..."
  find "$root" -maxdepth 1 -type f -name "${CONTAINER_NAME}-backup-*.tar.gz" -mtime +"$days" -print -delete || true
}
verify_running() {
  # Expect container named "${CONTAINER_NAME}" to be running again
  if ${CONTAINER_TOOL} ps --format '{{.Names}}' | grep -qx "${CONTAINER_NAME}"; then
    echo "[INFO] Container '${CONTAINER_NAME}' is running."
  else
    echo "[WARN] Container '${CONTAINER_NAME}' not found in '${CONTAINER_TOOL} ps'. Check '${CONTAINER_TOOL} ps -a' and logs."
  fi
}
# --- Stop stack cleanly using *-compose in its directory ---
echo "[INFO] Bringing down stack (${CONTAINER_TOOL}-compose down) in ${COMPOSE_DIR}..."
(
  cd "$COMPOSE_DIR"
  # Do NOT pass -p; let the project default to the directory name
  ${CONTAINER_TOOL}-compose down || {
    echo "[WARN] ${CONTAINER_TOOL}-compose down returned non-zero. Continuing (stack may not have been up)."
  }
)
# --- Create archive (compose dir: data, letsencrypt, compose file, etc.) ---
echo "[INFO] Archiving ${COMPOSE_DIR} to ${ARCHIVE}..."
# Preserve SELinux/xattrs and ownership; exclude the backups dir if it's under same parent
tar -C "$(dirname "$COMPOSE_DIR")" \
  --xattrs --selinux --same-owner --numeric-owner \
  --exclude "$(basename "$BACKUP_ROOT")" \
  -czf "$ARCHIVE" "$(basename "$COMPOSE_DIR")"
# Optional integrity checksum
sha256sum "$ARCHIVE" > "${ARCHIVE}.sha256"
# --- Start stack back up ---
echo "[INFO] Starting stack (${CONTAINER_TOOL}-compose up -d)..."
(
  cd "$COMPOSE_DIR"
  ${CONTAINER_TOOL}-compose up -d
)
# --- Verify expected container is running ---
verify_running
# --- Prune according to retention ---
prune_backups "$BACKUP_ROOT" "$RETENTION_DAYS"
echo "[OK] Backup completed: ${ARCHIVE}"
脚本用法示例:
[root@rhel-client01 scripts]# ./backup_npm.sh
[INFO] Removing stale lock file: /var/lock/npm_backup.lock
[INFO] Bringing down stack (podman-compose down) in /root/docker/nginx...
npm
npm
14dc3c3871a7a9716142a1011f1039258d330be1ddb49543eb7a8e257256239a
nginx_default
[INFO] Archiving /root/docker/nginx to /root/docker/backups/npm-backup-2026-02-10_155107.tar.gz...
[INFO] Starting stack (podman-compose up -d)...
be491bf43aa17f1a767075ed8b2cd55d93cdf4581ad04abe66a58f3bce0b5e74
e677dbedd5fdd92a440896dc4cae22165cb34ce704ec3ed8f7620ce243183585
npm
[INFO] Container 'npm' is running.
[INFO] Pruning backups older than 3 days in /root/docker/backups...
[OK] Backup completed: /root/docker/backups/npm-backup-2026-02-10_155107.tar.gz
[root@rhel-client01 scripts]#
[root@rhel-client01 scripts]# ls -ltr /root/docker/backups/
total 8
-rw-r--r--. 1 root root 638 Feb 10 15:51 npm-backup-2026-02-10_155107.tar.gz
-rw-r--r--. 1 root root 123 Feb 10 15:51 npm-backup-2026-02-10_155107.tar.gz.sha256

或者,为脚本创建一个 cron 作业,使其每天、每周等运行一次(根据您的判断),

[root@rhel-client01 scripts]# ln -s /root/scripts/backup_npm.sh /etc/cron.daily/backup_npm
[root@rhel-client01 scripts]#
提醒:由于脚本会停止 docker 容器,因此务必将归档脚本安排在可接受的瞬时停机时间内。这必须与系统和 docker 管理员协调。
  1. 为托管 docker 容器的系统创建 NetWorker 客户端。“存储集”是用于对包含 docker tarball 归档文件进行目录的目录:

Docker 客户端

  1. 执行客户端备份。NetWorker Administration Guide提供了有关创建备份策略和计划的更多信息。NetWorker 文档可通过以下方式获得:适用于NetWorker的支持 |手册和文档 

客户端备份包含 docker archive-tarball 数据:

[root@nsr ~]# mminfo -avot -q client=rhel-client01.amer.lan -r "nsavetime,savetime(20),name,sumflags,ssretent"
  save time    date     time   name                           fl  retent
...
 1770757763    02/10/2026 16:09 /root/docker/backups          cb 03/10/2026

[root@nsr ~]# nsrinfo -t 1770757763 rhel-client01.amer.lan
scanning client `rhel-client01.amer.lan' for savetime 1770757763(Tue 10 Feb 2026 04:09:23 PM EST) from the backup namespace
/root/docker/backups/npm-backup-2026-02-10_155107.tar.gz
/root/docker/backups/npm-backup-2026-02-10_155107.tar.gz.sha256
/root/docker/backups/
/root/docker/
/root/
/
6 objects found
数据将按照备份作中设置的保留期保留。

NetWorker 客户端恢复用于将 tarball 恢复到现有(或备用)NetWorker 客户端。系统和 docker 管理员必须执行后续步骤,以使用恢复的数据重新配置 docker 容器。

Affected Products

NetWorker

Products

NetWorker
Article Properties
Article Number: 000071581
Article Type: Solution
Last Modified: 18 Apr 2026
Version:  8
Find answers to your questions from other Dell users
Support Services
Check if your device is covered by Support Services.