本文共 5758 字,大约阅读时间需要 19 分钟。
作者:王志斌,曾获得中国PostgreSQL数据库管理工程师(PGCE),是PostgreSQL官方认证讲师,盘古云课堂特邀金牌讲师。
数据库容器化,一直是一个比较有争议的话题,在网上针对性的讨论也很多,缺点如数据库安全、性能问题[1]等等,当然优点也很明显,比如自动化运维、弹性伸缩[2]等等。
本文不讨论具体优缺点,主要目的是介绍如何编写Dockerfile[3],创建镜像文件,并且运行容器下的单机数据库(单机数据库为build包形式),下面将详细说明如何搭建docker环境、编写dockerfile及相关文件、构建镜像并运行容器等步骤。
首先,需要搭建本机的docker环境,Docker 要求 CentOS 系统的内核版本高于 3.10,可以通过以下命令进行环境监测和安装,本文演示所用操作系统版本为centos7。
1、通过uname -r命令查看你当前的内核版本
$ uname -r
2、使用root权限登录Centos。确保yum包更新到最新。
$ yum update
3、卸载旧版本(如果安装过旧版本的话)
$ yum remove docker docker-common docker-selinux docker-engine
4、安装需要的软件包,yum-util提供yum-config-manager功能,另外两个是devicemapper驱动依赖的
$ yum install -y yum-utils device-mapper-persistent-data lvm2
5、设置yum源
$ yum-config-manager --add-repo https://download.docker.com/linux/centos/docker-ce.repo
6、可以查看所有仓库中所有docker版本,并选择特定版本安装
$ yum list docker-ce --showduplicates | sort -r
7、安装docker
$ yum install docker-ce
8、启动并加入开机启动
$ systemctl start docker$ systemctl enable docker
9、验证安装是否成功(有client和service两部分表示docker安装启动都成功了)
$ docker version
在构建数据库镜像时,需要准备如下文件:
1、Dockerfile
创建镜像时所需要的基本环境、设置、相关的安装步骤、容器入口等。2、entrypoint.sh
容器启动时,默认执行的脚本文件,负责一些方法调用,如引导数据库初始化、参数配置及数据库启动等。3、functions
容器中定义的各类操作的脚本文件,通过entrypoint.sh来进行调用。4、start-stop-daemon
进程守护文件,通过该程序启动并监控postgres进程。下面将介绍关键文件的具体内容:
定义创建镜像文件,最后通过本文件在本地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_INCLUDEDIR=/usr/lib/postgresql/include \ PG_CLIENTDIR=/usr/bin \ PG_LOGDIR=/var/log/postgresql \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"]
主要进行一些初始化工作,具体方法在functions下进行详细定义。
#!/bin/bash set -e source "${PG_APP_HOME}/functions"if [[ -z ${1} ]]; then create_datadir configure_postgresql #启动数据库 echo "Starting postgresql ..." exec start-stop-daemon --start --chuid "${PG_USER}:${PG_USER}" \ --exec "${PG_BINDIR}/postgres" -- -D "${PG_DATADIR}" ${EXTRA_ARGS} else exec "$@" fi
数据库初始化目录、修改配置参数及运行等具体方法。
创建数据目录
create_datadir() { echo "Initializing datadir..." 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} }
初始化数据库
initialize_database() { if [[ ! -f ${PG_DATADIR}/PG_VERSION ]]; then 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 configure_hot_standby fi 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 set_hba_param "host all all 0.0.0.0/0 md5" }
设置日志目录
create_logdir() { echo "Initializing logdir..." mkdir -p ${PG_LOGDIR} chmod -R 1775 ${PG_LOGDIR} chown -R root:${PG_USER} ${PG_LOGDIR}}
设置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 "? Setting postgresql.conf parameter: ${key} = '${value}'" fi value="$(echo "${value}" | sed 's|[&]|\\&|g')" exec_as_postgres sed -i "s|^[#]*[ ]*${key} = .*|${key} = '${value}'|" ${PG_CONF} fi fi }
启动数据库
#配置postgresql数据库configure_postgresql() { initialize_database set_postgresql_param "listen_addresses" "127.0.0.1" quiet exec_as_postgres ${PG_BINDIR}/pg_ctl -D ${PG_DATADIR} -w start >/dev/null exec_as_postgres ${PG_BINDIR}/pg_ctl -D ${PG_DATADIR} -w stop >/dev/null set_postgresql_param "listen_addresses" "*" quiet }
创建镜像
进入到程序所在目录,通过命令创建镜像,注意最后的.
docker build -t postgresql.通过调用docker run运行容器,将内部5432端口映射为宿主机端口,同时将内部数据目录映射为宿主机目录。
docker run --name postgresql10 -itd --restart always --publish 5432:5432 --volume /root/pgdata:/var/lib/postgresql postgresql:latest这样就完成了一个单机的容器从构建镜像到运行容器的整个过程。
本文只是简单介绍如何快速制作单机数据库镜像及运行,后续将逐步介绍如何搭建主从环境以及repmgr、patroni、stolon等方案的容器化实践,另外关于docker容器本身资源限额问题,也是容器化必须关注的一个重要方面,有兴趣的朋友可以查阅相关资料进行了解。
[1]https://developer.aliyun.com/article/767231 [2]https://blog.51cto.com/14977574/2547293 [3]https://docs.docker.com/engine/reference/builder/ [4]https://www.cybertec-postgresql.com/en/running-postgres-in-docker-why-and-how/
了解更多PostgreSQL热点资讯、新闻动态、精彩活动,请访问中国PostgreSQL官方网站:www.postgresqlchina.com
解决更多PostgreSQL相关知识、技术、工作问题,请访问中国PostgreSQL官方问答社区:www.pgfans.cn
下载更多PostgreSQL相关资料、工具、插件问题,请访问中国PostgreSQL官方下载网站:www.postgreshub.cn
转载地址:http://mmmxf.baihongyu.com/