docker gitlab容器数据备份步骤

自动备份

  1. 创建/home/scripts下命名为gitlab_backup.sh的脚本

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    #!/bin/bash

    # 启用严格错误检查
    set -euo pipefail

    # 配置参数(允许通过环境变量覆盖)
    BACKUP_ROOT=${BACKUP_ROOT:-"${HOME}/gitlab-docker/backup"}
    CONTAINER_NAME=${CONTAINER_NAME:-"gitlab"}
    RETAIN_DAYS=${RETAIN_DAYS:-28}

    # 生成日期标签
    DATE=$(date +%Y%m%d_%H%M)
    BACKUP_DIR="${BACKUP_ROOT}/backup_${DATE}"
    LOG_FILE="${BACKUP_ROOT}/backup_log.txt"

    # 创建备份目录(logs不做备份,这里为挂载新容器做准备)
    mkdir -p "${BACKUP_DIR}/gitlab/"{config,logs,data}

    # 捕获错误并输出信息函数
    handle_error() {
    echo "" >> "$LOG_FILE"
    echo "${DATE}" >> "$LOG_FILE"
    echo "Backup completed Failed! ! !" >> "$LOG_FILE"
    echo "Error: $1" >> "$LOG_FILE"
    echo "Error: $1" | mail -s "gitlab-backup" user@qq.com
    # 如果备份失败,删除创建的文件夹
    sudo rm -rf "${BACKUP_DIR}"
    exit 1
    }

    # 1. GitLab 应用数据备份
    echo "Step 1: Creating GitLab application backup..."
    if ! docker exec -t "$CONTAINER_NAME" gitlab-rake gitlab:backup:create; then
    handle_error "Failed to create GitLab application backup."
    fi

    # 2. 备份配置文件
    CONFIG_SRC="${HOME}/gitlab-docker/gitlab/config"

    echo "Step 2: Backing up configuration..."
    if ! sudo tar -czf "${BACKUP_DIR}/gitlab/config/gitlab_config_${DATE}.tar.gz" -C "$CONFIG_SRC" .; then
    handle_error "Failed to backup GitLab configuration."
    fi

    # 3. 移动 GitLab 自动生成的备份文件
    DOCKER_BACKUP_SRC="${HOME}/gitlab-docker/gitlab/data/backups"
    if [ ! -d "$DOCKER_BACKUP_SRC" ] || [ -z "$(sudo ls -A $DOCKER_BACKUP_SRC)" ]; then
    handle_error "Backup source directory '$DOCKER_BACKUP_SRC' is empty or does not exist."
    fi

    echo "Step 3: Locating latest backup file..."
    LATEST_BACKUP=$(sudo find "$DOCKER_BACKUP_SRC" -type f -name '*.tar' -printf '%T@ %p\n' | sort -n | tail -1 | cut -d' ' -f2-)
    if [ -z "$LATEST_BACKUP" ]; then
    handle_error "No backup file found in $DOCKER_BACKUP_SRC"
    fi

    echo "Found latest backup: $LATEST_BACKUP"
    if ! sudo mv -v "$LATEST_BACKUP" "${BACKUP_DIR}/gitlab/data"; then
    handle_error "Failed to copy the latest backup file."
    fi

    # 4. 清理旧备份
    echo "Step 4: Cleaning up old backups..."
    if ! sudo find "$BACKUP_ROOT" -name 'backup_*' -mtime +"$RETAIN_DAYS" -print -exec rm -rf {} +; then
    handle_error "Failed to clean up old backups"
    fi

    # 5. 压缩整个备份目录
    echo "Step 5: Compressing backup directory..."
    if ! sudo tar -czf "${BACKUP_ROOT}/backup_${DATE}.tar.gz" -C "${BACKUP_ROOT}" "backup_${DATE}"; then
    handle_error "Failed to compress the backup directory."
    fi
    if ! sudo rm -rf "${BACKUP_DIR}"; then
    handle_error "Failed to remove the uncompressed backup directory."
    fi

    # 6. 记录日志并输出成功信息
    echo "" >> "$LOG_FILE"
    echo "${DATE}" >> "$LOG_FILE"
    echo "Backup completed successfully!" >> "$LOG_FILE"
    echo "Compressed backup location: ${BACKUP_ROOT}/backup_${DATE}.tar.gz" >> "$LOG_FILE"

    # 输出到shell,方便调试
    echo "Backup completed successfully!"
    echo "Backup completed successfully!" | mail -s "gitlab-backup" user@qq.com
  2. 配置邮件服务(将备份结果以网易邮件形式通知到管理员)

    1. 安装postfix

      1
      2
      sudo apt update
      sudo apt install postfix

      安装过程中选择 Internet Site

    2. 编辑配置文件

      1
      sudo nano /etc/postfix/main.cf

      修改/添加以下内容

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      # 基本配置
      myhostname = localhost
      myorigin = /etc/mailname
      inet_interfaces = loopback-only
      relayhost = [smtp.163.com]:465

      # SASL 认证
      smtp_sasl_auth_enable = yes
      smtp_sasl_password_maps = hash:/etc/postfix/sasl_passwd
      smtp_sasl_security_options = noanonymous
      smtp_sasl_mechanism_filter = login

      # TLS/SSL 加密
      smtp_use_tls = yes
      smtp_tls_wrappermode = yes
      smtp_tls_CAfile = /etc/ssl/certs/ca-certificates.crt
    3. 配置SMTP认证信息

      1
      sudo nano /etc/postfix/sasl_passwd

      写入以下内容

      1
      [smtp.163.com]:465 user@163.com:你的授权码
    4. 设置发件人域名

      1
      sudo nano /etc/mailname

    写入以下内容

    1
    163.com
  3. 生成数据库文件并设置权限:

    1
    2
    sudo postmap /etc/postfix/sasl_passwd
    sudo chmod 600 /etc/postfix/sasl_passwd /etc/postfix/sasl_passwd.db
    1. 重启Postfix

      1
      sudo systemctl restart postfix
    2. 测试发送邮件

      1
      echo "test" | mail -s "test subject" user@qq.com
    3. 可能存在的问题

      • MAIL FROM配置不正确,需要强制修改

        1. 修改postfix配置文件

          1
          sudo nano /etc/postfix/main.cf

          添加以下内容

          1
          smtp_generic_maps = hash:/etc/postfix/generic
        2. 创建地址映射文件

          1
          sudo nano /etc/postfix/generic

          写入以下内容

          1
          2
          3
          4
          @logo-ubuntu-fd  user@163.com
          @localhost user@163.com
          # 动态匹配当前主机名
          @$(myhostname) user@163.com
        3. 生成映射数据库

          1
          sudo postmap /etc/postfix/generic
        4. 重启Postfix

          1
          sudo systemctl restart postfix
  4. 自动运行脚本

    1
    2
    3
    4
    5
    # 添加权限
    chomd +x backup_gitlab.sh

    # 通过contab设置定期任务 每周一早上8点执行一次备份
    0 8 * * 1 /home/Username/scripts/gitlab_backup.sh
  5. 为脚本添加sudo免密码权限

    1
    2
    3
    4
    5
    # 1.visudo 命令
    sudo visudo

    # 在文件末尾添加
    your-username ALL=(ALL) NOPASSWD: ALL
  6. 手动触发脚本执行测试

    1
    ./home/Username/scripts/gitlab_backup.sh
  7. 说明

    • 备份产生的目录结构为gitlab /(config + logs + data),其中logs是一个空文件夹,此举只是为了方便生成新容器时方便挂载,data包含一个gitlab内置备份功能生成的一个tar文件,config则是从源容器完全移植过来的。
    • backup下会自动生成一个log.txt文件记录备份结果日志。

恢复

  1. 生成一个新的容器(挂载到备份目录上)

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    docker run -d \
    --name gitlab-new \
    --hostname gitlab.example.com \
    --publish 9080:80 \
    --publish 9443:443 \
    --publish 3222:22 \
    --volume $PWD/gitlab/config:/etc/gitlab \
    --volume $PWD/gitlab/logs:/var/log/gitlab \
    --volume $PWD/gitlab/data:/var/opt/gitlab \
    --shm-size 256m \
    --restart always \
    my-gitlab:16.10.2
  2. 移动备份文件到新的容器备份文件目录下

    1
    2
    3
    4
    # 进入容器终端
    docker exec -it gitlab-new /bin/bash

    mv /var/opt/gitlab/1638293100_gitlab_backup.tar /var/opt/gitlab/backups/
  3. 设置文件权限

    1
    chown git:git /var/opt/gitlab/backups/1638293100_gitlab_backup.tar
  4. 解决PostgreSQL数据库扩展权限问题

    1. 修改PostgreSQL相关配置

      1
      2
      3
      4
      5
      6
      7
      vi /var/opt/gitlab/postgresql/data/postgresql.conf
      # listen_addresses = ''修改为listen_addresses = '*'

      vi /var/opt/gitlab/postgresql/data/pg_hba.conf
      # 最下面添加
      # local all all trust
      # host all all 127.0.0.1/32 trust
    2. 重启gitlab服务

      1
      gitlab-ctl restart
    3. 修改gitlab账号为超级用户

      1
      2
      3
      4
      5
      6
      7
      gitlab-psql -d gitlabhq_production

      gitlabhq_production=# ALTER USER gitlab WITH SUPERUSER;
      gitlabhq_production=# ALTER ROLE
      gitlabhq_production=# \q

      exit
  5. 执行恢复

    1
    2
    3
    4
    5
    6
    7
    8
    # 停止连接到数据库的进程(在容器内执行)
    gitlab-ctl stop puma
    gitlab-ctl stop sidekiq

    # 执行恢复(替换文件名中的备份时间戳)
    gitlab-rake gitlab:backup:restore BACKUP=1638293100

    # 按照提示输入 "yes" 确认
  6. 重启gitlab服务

    1
    gitlab-ctl restart
  7. 检查gitlab数据是否完全恢复

  8. 可能遇到的问题 新容器不能正常启动 502代码:修复权限

    1
    docker exec -it gitlab-new update-permissions