暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

【GaussDB】构建一个GaussDB的Docker镜像

【GaussDB】构建一个GaussDB的Docker镜像

📋 背景

华为官方未提供GaussDB的Docker镜像,这在很多场景下对应用开发测试非常不方便。

TPOPS用的元库是在docker里的,但是在TPOPS 25.1.30.10 中(GaussDB 内核 506.0 SPC0100)使用的元库是GaussDB 505.1.0.B026版本,这个元库版本里还有GaussDBInstaller(从505.2版本开始不再提供GaussDBInstaller的安装方式),版本不是最新,而且镜像大小超过1GB,包含了一些不必要的东西。(镜像构建代码位置:\docker-service\action\mainAction\build_service_image.sh ->install_build_gaussdb_package)

DockerHub上有apecloud提供的gaussdb,但是只是解压了gaussdb内核和om,并没有安装和初始化数据目录,不是开箱即用的状态,而且内核版本也比较老(503.1.0)。GaussDB最近的版本每次都会有大量特性更新,就算两个相邻版本间差异也会比较大,所以还是需要使用最新版本的内核进行构建。

本文介绍一种构建GaussDB的Docker镜像的方式(单机集中式,不含om、cm、etcd等组件)。


🛠️ 前置准备

基础镜像选择

首先,准备基础镜像。由于GaussDB目前只提供以下几个操作系统对应的内核包,因此,操作系统镜像最好也是从这几个里面选:

  • 麒麟 V10 SP1
  • 麒麟 V10 SP2
  • 麒麟 V10 SP3
  • 统信 V20
  • HCE 2.0
  • SUSE 12 SP5
  • BCLINUX 21.10

这几个操作系统中,国际上使用范围最广的应该是SUSE(毕竟是基于RHEL的分支),但是由于目前国内信创上用得最多的是麒麟V10,为了让运行环境尽量相似,所以本次暂时还是使用麒麟V10作为基础镜像。

注意:由于麒麟官方似乎并未发布Docker镜像,所以我只能在DockerHub上找了个基本完整的镜像 xudingjun3131/kylinv10:sp3-20230324,如果使用其他镜像,需要自行检查其他依赖包是否完整

GaussDB内核程序

然后就是GaussDB内核程序,在 【GaussDB】如何从GaussDB发布包中提取出内核二进制文件 这篇文章中,我们已经提取到了GaussDB的 GaussDB-Kernel_506.0.0.SPC0100_Kylin_64bit.bin,这是一个包含有GaussDB内核可执行程序的最小自解压包。


🔧 构建脚本

Dockerfile

在构建阶段,把GaussDB内核包拷贝进去(不解压)、安装了libaio(需要有访问麒麟官方yum仓库的网络权限)、配置了基本环境变量:

FROM xudingjun3131/kylinv10:sp3-20230324 as builder COPY GaussDB-Kernel_506.0.0.SPC0100_Kylin_64bit.bin /opt/gaussdb/ COPY entrypoint.sh /opt/gaussdb/ RUN mkdir /opt/gaussdb/log &&\ mkdir /opt/gaussdb/data &&\ yum install libaio sudo -y &&\ yum clean all && \ dnf clean all && \ rm -rf /var/cache/dnf/* && \ ln -s /usr/bin/vim /usr/bin/vi &&\ mkdir /var/run &&\ touch /var/run/passwd &&\ useradd gaussdb &&\ rm -rf /tmp/* &&\ echo "export GAUSSHOME=/opt/gaussdb">>/home/gaussdb/.bash_profile &&\ echo "export PATH=\$GAUSSHOME/bin:\$PATH">>/home/gaussdb/.bash_profile &&\ echo "export LD_LIBRARY_PATH=\$GAUSSHOME/lib:\$LD_LIBRARY_PATH">>/home/gaussdb/.bash_profile &&\ echo "export PGDATA=\$GAUSSHOME/data">>/home/gaussdb/.bash_profile &&\ echo "export PGDATABASE=postgres">>/home/gaussdb/.bash_profile &&\ echo "export GAUSSLOG=\$GAUSSHOME/log">>/home/gaussdb/.bash_profile ENTRYPOINT ["/opt/gaussdb/entrypoint.sh"] EXPOSE 5432 CMD ["gaussdb"]

dockerfile的编写是控制镜像大小的关键,由于docker镜像每个命令分层,可以还原出每层的文件,所以任何文件新增、删除、修改、甚至是改文件属性,都会使最后镜像的大小受影响。如非必要,千万不要在dockerfile里执行chmodchown这样的命令,因为这会导致被操作的文件占用大小翻倍。

启动脚本

启动脚本 entrypoint.sh 的工作流程:

  1. 先检查是否已存在解压后的数据库软件:
  • 如果未安装:释放GaussDB内核文件
  • 如果已安装:跳过安装
  1. 检查是否已经初始化过数据目录:
  • 如果未初始化: 初始化数据目录 → 修改数据库参数 → 创建一个管理员用户 → 重启数据库
  • 如果已经初始化:直接启动数据库
#!/bin/bash export OSEXEC="sudo -u gaussdb -i " export DBSET="$OSEXEC gs_guc set -D /opt/gaussdb/data" if [ -s "/opt/gaussdb/bin/gaussdb" ]; then BINARY_ALREADY_EXISTS='true' else chmod +x /opt/gaussdb/GaussDB-Kernel_506.0.0.SPC0100_Kylin_64bit.bin chown gaussdb: /opt/gaussdb -R $OSEXEC /bin/bash -c "cd /opt/gaussdb && ./GaussDB-Kernel_506.0.0.SPC0100_Kylin_64bit.bin && rm -rf GaussDB-Kernel_506.0.0.SPC0100_Kylin_64bit.bin" fi if [ -s "/opt/gaussdb/data/PG_VERSION" ]; then DATABASE_ALREADY_EXISTS='true' else $OSEXEC gs_initdb --pgdata=/opt/gaussdb/data --nodename=primary --pwpasswd=Gaussdb@123 --encoding=UTF-8 --locale=C $DBSET -c "a_format_dev_version='s6'" $DBSET -c "a_format_version='10c'" $DBSET -c "ai_watchdog_oom_other_used_memory_threshold=-1" $DBSET -c "ai_watchdog_oom_process_threshold=1" $DBSET -c "character_set_client='UTF8'" $DBSET -c "checkpoint_segments=1024" $DBSET -c "client_encoding='UTF8'" $DBSET -c "cursor_sharing=off" $DBSET -c "dcf_rep_append_thread_num=3" $DBSET -c "dcf_run_mode=1" $DBSET -c "effective_cache_size=160MB" $DBSET -c "enable_mergejoin=off" $DBSET -c "enable_nestloop=off" $DBSET -c "enable_slot_log=on" $DBSET -c "enable_thread_pool=on" $DBSET -c "explain_perf_mode='pretty'" $DBSET -c "extra_float_digits=3" $DBSET -c "gs_format_behavior_compat_options='sqrt_karatsuba'" $DBSET -c "instr_unique_sql_combination_options='in_clause,forbid_select_for_update'" $DBSET -c "instr_unique_sql_count=200000" $DBSET -c "listen_addresses='*'" $DBSET -c "local_bind_address='0.0.0.0'" $DBSET -c "log_line_prefix='%m %n %u %d %h %p %S %x %a %e'" $DBSET -c "log_min_duration_statement=100ms" $DBSET -c "log_timezone='Asia/Shanghai'" $DBSET -c "maintenance_work_mem=16MB" $DBSET -c "max_compile_packages=2000" $DBSET -c "max_concurrent_autonomous_transactions=1000" $DBSET -c "max_connections=3000" $DBSET -c "max_files_per_process=1024" $DBSET -c "max_process_memory=24GB" $DBSET -c "max_replication_slots=20" $DBSET -c "max_wal_senders=20" $DBSET -c "numa_distribute_mode='all'" $DBSET -c "password_effect_time=0" $DBSET -c "password_reuse_time=0" $DBSET -c "product_version='V2.0'" $DBSET -c "recovery_max_workers=4" $DBSET -c "recovery_time_target=0" $DBSET -c "session_timeout=0" $DBSET -c "sql_beta_feature='a_style_coerce,sel_semi_poisson, sel_expr_instr, rand_cost_opt, page_est_opt, param_path_opt'" $DBSET -c "ssl=off" $DBSET -c "ssl_ca_file=cacert.pem" $DBSET -c "standby_shared_buffers_fraction=1" $DBSET -c "system_view_version=1" $DBSET -c "thread_pool_attr='16,2,(nobind)'" $DBSET -c "vacuum_cost_delay=1" $DBSET -c "vacuum_cost_limit=1000" $DBSET -c "verify_log_buffers=16MB" $DBSET -c "wal_buffers=256MB" $DBSET -c "wal_keep_segments=128" $DBSET -c "work_mem=64MB" $DBSET -c "xloginsert_locks=16" $DBSET -c "password_encryption_type=1" $DBSET -c "password_lock_time=1" $DBSET -c "failed_login_attempts=100" $DBSET -c "wal_level='logical'" $DBSET -c "log_statement='ddl'" $DBSET -c "log_error_verbosity='verbose'" $DBSET -c "track_activity_query_size=40960" $DBSET -c "lockwait_timeout=0" $DBSET -c "update_lockwait_timeout=0" $DBSET -c "idle_in_transaction_timeout=0" $DBSET -c "behavior_compat_options='aformat_null_test,aformat_regexp_match,allow_procedure_compile_check,bind_procedure_searchpath,compat_cursor,convert_string_digit_to_numeric,correct_to_number,current_sysdate,display_leading_zero,dynamic_sql_compat,enable_bpcharlikebpchar_compare,enable_case_when_alias,enable_crosstype_integer_operator,enable_ora_joinop_in_updatestmt,enable_use_ora_timestamptz,end_month_calculate,forbid_package_function_with_prefix,forbid_skip_tableof_empty_str_elem,forbid_update_multi_same_tables,plsql_rollback_keep_user,plsql_security_definer,plstmt_implicit_savepoint,proc_implicit_for_loop_variable,proc_outparam_override,proc_outparam_transfer_length,rownum_type_compat,show_full_error_lineno,sys_function_without_brackets,tableof_elem_constraints,time_constexpr_compact,truncate_numeric_tail_zero,unbind_divide_bound,varray_compat'" $DBSET -c "disable_keyword_options='datetime,regexp,rlike,zerofill,unit'" $DBSET -c "max_stack_depth=4MB" $DBSET -c "ddl_invalid_mode='invalid'" $DBSET -c "enable_force_create_obj=on" $DBSET -c "max_compile_functions=100000" $DBSET -c "max_recursive_times=1500" $DBSET -c "enable_recyclebin=on" $DBSET -c "undo_retention_time=900" $DBSET -c "audit_resource_policy=off" $DBSET -c "audit_file_remain_time=180" $DBSET -c "log_directory='/opt/gaussdb/log/pg_log/dn_6001'" $DBSET -c "audit_directory='/opt/gaussdb/log/pg_audit/dn_6001'" $DBSET -c "asp_log_directory='/opt/gaussdb/log/asp_data/dn_6001'" $DBSET -c "perf_directory='/opt/gaussdb/log/pg_perf/dn_6001'" $DBSET -c "query_log_directory='/opt/gaussdb/log/sql_monitor/dn_6001'" $DBSET -h "host all all 0.0.0.0/0 md5" $OSEXEC gs_ctl reload -D /opt/gaussdb/data $OSEXEC gs_ctl start -D /opt/gaussdb/data $OSEXEC gsql -d postgres -c "begin create user admin password 'Gaussdb@123' sysadmin monadmin; exception when others then null; end;" $OSEXEC gs_ctl stop -D /opt/gaussdb/data fi $OSEXEC gaussdb -D /opt/gaussdb/data

参数说明:这组参数大部分是参考了TPOPS推荐的参数,但根据实际项目需要修改了部分参数。注意 shared_buffers 没有配置,因为Docker环境往往内存比较小,建议根据实际环境进行修改。


🚀 执行构建

PS F:\GITEE\gaussdb506.0-docker> docker build -t gaussdb506.0:2 . [+] Building 20.7s (9/9) FINISHED docker:desktop-linux => [internal] load build definition from dockerfile 0.1s => => transferring dockerfile: 1.01kB 0.0s => WARN: FromAsCasing: 'as' and 'FROM' keywords' casing do not match (line 1) 0.1s => [internal] load metadata for docker.io/xudingjun3131/kylinv10:sp3-20230324 0.0s => [internal] load .dockerignore 0.0s => => transferring context: 2B 0.0s => CACHED [1/4] FROM docker.io/xudingjun3131/kylinv10:sp3-20230324 0.0s => [internal] load build context 3.2s => => transferring context: 111.17MB 3.2s => [2/4] COPY GaussDB-Kernel_506.0.0.SPC0100_Kylin_64bit.bin /opt/gaussdb/ 0.3s => [3/4] COPY entrypoint.sh /opt/gaussdb/ 0.1s => [4/4] RUN mkdir /opt/gaussdb/log &&mkdir /opt/gaussdb/data &&yum install libaio sudo -y &&yum clean all && dnf clean al 16.1s => exporting to image 0.7s => => exporting layers 0.6s => => writing image sha256:8fe043ded72154ffd233b1aa3bdec7ffa7cf44a3e3beee238b63469b68b1d181 0.0s => => naming to docker.io/library/gaussdb506.0:2 0.0s 1 warning found (use docker --debug to expand): - FromAsCasing: 'as' and 'FROM' keywords' casing do not match (line 1) View build details: docker-desktop://dashboard/build/desktop-linux/desktop-linux/9b8ukn96t8ogbb77mzbwn19l3 What's next: View a summary of image vulnerabilities and recommendations → docker scout quickview

这个warning可以忽略,原本是想用多阶段构建看能不能让镜像再缩小一点,就加了个标签,但后面发现效果不好,就没有使用多阶段构建。

📊 构建结果分析

如果不算基础镜像下载时间,构建只需要二十秒左右。

  • ZIP压缩后的镜像大小:308MB
  • 压缩前的镜像大小:732.88MB
    • 基础镜像:609MB
    • GaussDB内核:111MB
    • RUN命令产生的文件变化:约12MB(主要是执行yum命令引起的相关文件变化)
PS F:\GITEE\gaussdb506.0-docker> docker history gaussdb506.0:2
IMAGE          CREATED             CREATED BY                                       SIZE      COMMENT
8434929c5065   2 minutes ago       CMD ["gaussdb"]                                  0B        buildkit.dockerfile.v0
<missing>      2 minutes ago       EXPOSE map[5432/tcp:{}]                          0B        buildkit.dockerfile.v0
<missing>      2 minutes ago       ENTRYPOINT ["/opt/gaussdb/entrypoint.sh"]        0B        buildkit.dockerfile.v0
<missing>      2 minutes ago       RUN /bin/sh -c mkdir /opt/gaussdb/log &&mkdi…   17.6MB    buildkit.dockerfile.v0
<missing>      58 minutes ago      COPY entrypoint.sh /opt/gaussdb/ # buildkit      5.01kB    buildkit.dockerfile.v0
<missing>      About an hour ago   COPY GaussDB-Kernel_506.0.0.SPC0100_Kylin_64…   111MB     buildkit.dockerfile.v0
<missing>      21 months ago                                                        609MB     Imported from -PS F:\GITEE\gaussdb506.0-docker>

想要再大幅减少空间就需要从阉割基础镜像开始了,暂时没太大必要。这里先提供一个方案,用tpops里的docker-service\package\base_image\x86_64\base_image_gaussdb_x86_64.tar作为基础镜像,然后提取对应HCE系统版本的GaussDB内核再来构建,估计压缩前的镜像大小能缩小到444MB ,zip压完估计到200MB以内了。


▶️ 启动容器

PS F:\GITEE\gaussdb506.0-docker> docker run --name gaussdb506.0_1 -d -p 8000:5432 gaussdb506.0:2 6fa7ff2a2ecdab48c0b568dae369eb4b1e1878936af1b190caeab5ab2c8c0a68

注意:初次启动需要一些时间进行初始化,后续启动就很快了。


🔗 连接测试

内部连接

PS F:\GITEE\gaussdb506.0-docker> docker exec -it gaussdb506.0_1 /bin/bash [root@7e63c063a43c /]# su - gaussdb [gaussdb@7e63c063a43c ~]$ gsql -r gsql ((GaussDB Kernel 506.0.0.SPC0100 build e324981f) compiled at 2025-04-27 14:27:52 last mr 23420 release) Non-SSL connection (SSL connection is recommended when requiring high-security) Type "help" for help. gaussdb=# \q [gaussdb@7e63c063a43c ~]$ gsql -r -d postgres -U admin -WGaussdb@123 -h 127.0.0.1 -p 5432 gsql ((GaussDB Kernel 506.0.0.SPC0100 build e324981f) compiled at 2025-04-27 14:27:52 last mr 23420 release) Non-SSL connection (SSL connection is recommended when requiring high-security) Type "help" for help. gaussdb=> \q [gaussdb@7e63c063a43c ~]$

外部连接

[Ruby@gaussdb-dn1 ~]$ gsql -r -d postgres -U admin -WGaussdb@123 -h 192.168.163.227 -p 8000 gsql ((GaussDB Kernel 506.0.0.SPC0100 build e324981f) compiled at 2025-04-27 14:27:52 last mr 23420 release) Non-SSL connection (SSL connection is recommended when requiring high-security) Type "help" for help. gaussdb=> select version(); version --------------------------------------------------------------------------------------------------------------- gaussdb (GaussDB Kernel 506.0.0.SPC0100 build e324981f) compiled at 2025-04-27 14:27:52 last mr 23420 release (1 row) gaussdb=>

💾 关于数据目录持久化

容器内的数据目录在 /opt/gaussdb/data,可以在创建容器的时候映射到本地目录:

PS F:\GITEE\gaussdb506.0-docker> docker run --name gaussdb506.0_1 -d -p 8000:5432 -v .\data:/opt/gaussdb/data gaussdb506.0:2 0ffa152c266e4b6a1fa2d6e780228edacfde44acfaac14f51fd292aa7354bbeb

注意:映射数据目录会让首次启动速度慢很多。


📂 开源

相关代码已开源,后续优化会在开源仓里更新:

开源地址:https://gitee.com/darkathena/gaussdb-docker


⚠️ 免责声明

声明:该方案非华为官方提供,使用该方案出现的任何问题,使用者自行承担,本人和华为公司均不承担任何责任。

「喜欢这篇文章,您的关注和赞赏是给作者最好的鼓励」
关注作者
【版权声明】本文为墨天轮用户原创内容,转载时必须标注文章的来源(墨天轮),文章链接,文章作者等基本信息,否则作者和墨天轮有权追究责任。如果您发现墨天轮中有涉嫌抄袭或者侵权的内容,欢迎发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论