博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Docker容器之主从篇
阅读量:2019 次
发布时间:2019-04-28

本文共 10349 字,大约阅读时间需要 34 分钟。

作者:王志斌,曾获得中国PostgreSQL数据库管理工程师(PGCE),是PostgreSQL官方认证讲师,盘古云课堂特邀金牌讲师。

上一篇文章向大家介绍了一个容器的单机数据库从创建开始到运行的整个过程,相信大家对Dockerfile的基本概念有了一个大致的了解,下面将给大家介绍如何在容器下创建主从复制环境。

关于如何搭建docker环境,在第一篇中已经介绍过,这里就不赘述。下面我们直接进入主题,构建docker镜像的步骤与单机的基本镜像构建基本一样,只是在具体的脚本内容上有所差别。

为了方便理解,此处仍按步骤进行操作:

创建镜像

Dockerfile

定义创建镜像文件,最后通过本文件在本地docker仓库中创建镜像。

注:这部分内容与之前单机构建镜像文件没有差别。

#基础镜像版本from centos:7 #维护人员信息MAINTAINER wangzhibin #变量PG_VERSION=10 \ PG_USER=postgresql \ PG_HOME=/var/lib/postgresql\ PG_BINDIR=/usr/lib/postgresql//bin \ PG_LIBDIR=/usr/lib/postgresql/lib \ PG_LOGDIR=/var/log/postgresql \PG_INCLUDEDIR=/usr/lib/postgresql/include \ PG_CLIENTDIR=/usr/bin \ PG_SHAREDIR=/usr/lib/postgresql/share #运行时环境变量ENV PG_APP_HOME="/etc/docker-postgresql" \ ENV LD_LIBRARY_PATH /usr/lib/postgresql/lib #安装依赖并创建用户组和用户RUN yum install -y acl sudo locales libxml2-dev libssl-dev net-tools \ && groupadd postgresql\ && useradd postgresql -g postgresql -p "123456" \ && echo root:rootpwd|chpasswd \ && echo postgresql:123456|chpasswd #拷贝文件COPY bin/ ${PG_BINDIR} COPY lib/ ${PG_LIBDIR} COPY include/ ${PG_INCLUDEDIR} COPY bin/ ${PG_CLIENTDIR} COPY share/ ${PG_SHAREDIR} COPY runtime/ ${PG_APP_HOME}/ COPY start-stop-daemon /sbin/COPY entrypoint.sh /sbin/entrypoint.sh && chmod 755 /sbin/start-stop-daemon#修改入口执行文件权限RUN chmod 755 /sbin/entrypoint.sh #映射端口EXPOSE 5432/tcp#设定工作目录,默认启动后切换至该目录 WORKDIR ${PG_HOME} #设置执行的入口文件ENTRYPOINT ["/sbin/entrypoint.sh"]

entrypoint.sh

#!/bin/bashset -e# shellcheck source=runtime/functionssource "${PG_APP_HOME}/functions"[[ ${DEBUG} == true ]] && set -x# 接收外部参数if [[ ${1:0:1} = '-' ]]; then  EXTRA_ARGS="$@"  set --elif [[ ${1} == postgres || ${1} == $(command -v postgres) ]]; then  EXTRA_ARGS="${@:2}"  set --fi# default behaviour is to launch postgresif [[ -z ${1} ]]; then  create_datadir  configure_postgresql  #启动数据库  echo "开始Postgresql ..."  exec start-stop-daemon --start --chuid "${PG_USER}:${PG_USER}" \    --exec "${PG_BINDIR}/postgres" -- -D "${PG_DATADIR}" ${EXTRA_ARGS}else  exec "$@"fi

functions

该文件的主要功能是:初始化数据库目录、修改配置参数及运行数据库,在备用模式下,根据设置角色不同,设置流复制,实现主从模式,下面为部分脚本代码:

创建数据目录

create_datadir() {
echo "初始化数据目录" mkdir -p ${PG_HOME} if [[ -d ${PG_DATADIR} ]]; then chmod 0600 $( find ${
PG_DATADIR} -type f ) chmod 0700 $( find ${
PG_DATADIR} -type d ) fi chown -R ${PG_USER}:${PG_USER} ${PG_HOME} }

初始化数据库

注:此处与之前单机有不同,通过pg_baskbackup全量备份后,并创建流复制。

initialize_database() {
if [[ ! -f ${PG_DATADIR}/PG_VERSION ]]; then case ${REPLICATION_MODE} in slave|snapshot|backup) if [[ -z $REPLICATION_HOST ]]; then echo "未设置复制主机" exit 1 fi if [[ -z $REPLICATION_USER ]]; then echo "未设置复制用户" exit 1 fi if [[ -z $REPLICATION_PASS ]]; then echo "未设置复制密码" exit 1 fi echo -n "等待 $REPLICATION_HOST 接受连接 (60s timeout)" timeout=60 #检查主机连接状态 while ! ${PG_BINDIR}/pg_isready -h $REPLICATION_HOST -p $REPLICATION_PORT -t 1 >/dev/null 2>&1 do timeout=$(expr $timeout - 1) if [[ $timeout -eq 0 ]]; then echo "超时退出" exit 1 fi echo -n "." sleep 1 done case ${REPLICATION_MODE} in slave) echo "从$REPLICATION_HOST 复制数据" exec_as_postgres PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \ -h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -X stream -w >/dev/null ;; snapshot) echo "在复制主机 $REPLICATION_HOST 生成快照" exec_as_postgres PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \ -h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -X fetch -w >/dev/null ;; backup) echo "备份 $REPLICATION_HOST 数据" exec_as_postgres PGPASSWORD=$REPLICATION_PASS ${PG_BINDIR}/pg_basebackup -D ${PG_DATADIR} \ -h ${REPLICATION_HOST} -p ${REPLICATION_PORT} -U ${REPLICATION_USER} -X fetch -w >/dev/null exit 0 ;; esac ;; *) if [[ -n $PG_PASSWORD ]]; then echo "${PG_PASSWORD}" > /tmp/pwfile Fi exec_as_postgres ${PG_BINDIR}/initdb --pgdata=${PG_DATADIR} \ --username=${PG_USER} --encoding=unicode --dbstyle=${PG_MODE} --auth=trust ${PG_PASSWORD:+--pwfile=/tmp/pwfile} >/dev/null ;; esac configure_hot_standby # 配置数据路径 set_postgresql_param "data_directory" "${PG_DATADIR}" # 配置日志 set_postgresql_param "logging_collector" on set_postgresql_param "log_directory" "${PG_LOGDIR}" set_postgresql_param "log_filename" "postgresql-${PG_VERSION}-main.log" # 创建本地信任连接 if [[ ${PG_TRUST_LOCALNET} == true ]]; then set_hba_param "host all all samenet trust" fi # 允许所有远端连接到postgresql set_hba_param "host all all 0.0.0.0/0 md5"}

设置pg_hba

#设置pg_hba文件 set_hba_param() {
local value=${1} if ! grep -q "$(sed "s| | \\\+|g" <<< ${
value})" ${PG_HBA_CONF}; then echo "${value}" >> ${PG_HBA_CONF} fi }

设置postgresql.conf

#设置postgresql参数 set_postgresql_param() {
local key=${1} local value=${2} local verbosity=${3:-verbose} if [[ -n ${value} ]]; then local current=$(exec_as_postgres sed -n -e "s/^\(${
key} = '\)\([^ ']*\)\(.*\)$/\2/p" ${PG_CONF}) if [[ "${current}" != "${value}" ]]; then if [[ ${verbosity} == verbose ]]; then echo "? 设置postgresql.conf 参数: ${key} = '${value}'" fi value="$(echo "${value}" | sed 's|[&]|\\&|g')" exec_as_postgres sed -i "s|^[#]*[ ]*${key} = .*|${key} = '${value}'|" ${PG_CONF} fi fi }

设置recovery.conf

set_recovery_param() {
local key=${1} local value=${2} local hide=${3} if [[ -n ${value} ]]; then local current=$(exec_as_postgres sed -n -e "s/^\(.*\)\(${key}=\)\([^ ']*\)\(.*\)$/\3/p" ${PG_RECOVERY_CONF}) if [[ "${current}" != "${value}" ]]; then case ${hide} in true) echo "? 设置primary_conninfo 参数: ${key}" ;; *) echo "? 设置 primary_conninfo 参数: ${key} = '${value}'" ;; esac exec_as_postgres sed -i "s|${key}=[^ ']*|${key}=${value}|" ${PG_RECOVERY_CONF} fi fi}

设置流复制

configure_recovery() {
if [[ ${REPLICATION_MODE} == slave ]]; then echo "配置还原" if [[ ! -f ${PG_RECOVERY_CONF} ]]; then exec_as_postgres touch ${PG_RECOVERY_CONF} ( echo "standby_mode = 'on'"; echo "primary_conninfo = 'host=${REPLICATION_HOST} port=${REPLICATION_PORT} user=${REPLICATION_USER} password=${REPLICATION_PASS}'"; ) > ${PG_RECOVERY_CONF} else set_recovery_param "host" "${REPLICATION_HOST}" set_recovery_param "port" "${REPLICATION_PORT}" set_recovery_param "user" "${REPLICATION_USER}" set_recovery_param "password" "${REPLICATION_PASS}" "true" set_recovery_param "sslmode" "${REPLICATION_SSLMODE}" fi else rm -rf ${PG_RECOVERY_CONF} fi}

创建数据库

create_database() {
if [[ -n ${DB_NAME} ]]; then case $REPLICATION_MODE in slave|snapshot|backup) echo "不能在复制模式的节点下创建数据库" ;; *) for database in $(awk -F',' '{
for (i = 1 ; i <= NF ; i++) print $i}' <<< "${DB_NAME}"); do echo "创建数据库: ${database}..." if [[ -z $(psql -U ${PG_USER} -d ${PG_USER} -Atc "SELECT 1 FROM pg_catalog.pg_database WHERE datname = '${database}'";) ]]; then psql -U ${PG_USER} -d ${PG_USER} -c "CREATE DATABASE \"${database}\" WITH TEMPLATE = \"${DB_TEMPLATE}\";" >/dev/null fi if [[ -n ${DB_USER} ]]; then echo "分配给用户 ${DB_USER} ..." psql -U ${PG_USER} -d ${PG_USER} -c "GRANT ALL PRIVILEGES ON DATABASE \"${database}\" to \"${DB_USER}\";" >/dev/null fi done ;; esac fi}

创建普通用户

create_user() {
if [[ -n ${DB_USER} ]]; then case $REPLICATION_MODE in slave|snapshot|backup) echo "用户不能创建在复制节点上" ;; *) if [[ -z ${DB_PASS} ]]; then echo "需要指定数据库用户密码" exit 1 fi echo "创建数据库用户: ${DB_USER}" if [[ -z $(psql -U ${
PG_USER} -d ${
PG_USER} -Atc "SELECT 1 FROM pg_catalog.pg_user WHERE usename = '${DB_USER}'";) ]]; then psql -U ${PG_USER} -d ${PG_USER} -c "CREATE ROLE \"${DB_USER}\" with LOGIN CREATEDB PASSWORD '${DB_PASS}';" >/dev/null fi ;; esac fi}

创建复制用户

create_replication_user() {
if [[ -n ${REPLICATION_USER} ]]; then case $REPLICATION_MODE in slave|snapshot|backup) ;; *) if [[ -z ${REPLICATION_PASS} ]]; then echo "未设置复制用户密码" exit 1 fi echo "创建复制用户: ${REPLICATION_USER}" if [[ -z $(psql -U ${
PG_USER} -d ${
PG_USER} -Atc "SELECT 1 FROM pg_catalog.pg_user WHERE usename = '${REPLICATION_USER}'";) ]]; then psql -U ${PG_USER} -d ${PG_USER} -c "CREATE ROLE \"${REPLICATION_USER}\" WITH REPLICATION LOGIN ENCRYPTED PASSWORD '${REPLICATION_PASS}';" >/dev/null fi set_hba_param "host replication ${REPLICATION_USER} 0.0.0.0/0 md5" ;; esac fi}

启动数据库

#配置postgresql数据库   source /etc/profile  initialize_database  configure_recovery  rm -rf ${PG_DATADIR}/postmaster.pid  set_postgresql_param "listen_addresses" "127.0.0.1" quiet    exec_as_postgres ${PG_BINDIR}/pg_ctl -D ${PG_DATADIR} -w start >/dev/null        create_user    create_database    create_replication_user  # stop the postgres server  exec_as_postgres ${PG_BINDIR}/pg_ctl -D ${PG_DATADIR} -w stop >/dev/null  # listen on all interfaces  set_postgresql_param "listen_addresses" "*" quiet

创建镜像

进入到程序所在目录,通过命令创建镜像,注意最后的.

docker build -t postgresql .

运行镜像

构建镜像完成后,可以调用分别调用一下命令,启动主从环境并进行验证。

主机

docker run --name postgresql-master -itd --restart always --env ‘DB_USER=dbuser’ --env ‘DB_PASS=dbuserpass’ --env ‘DB_NAME=test’ --env ‘REPLICATION_USER=repluser’ --env ‘REPLICATION_PASS=repluserpass’ postgresql

备机

docker run --name postgresql-slave -itd --restart always --link postgresql-master:master --env ‘REPLICATION_MODE=slave’ --env ‘REPLICATION_SSLMODE=prefer’ --env ‘REPLICATION_HOST=master’ --env ‘REPLICATION_PORT=5432’ --env ‘REPLICATION_USER=repluser’ --env ‘REPLICATION_PASS=repluserpass’ postgresql

查看复制状态

[root@localhost ~]# docker exec -it postgresql-master /bin/bash

[root@487bfb4d0bf1 postgres]# psql -Upostgres -dpostgres -u

在这里插入图片描述

了解更多PostgreSQL热点资讯、新闻动态、精彩活动,请访问中国PostgreSQL官方网站:

解决更多PostgreSQL相关知识、技术、工作问题,请访问中国PostgreSQL官方问答社区:

下载更多PostgreSQL相关资料、工具、插件问题,请访问中国PostgreSQL官方下载网站:

转载地址:http://qmmxf.baihongyu.com/

你可能感兴趣的文章
Quartz入门实例7-处理被中断的Job
查看>>
Quartz入门实例8-实现一个Job监听器
查看>>
Leetcode 删除排序链表中的重复元素
查看>>
服务器修改端口
查看>>
微信学习资料
查看>>
JS(1) JavaScript 用法
查看>>
(六) JavaScript 对象
查看>>
开源项目(3-1)行为提取和动作识别
查看>>
[hbase] hbase 基础使用
查看>>
Android入门笔记10: AutoCompleteTextView 自动补全文本
查看>>
Android入门笔记16: EditText 和 返回键
查看>>
909422229_Jeesite多表联合列表分页实现
查看>>
909422229_阻塞与非阻塞的区别
查看>>
Node.js学习 - GET/POST
查看>>
CentOS7安装Nginx并部署
查看>>
Zookeeper安装使用及JavaAPI使用
查看>>
SQL Server中的数据类型
查看>>
SpringMVC学习系列(4) 之 数据绑定-1
查看>>
秒杀的基本知识点,了解一下
查看>>
Linux如何在系统启动时自动加载模块
查看>>