入坑docker中部署oracle

入坑docker中部署oracle

文章目录

  • 入坑docker中部署oracle
    • 安装docker、docker-compose
    • 初始化swarm集群
    • 安装相关镜像
    • 坑在哪里?
      • 部署前docker-compose.yml文件
      • 定期给数据库备份
      • 还原数据
      • 常见的坑
    • 总结
    • 参照来源
    • 感谢

安装docker、docker-compose

  • 安装docker、docker-compose参照ubuntu安装docker、docker-compose教程

初始化swarm集群

  • 初始化swarm集群 docker swarm init入坑docker中部署oracle_第1张图片

  • 创建docker swarm overlay网络 docker network create --driver overlay unreal-network入坑docker中部署oracle_第2张图片

    准备工作完成了,下面开始部署oracle吧!!!

安装相关镜像

​ 这里以dockerhub上的truevoly/oracle-12c为例:

  • 下载镜像:docker pull truevoly/oracle-12c

  • 编辑docker-compose文件:

version: "3"
services:
  oracleDataBases:
    image: truevoly/oracle-12c  		#镜像  sath89/oracle-12c      #镜像
    volumes:         	 									#挂载   :前面的是本地的文件夹   表示: 容器内的文件夹挂载到本地的文件夹下面
      - /mnt/ora:/u01/app/oracle
      - /etc/localtime:/etc/localtime:ro
    ports:            											#端口映射
      - "1521:1521"
      - "9081:8080"
    environment:
      - DBCA_TOTAL_MEMORY=1024
    deploy:
      replicas: 1 											# replicas模式, 复制数目为1
      restart_policy:
        condition: on-failure
      placement:
        constraints: [node.role == manager]	 			# 部署位置,只在工作节点部署
    networks:
      - default

networks:
  default:
    external:
      name: unreal-network
  • 启动docker-compose.yml: docker stack deploy -c docker-compose-oracle.yml unreal

  • 查看容器运行情况docker service lsdocker ps
    入坑docker中部署oracle_第3张图片

  • 查看容器启动的日志 docker service logs -f unreal_oracleDataBases(这个过程时间有点长,耐心等待就可以了,直到看到最后一行的“Database ready to use. Enjoy! ?”,就表示部署完成了)
    入坑docker中部署oracle_第4张图片

  • 这样docker中的oracle就部署完毕了。打开数据库工具(这里是用的是JetBrains Toolbox中下载的DateGrip),按照docker-compose.yml文件中的信息编辑连接。

    1. 连接名可以按照自己工作的习惯命名; Name:@192.168.0.9。
    2. 备注信息可以按照自己的数据库用途进行相关描述,便于使用; Commen: 本地项目测试使用。
    3. 在常规信息中
    • 可以选择连接类型、驱动程序当然是Driver:。至于这里为什么是Connection type:SID,大概是由镜像决定的,具体怎么封装oracle镜像文件,还有待进一步学习。
    • 输入相对应的Host、Port、SID、Driver、User、Password以及密码是否永久保存的Save。
    • URL是在你输入过程中工具会自动生成。
      入坑docker中部署oracle_第5张图片

坑在哪里?

部署前docker-compose.yml文件

  • 这部分非常重要:
  1. 首先部署的service name 一定要起一个跟自己服务相关的名字,便于后期的使用。
  2. 挂载目录非常有必要,这样可以预防容器重启带来的数据库信息丢失的风险,这里的数据库信息是指全部。
  3. 挂载目录必须是可读写权限,否则在数据库初始化的时候容器没有在预定的挂载目录中初始化环境的权限。

定期给数据库备份

  • 这个工作的重要性不用多说,最好能将部署容器时的所有文件都备份下来
  • 如果不能做到所有文件都保存,至少要将/u01/app/oracle/oradata/xe/中的文件及时备份,在实际的生产环境中可以把这些文件都挂载到一个安全系数比较高的存储机中。

还原数据

  • 其实只要把数据做好备份,只需要按照上面的步骤,将数据库重新建起来,恢复容器即可,按照oracle数据恢复的方法,将数据库文件灌到/u01/app/oracle/oradata/xe/中,再重新装载数据即可。可参照这篇Oracle数据库冷备份与恢复(救命稻草)文章。

常见的坑

  • 当你查看容器启动日志时你会发现如图报错信息。[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传入坑docker中部署oracle_第6张图片日志中提示的很清楚,DBCA Operation failed,Look at the log file "/u01/app/oracle/cfgtoollogs/dbca/xe/xe.log" for further details。打开对应挂载到本地的日志文件sudo cat /mnt/ora/cfgtoollogs/dbca/xe/xe.log发现问题所在,出现ORA-00821: Specified value of sga_target 768M is too small, needs to be at least 1160M,以及ORA-01078: failure in processing system parameters的错误,导致建库失败。入坑docker中部署oracle_第7张图片解决方式:找到挂载在本地的文件目录中的*.ora文件,我这里本地文件生成的目录是/mnt/ora/cfgtoollogs/dbca/xe/initxeTempOMF.ora,入坑docker中部署oracle_第8张图片打开文件后将日志中提示的sga_target的值,由768m修改到不小于1160m。然后删除容器docker service rm unreal_oracleDataBase,重启容器docker stack deploy -c docker-compose-oracle.yml unreal,再查看启动日志。发现日志没有什么变化,证明我们前面找到的文件路径并不正确。这里再重新给已经生成的文件给予sudo chmod -R 777 /mnt/ora/权限。

  • 容器启动过程实际上是按照容器中根目录下/entrypoint.sh脚本运行的,这里贴出来给大家参阅,希望能够提供相应的解决问题的灵感:

    #!/bin/bash
    set -e
    
    # Prevent owner issues on mounted folders, if desired
    if [ "$ENABLE_OWNERSHIP_FIX" = true ] ; then
    	chown -R oracle:dba /u01/app/oracle
    	chown -R oracle:dba /docker-entrypoint-initdb.d/
    fi
    
    rm -f /u01/app/oracle/product
    ln -s /u01/app/oracle-product /u01/app/oracle/product
    
    #Run Oracle root scripts
    /u01/app/oraInventory/orainstRoot.sh > /dev/null 2>&1
    echo | /u01/app/oracle/product/12.1.0/xe/root.sh > /dev/null 2>&1 || true
    
    if [ -z "$CHARACTER_SET" ]; then
    	if [ "${USE_UTF8_IF_CHARSET_EMPTY}" == "true" ]; then
    		export CHARACTER_SET="AL32UTF8"
    	fi
    fi
    
    if [ -n "$CHARACTER_SET" ]; then
    	export CHARSET_MOD="NLS_LANG=.$CHARACTER_SET"
    	export CHARSET_INIT="-characterSet $CHARACTER_SET"
    fi
    
    
    impdp () {
    	set +e
    	DUMP_FILE=$(basename "$1")
    	DUMP_NAME=${DUMP_FILE%.dmp} 
    	cat > /tmp/impdp.sql << EOL
    -- Impdp User
    CREATE USER IMPDP IDENTIFIED BY IMPDP;
    ALTER USER IMPDP ACCOUNT UNLOCK;
    GRANT dba TO IMPDP WITH ADMIN OPTION;
    -- New Scheme User
    create or replace directory IMPDP as '/docker-entrypoint-initdb.d';
    create tablespace $DUMP_NAME datafile '/u01/app/oracle/oradata/$DUMP_NAME.dbf' size 1000M autoextend on next 100M maxsize unlimited;
    create user $DUMP_NAME identified by $DUMP_NAME default tablespace $DUMP_NAME;
    alter user $DUMP_NAME quota unlimited on $DUMP_NAME;
    alter user $DUMP_NAME default role all;
    grant connect, resource to $DUMP_NAME;
    exit;
    EOL
    
    	su oracle -c "$CHARSET_MOD $ORACLE_HOME/bin/sqlplus -S / as sysdba @/tmp/impdp.sql"
    	su oracle -c "$CHARSET_MOD $ORACLE_HOME/bin/impdp IMPDP/IMPDP directory=IMPDP dumpfile=$DUMP_FILE $IMPDP_OPTIONS"
    	#Disable IMPDP user
    	echo -e 'ALTER USER IMPDP ACCOUNT LOCK;\nexit;' | su oracle -c "$CHARSET_MOD $ORACLE_HOME/bin/sqlplus -S / as sysdba"
    	set -e
    }
    
    case "$1" in
    	'')
    		#Check for mounted database files
    		if [ "$(ls -A /u01/app/oracle/oradata 2>/dev/null)" ]; then
    			echo "found files in /u01/app/oracle/oradata Using them instead of initial database"
    			echo "XE:$ORACLE_HOME:N" >> /etc/oratab
    			chown oracle:dba /etc/oratab
    			chmod 664 /etc/oratab
    			rm -rf /u01/app/oracle-product/12.1.0/xe/dbs
    			ln -s /u01/app/oracle/dbs /u01/app/oracle-product/12.1.0/xe/dbs
    			#Startup Database
    			su oracle -c "/u01/app/oracle/product/12.1.0/xe/bin/tnslsnr &"
    			su oracle -c 'echo startup\; | $ORACLE_HOME/bin/sqlplus -S / as sysdba'
    		else
    			echo "Database not initialized. Initializing database."
    			export IMPORT_FROM_VOLUME=true
    
    
    			#printf "Setting up:\nprocesses=$processes\nsessions=$sessions\ntransactions=$transactions\n"
    			set +e
    			mv /u01/app/oracle-product/12.1.0/xe/dbs /u01/app/oracle/dbs
    			set -e
    
    			ln -s /u01/app/oracle/dbs /u01/app/oracle-product/12.1.0/xe/dbs
    
    			echo "Starting tnslsnr"
    			su oracle -c "/u01/app/oracle/product/12.1.0/xe/bin/tnslsnr &"
    			#create DB for SID: xe
    			su oracle -c "$ORACLE_HOME/bin/dbca -silent -createDatabase -templateName General_Purpose.dbc -gdbname xe -sid xe -responseFile NO_VALUE $CHARSET_INIT -totalMemory $DBCA_TOTAL_MEMORY -emConfiguration LOCAL -pdbAdminPassword oracle -sysPassword oracle -systemPassword oracle"
    			
    			echo "Configuring Apex console"
    			cd $ORACLE_HOME/apex
    			su oracle -c 'echo -e "0Racle$\n8080" | $ORACLE_HOME/bin/sqlplus -S / as sysdba @apxconf > /dev/null'
    			su oracle -c 'echo -e "${ORACLE_HOME}\n\n" | $ORACLE_HOME/bin/sqlplus -S / as sysdba @apex_epg_config_core.sql > /dev/null'
    			su oracle -c 'echo -e "ALTER USER ANONYMOUS ACCOUNT UNLOCK;" | $ORACLE_HOME/bin/sqlplus -S / as sysdba > /dev/null'
    			echo "Database initialized. Please visit http://#containeer:8080/em http://#containeer:8080/apex for extra configuration if needed"
    		fi
    
    		if [ $WEB_CONSOLE == "true" ]; then
    			echo 'Starting web management console'
    			su oracle -c 'echo EXEC DBMS_XDB.sethttpport\(8080\)\; | $ORACLE_HOME/bin/sqlplus -S / as sysdba'
    		else
    			echo 'Disabling web management console'
    			su oracle -c 'echo EXEC DBMS_XDB.sethttpport\(0\)\; | $ORACLE_HOME/bin/sqlplus -S / as sysdba'
    		fi
    
    		if [ $IMPORT_FROM_VOLUME ]; then
    			echo "Starting import from '/docker-entrypoint-initdb.d':"
    
    			for f in $(ls /docker-entrypoint-initdb.d/*); do
    				echo "found file $f"
    				case "$f" in
    					*.sh)     echo "[IMPORT] $0: running $f"; . "$f" ;;
    					*.sql)    echo "[IMPORT] $0: running $f"; echo "exit" | su oracle -c "$CHARSET_MOD $ORACLE_HOME/bin/sqlplus -S / as sysdba @$f"; echo ;;
    					*.dmp)    echo "[IMPORT] $0: running $f"; impdp $f ;;
    					*)        echo "[IMPORT] $0: ignoring $f" ;;
    				esac
    				echo
    			done
    
    			echo "Import finished"
    			echo
    		else
    			echo "[IMPORT] Not a first start, SKIPPING Import from Volume '/docker-entrypoint-initdb.d'"
    			echo "[IMPORT] If you want to enable import at any state - add 'IMPORT_FROM_VOLUME=true' variable"
    			echo
    		fi
    
    		echo "Database ready to use. Enjoy! ;)"
    
    		##
    		## Workaround for graceful shutdown.
    		##
    		while [ "$END" == '' ]; do
    			sleep 1
    			trap "su oracle -c 'echo shutdown immediate\; | $ORACLE_HOME/bin/sqlplus -S / as sysdba'" INT TERM
    		done
    		;;
    
    	*)
    		echo "Database is not configured. Please run '/entrypoint.sh' if needed."
    		exec "$@"
    		;;
    esac
    
  • 由于不同环境的服务器docker-compose.yml中的DBCA_TOTAL_MEMORY的值不同,sga_target的值的大小为DBCA_TOTAL_MEMORY的75%,这样设置的话,日志中提示需要1160M的时候只需要计算这DBCA_TOTAL_MEMORY的值即可,1160/0.75=1546.666666667m,但是我们的yml文件中写了1024,显然是不够的,所以这里把docker-compose.yml中的内容改为

        environment:
          - DBCA_TOTAL_MEMORY=2048
    

总结

​ 其实本人在写这篇帖子的之前,是因为本地测试环境的服务器需要重装系统,但是在备份原数据的时候,可能是因为服务器硬盘的问题,导致没有完成备份,但是当时也没有发现。直到系统重装结束之后,在解压原文件的时候出错,才意识到已经无法挽回,所幸只是本地的测试环境,最后只能重头再来。

​ 但是数据库文件在自己的电脑上备份过一份比较早的数据,只是在表结构,数据量上,都与当时丢失的数据库有些差别,但不影响使用,所以开始了数据恢复的踩坑之路。后来发现只要数据文件(也就是/u01/app/oracle/oradata/xe/中的****.data, ***.tmp文件)及时备份,那么数据恢复也就很简单了。相关的数据恢复在百度中搜索oracle数据库文件恢复,有很多,这里就不再多说了。

​ 这篇帖子的初衷是为了本人不再掉入相同的坑所做的记录,也是在无数次踩坑之后痛下决心做的记录,希望未来的学习中能够坚持。

参照来源

  • ubuntu安装docker、docker-compose教程
  • Oracle数据库冷备份与恢复(救命稻草)

感谢

后台达人 soslinken 和Linux达人 Builder_ming

你可能感兴趣的:(docker)