1. 说明

  1. 之前使用的是 CentOS 7 和 Ubuntu,架构都是 x86_64。采用 本机安装 + 打快照 的方式来部署 PostgreSQL + PostGIS,用起来一直挺稳定。
  2. 这次换成了 CentOS 7 AltArch 架构,本来以为照旧从 PostgreSQL 官网安装就行,结果在装 PostGIS 的时候遇到了很多依赖缺失的问题。查了一圈资料后才发现,是因为 ARM 架构的依赖包更新不太及时。折腾了好一阵子还是没解决,最后干脆改成 容器化安装 PostgreSQL + PostGIS,也避免了依赖问题。

2. 介绍

在这里插入图片描述

在这里插入图片描述

3. 启动脚本

启动脚本 /home/startup.sh
启动后,如果镜像不存在他会先进行拉取镜像,再进行程序的启动
启动镜像如果权限不够,可以执行 chmod 给启动脚本修改权限

#!/bin/bash

# Docker 镜像和容器名称
PROJECT_NAME=postgresql-14
DOCKER_IMAGE="swr.cn-north-4.myhuaweicloud.com/ddn-k8s/docker.io/kartoza/postgis:14-3.3-linuxarm64"
CONTAINER_NAME="postgresql-14"
PROJECT_LOGS="docker_logs.txt"

# 判断容器是否正在运行
isExist(){
    # 查找容器是否正在运行
    container_id=$(docker ps -q -f name=${CONTAINER_NAME})
    if [ -z "$container_id" ]; then
        return 0  # 不存在
    else
        return 1  # 存在
    fi
}

# 获取容器的状态
get_status(){
    container_status=$(docker inspect --format '{{.State.Status}}' ${CONTAINER_NAME})
    echo "Container ${CONTAINER_NAME} status: ${container_status}"
}

# 删除日志文件
deletelog(){
    echo "日志文件:${PROJECT_LOGS}"
    if [ -f "${PROJECT_LOGS}" ]; then
        echo "日志文件存在, 删除日志文件"
        # rm -f ${PROJECT_LOGS}
    else
        echo "日志文件不存在"
    fi
}

# 启动 Docker 容器
start(){
    # 检查容器是否已经在运行
    isExist
    if [ $? -eq "0" ]; then
        echo "启动 ${CONTAINER_NAME} 容器..."
        docker run -d --name ${CONTAINER_NAME} \
            -e POSTGRES_USER=postgres \
            -e POSTGRES_PASS=postgres \
            -e ALLOW_IP_RANGE=0.0.0.0/0 \
            -v /home/docker:/var/lib/postgresql \
            -p 5432:5432 \
            --restart=always \
            ${DOCKER_IMAGE}
        echo "${CONTAINER_NAME} 启动成功"
    else
        echo "${CONTAINER_NAME} 容器已经在运行"
    fi
}

# 停止 Docker 容器
stop(){
    # 检查容器是否在运行
    isExist
    if [ $? -eq "0" ]; then
        echo "${CONTAINER_NAME} 容器未运行"
    else
        echo "停止 ${CONTAINER_NAME} 容器..."
        docker stop ${CONTAINER_NAME}
        docker rm ${CONTAINER_NAME}
        echo "${CONTAINER_NAME} 容器停止并删除成功"
    fi
}

# 重启 Docker 容器
restart(){
    stop
    start
}

# 查看容器状态
status(){
    get_status
}

# 查看容器日志
logs(){
    echo "查看容器日志"
    docker logs -f ${CONTAINER_NAME}
}

# 设置容器自启动
set_autostart(){
    # 检查容器是否已经存在
    isExist
    if [ $? -eq "0" ]; then
        echo "容器 ${CONTAINER_NAME} 尚未启动,无法设置自启动"
        start
    fi

    # 获取容器的当前重启策略
    current_restart_policy=$(docker inspect --format '{{.HostConfig.RestartPolicy.Name}}' ${CONTAINER_NAME})

    # 判断是否已设置为 'always'
    if [ "$current_restart_policy" == "always" ]; then
        echo "${CONTAINER_NAME} 已经设置为自启动,取消自启动..."
        docker update --restart=no ${CONTAINER_NAME}
        echo "${CONTAINER_NAME} 已取消自启动"
    else
        echo "容器 ${CONTAINER_NAME} 没有自启动设置,设置为自启动..."
        docker update --restart=always ${CONTAINER_NAME}
        echo "${CONTAINER_NAME} 自启动设置成功"
    fi
}

# 全部操作(停止 + 删除日志文件 + 启动容器)
all(){
    stop
    deletelog
    start
}

# 帮助信息
help(){
    echo " 
====================================================================================================   
## Postres 容器操作脚本  
脚本输入格式为 
    bash> ./startup.sh [command]

command 的命令 start | stop | restart | status | logs | all | deletelog | set_autostart
    1. start            启动 PostGres 容器
    2. stop             停止 PostGres 容器
    3. restart          重启 PostGres 容器
    4. status           查看 PostGres 容器状态
    5. logs             查看 PostGres 容器日志
    6. all              stop + deletelog + start
    7. deletelog        删除日志文件
    8. set_autostart    设置容器自启动(启用或取消)
========================================================================================================="
}

# 根据用户输入执行对应操作
case "$1" in
        "start")
                start
                ;;
        "stop")
                stop
                ;;
        "restart")
                restart
                ;;
        "status")
                status
                ;;
        "logs")
                logs
                ;;
        "all")
                all
                ;;
        "deletelog")
                deletelog
                ;;
        "set_autostart")
                set_autostart
                ;;
        "help")
                help
                ;;
        *)
                echo "请使用正确的命令: start | stop | restart | status | logs | all | deletelog | set_autostart"
                ;;
esac

  • 启动后

在这里插入图片描述

4. 备份

  1. 为了保证数据安装性,对数据进行备份
  2. 这边采用的是 crontab + 备份脚本 + 定时推送 + 定期清除数据 进行数据的冗余备份
  3. 本地保存 7 天,历史数据库备份默认是 30 天,
  4. 这里只对 crontab备份脚本 进行展开说明,另外两个是通过程序进行动态控制的,这样可以记录系统操作
  5. 定时推送定期清除数据 也可以采用脚本的方式进行实现,替代如下
  1. 定时推送 => [scp | ftp | rsync] + crontab 实现
  2. 定期清除数据 => rm + crontab 实现
  • 备份脚本
#!/bin/bash
# PostgreSQL Docker 容器数据库备份与还原脚本
# 使用方式:
#   ./pg_backup.sh backup <数据库名>
#   ./pg_backup.sh restore <数据库名> [备份文件名]

# ===== 配置区 =====
CONTAINER_NAME="postgresql-14"   # 容器名
PGUSER="postgres"                # 用户
PGHOST="127.0.0.1"               # 主机
PGPASSWORD="postgres"        # 密码
PGDATA_DIR="/var/lib/postgresql/dump" # 容器内目录(映射到宿主机 /home/docker)
LOCAL_DIR="/home/docker/dump"         # 宿主机目录
# ==================

ACTION=$1
DBNAME=$2
FILENAME=$3

# 备份
backup(){
    if [ -z "$DBNAME" ]; then
        echo "❌ 缺少数据库名"
        echo "用法: $0 backup <数据库名>"
        exit 1
    fi
    FILE="${DBNAME}_$(date +%Y%m%d_%H%M%S).dump"
    echo "开始备份数据库 ${DBNAME}${LOCAL_DIR}/${FILE} ..."
    docker exec -e PGPASSWORD=$PGPASSWORD -i $CONTAINER_NAME \
        pg_dump -h $PGHOST -U $PGUSER -F c -d $DBNAME \
        -f $PGDATA_DIR/$FILE
    if [ $? -eq 0 ]; then
        echo "✅ 备份成功: ${LOCAL_DIR}/${FILE}"
    else
        echo "❌ 备份失败"
    fi
}

# 还原
restore(){
    if [ -z "$DBNAME" ]; then
        echo "❌ 缺少数据库名"
        echo "用法: $0 restore <数据库名> [备份文件名]"
        exit 1
    fi
    if [ -z "$FILENAME" ]; then
        FILE=$(ls -t ${LOCAL_DIR}/${DBNAME}_*.dump 2>/dev/null | head -1)
        if [ -z "$FILE" ]; then
            echo "❌ 未找到 ${LOCAL_DIR}/${DBNAME}_*.dump 文件"
            exit 1
        fi
    else
        FILE="${LOCAL_DIR}/${FILENAME}"
        if [ ! -f "$FILE" ]; then
            echo "❌ 指定的文件不存在: $FILE"
            exit 1
        fi
    fi
    BASENAME=$(basename $FILE)

    echo "开始将 ${FILE} 还原到数据库 ${DBNAME} ..."

    # 创建数据库(已存在忽略错误)
    docker exec -e PGPASSWORD=$PGPASSWORD -i $CONTAINER_NAME \
        createdb -h $PGHOST -U $PGUSER $DBNAME 2>/dev/null || true

    # 执行还原
    docker exec -e PGPASSWORD=$PGPASSWORD -i $CONTAINER_NAME \
        pg_restore -h $PGHOST -U $PGUSER -d $DBNAME -v $PGDATA_DIR/$BASENAME
    if [ $? -eq 0 ]; then
        echo "✅ 还原成功: ${DBNAME}"
    else
        echo "❌ 还原失败"
    fi
}

# 帮助信息
help(){
    echo "
====================================================================================================
## PostgreSQL 备份还原脚本
用法:
    ./pg_backup.sh backup <数据库名>
        → 备份指定数据库到 ${LOCAL_DIR}/下

    ./pg_backup.sh restore <数据库名> [备份文件名]
        → 还原到指定数据库
        → 如果不指定文件名,则自动选择最新的备份

命令说明:
    1. backup     备份数据库
    2. restore    还原数据库
    3. help       显示帮助
===================================================================================================="
}

# 根据用户输入执行对应操作
case "$ACTION" in
    "backup")
        backup
        ;;
    "restore")
        restore
        ;;
    "help")
        help
        ;;
    *)
        echo "请使用正确的命令: backup | restore | help"
        ;;
esac
  • crontab
## 执行这一句进入定时任务
crontab -e

两种备份方式

##第一种: 每天 1点的进行  备份  
0 1 * * * /bin/bash /home/backup_restore.sh backup database  

##第二种: 每天 1点的进行  备份  +  传输  + 日志记录
## 0 1 * * * /bin/bash /home/backup_restore.sh backup database && /bin/bash /home/backup_scp.sh >> /home/backup_scp_cron.log 2>&1

在这里插入图片描述

5. 问题

在测试容器化安装是否有无问题的时候,查询当前时间,服务器 和 容器内 的时间不一致,存在 8 小时时差
解决方法如下

## 先进入容器,再进入数据库,
## 指定数据库:命令行执行下面两行指令
## 退出容器,重启容器  就可以解决时差问题
ALTER SYSTEM SET timezone = 'Asia/Shanghai';
ALTER SYSTEM SET log_timezone = 'Asia/Shanghai';

更多推荐