二 使用 docker 运行 wordpress

二 使用 docker 运行 wordpress

【动机】

使用 docker 封装应用的优点在此不用赘述。由于 wordpress 的运行,一般涉及到两个容器:wordpress 和 mysql, 前者自带 apache 和 php 运行时。如果不采用 docker compose 编排容器,如何实现原生控制容器的启停、备份、还原?

【意图】

  1. 使用 docker –link 命令为两个容器建立连接;
  2. 首次运行网站,安装,配置网站相关信息;
  3. 完整备份 mysql、wordpress 到本地;
  4. 将本地备份上传到百度网盘;
  5. 从百度网盘下载备份到本地;
  6. 利用本地备份还原容器;
  7. 两个容器的相关配置,使用 json 文件保存。

【文件结构】

其中,wpsites 是根目录,guoshi 和 sanxiao(还可以自由添加其他实体)是网站实体目录,其下级 backup 是备份目录(其下级备份可以有多个,均以备份时间为名),running 是容器当前运行采用的实际内容。

【实现】

入口脚本文件 main.sh

#!/bin/bash



:<<COMMENT
  rely: 
    1.  jq; to parse json file
    2.  docker; 
    3.  bypy 
    4.  bc  (进度条用到)
    5. wget curl dig nslookup
COMMENT

set -e 

# global constant:
declare -r __DEBUG__=

declare -r ENTRY_FILE_PATH=$(readlink -f $0)
declare -r ENTRY_FILE_NAME=$(basename $ENTRY_FILE_PATH)

declare -r ROOT_DIR_PATH=$(dirname $ENTRY_FILE_PATH) 
declare -r ROOT_DIR_NAME=$(basename $ROOT_DIR_PATH)

declare -r CONFIG_FILE_REL_PATH="data/config.json"
declare -r CONFIG_FILE_PATH="$ROOT_DIR_PATH/$CONFIG_FILE_REL_PATH"
declare -r DEFAULT_CONFIG_ROOT="default"

# region Ignored
# 根据当前脚本与 library 和 execution 的相对位置, .. 可能有所变化
declare -r LNX_LIB_DIR="$ROOT_DIR_PATH/../../library"
# endregion Ignored

# 块 source, 详情查看 library/doc/compile.txt
# 排除目录: -path "$ROOT_DIR_PATH/document" -prune -o \
# 最后接 -print
# region Sourcing
for file in \
    $(find $ROOT_DIR_PATH \
        -path "$ROOT_DIR_PATH/log" -prune -o \
        -path "$ROOT_DIR_PATH/data" -prune -o \
        -path "$ROOT_DIR_PATH/doc" -prune -o \
        -path "$ROOT_DIR_PATH/test" -prune -o \
        -type f -regex .*?\.sh$ \
        -not -wholename "$ENTRY_FILE_PATH" -print ) \
    $(find $LNX_LIB_DIR \
        -type f -regex .*?\.sh$ ) ; do
      source $file
done
# endregion Sourcing 

# global variable:
# 将 json 文件读入字符串, 以便程序启动后,即使删除整个脚本程序, 仍然保证可以顺利运行
declare __JSON_CONTENT__=$(jq . $CONFIG_FILE_PATH)
[ -z "$__JSON_CONTENT__" ] && error "$CONFIG_FILE_PATH 尚未准备好!" && exit 0 

# 编译后的执行文件, 执行前立即保密配置文件中的敏感数据. 
# 本地执行, 则不需要保密
# keep_line     keep_config_secret

# 容器运行的数据父目录
declare RunningParentDir=

# 容器备份的数据父目录
declare LocalBackupParentDir=

# 百度网盘备份的数据父目录
declare BaiduBackupParentDir=

# 本地备份列表(空格分隔的多个目录名字符串)
declare LocalBackups

declare BaiduAvailable
# 百度备份列表(空格分隔的多个目录名字符串)
declare BaiduBackups

# 暂时废弃
#declare LocalRepoTags
#declare WebRepoTags
# -------------------------------start --------------------------------- 
__TEST__=

  # 如果采用 [ ... ] && ... || ... 的形式, 当 choose_entity 退出码非 0 时,
  # 将继续执行 unit_test_start, 这可能不是需要的 
  if [  "$__TEST__" ]; then
      unit_test_start
  else
      clear
      check_baidu_available BaiduAvailable
      choose_entity
  fi
caption "Thanks for your use. Byebye!"

# region Ignored
# 自编译部分, 详情查看 library/doc/compile.txt
if [ "$1" ]; then
    # 配置文件先保密, 再复制
    keep_config_secret
    menu "start compiling ..."
    # 极简调用方式, 但要注意将源文件的 compiling 块和 soucing 块的名称写成函数默认, 即 Ignored 和 Sourcing:
    # 编译后的文件达到 230k, 以至于报错: Argument list too long: /bin/bash, 无法运行。
    # 故针对当前的 shc 版本, 只能使用 script2execution 函数做打包之用(添加 -g 标志)
    cmdline="script2execution 
            --target-path \"$ROOT_DIR_PATH/../../execution/$ROOT_DIR_NAME/${ENTRY_FILE_NAME%.*}\" 
            --attaches \"$CONFIG_FILE_REL_PATH data/sql_adt.cnf \" 
            --give-up-self-compile
        "

    perform --prompt "编译中, 请稍候......" --cmdline "$cmdline" -delay 0.2 
    aop "success -e" center "Compiling finished."
    # 恢复本地 json 文件
    echo $__JSON_CONTENT__ | jq . > $CONFIG_FILE_PATH --tab
fi
# endregion Ignored

可以看到, 包含任意命令行参数,表示自编译为可执行体。

接下来是配置文件 config.json:

{
  "default": {
    "dataPath": {
      "root": "/app/freezone/wpsites",
      "runningParentFmt": "%s/running",
      "backupParentFmt": "%s/backup"
    },
    "dateFmt": "+%Y%m%d-%H%M%S",
    "baidu": {
      "root": "websites",
      "backupParentFmt": "%s",
      "timeout": 10
    },
    "prompt": {
      "congratulations": "congratulations! All the work has been done successfully."
    },
    "mysql": {
      "tag": "9.1.0",
      "container": {
        "volume": "/var/lib/mysql",
        "addConfig": "/etc/mysql/conf.d/sql_adt.cnf"
      },
      "host": {
        "addConfig": "data/sql_adt.cnf"
      },
      "timeout": 320
    },
    "wordpress": {
      "tag": "php8.3-apache",
      "container": {
        "volume": "/var/www/html"
      }
    }
  },
  "guoshi": {
    "mysql": {
      // "rootPwd": "mysql root 用户密码待填入",
      // "hostname": "mysql 主机名称待填入",
      "port": 1111,
      "container": {
        "name": "guoshi-mysql-container"
      },
      "host": {
        "addConfig": null
      }
    },
    "wordpress": {
      "tag": null,
      "port": 1119,
      "container": {
        "name": "guoshi-wordpress-container",
        "volume": null
      },
      "database": {
        // "name": "wp 在数据库服务器中, 对应的数据库名",
        // "account": "wp 对应数据库专用账号名称待填入",
        // "password": "上述账号密码待填入",
        "tablePrefix": "guoshi_",
        "backupSqlName": "wp.sql"
      },
      "webstation": {
        "title": "漠北清音"
      }
    }
  },
  "sanxiao": {
    "mysql": {
      // "rootPwd": "mysql root 用户密码待填入",
      // "hostname": "mysql 主机名称待填入",
      "port": 2111,
      "container": {
        "name": "sanxiao-mysql-container"
      },
      "host": {
        "addConfig": null
      }
    },
    "wordpress": {
      "tag": null,
      "port": 2119,
      "container": {
        "name": "sanxiao-wordpress-container",
        "volume": null
      },
      "database": {
        // "name": "wp 在数据库服务器中, 对应的数据库名",
        // "account": "wp 对应数据库专用账号名称待填入",
        // "password": "上述账号密码待填入",
        "tablePrefix": "sanxiao_",
        "backupSqlName": "wp.sql"
      },
      "webstation": {
        "title": "中华神作"
      }
    }
  }
}

【运行效果】

此处以新安装“中华神作”为例, 演示容器的创建、备份、还原、移除, 以及运行结束后的自编译。

其中上传备份到百度,速度比较慢,就不继续示范了。

最后是自编译示范: