· 前言
为什么有这篇文章?工作很多年,一直都没有分享过工作中的积累和收获。前几年写过几篇博客,也早已辍笔。忽然发现工作中的很多东西,如果你不分享,自己也记不住,就拿这篇做个开始吧。
为什么选择简书?互联网时代,分享是主题,博客已落后于这个时代。
· 起因
前几天,部门有个客户交流,需要搭建一个演示系统,问同事要了一堆代码和数据库,数据库是oracle,发现要搭建个演示环境还挺复杂。想到用 docker 搭建个环境,上传到仓库中,用的时候 pull 下来,岂不方便?说干就干,殊不知中间N多陷阱,踩了不少坑,记录下来,免得走冤枉路。
· 准备环境
1. docker 环境
如果你不是在 Linux 中工作,那对不起,你需要一个虚拟机。无论是在Mac 还是在 Windows,你都可以用 Docker Toolbox 来搭建一个Docker环境,这不是本文的重点,请参考官方文档,docker 的参考手册在这里。
2. 阿里云镜像
docker.io 的镜像对于国内的同学来说实在是太慢了,你需要一个镜像站点,可以用阿里云,有淘宝账号就可以申请,免费,速度很快,这也不是本文的重点,请到 这里 查看你的资源库。
在镜像加速器中,你可以找到如何设置你自己的镜像加速器,这里就不再赘述了。
3. 下载基础镜像
如果一切从零开始,比如说安装oracle,那就比较复杂了,好在这个世界总是有些 “好事之徒” 。从阿里云上下载一个基础镜像吧:
可以在镜像搜索中,找到适合自己的镜像。
· 开始工作
启动镜像:
docker run -d --name oracle_11g --privileged=true -p 8080:8080 -p 1521:1521 registry.cn-hangzhou.aliyuncs.com/helowin/oracle_11g
我这个项目用到jdk 1.7 和 tomcat7, 先将需要的资源复制到容器中:
docker cp /Users/xxx/xxx.DMP oracle_11g:/tmp
docker cp /Users/xxx/jdk-7u71-linux-x64.rpm oracle_11g:/tmp/
docker cp /Users/xxx/apache-tomcat-7.0.85.tar.gz oracle_11g:/tmp/
docker cp /Users/xxx/xxx.war oracle_11g:/tmp
docker cp /Users/xxx/jta-1.1.jar oracle_11g:/tmp
进入容器:
docker exec -ti 容器ID /bin/bash
初始化环境变量:
source /home/oracle/.bash_profile
安装一些必要工具:
su #输入密码helowin
yum install tar
yum install vim
原有的jdk是1.6版本,升级为1.7:
rpm -qa|grep jdk
rpm -e --nodeps java-1.6.0-openjdk-1.6.0.0-6.1.13.4.el6_5.x86_64
rpm -ivh /tmp/jdk-7u71-linux-x64.rpm
java -version
解压安装 tomcat,并复制jta包(项目需要,非必须):
cp /tmp/apache-tomcat-7.0.85.tar.gz /usr/java/
cd /usr/java/
tar -zxvf apache-tomcat-7.0.85.tar.gz
cp /tmp/jta-1.1.jar /usr/java/apache-tomcat-7.0.85/lib/
修改虚拟机参数 $TOMCAT_HOME/bin/catalina.sh
vim /usr/java/apache-tomcat-7.0.85/bin/catalina.sh
在 cygwin=false 前增加,根据需要自行修改:
JAVA_OPTS="-Xms1024M -Xmx1024M -Xss512K -XX:PermSize=128M -XX:MaxPermSize=256M"
重点来了,这里曾经踩坑无数,翻来覆去做了几次,一直没有成功。oracle 的数据导入进去后,commit 镜像后重启,数据就丢了。。。经过反复研究才发现,在docker中,很多数据库都有这个问题。经过测试,在 oracle 安装目录下的 app/oracle/oradata 这个目录的数据,docker无法固化下来,因此要把这个目录的数据移动到其他目录才行。这个目录包含三类数据:控制文件、系统数据库文件和日志文件。下面分步骤讲解如何移动这三种文件。
1. 新建外部目录(root用户),用于保存这几类文件,几个子目录分别用于保存控制文件(ctl)、数据库文件和日志文件(oradata)、备份文件(bak):
mkdir /oracle
chown -R oracle:oinstall /oracle
exit //退出 root 用户
mkdir /oracle/ctl /oracle/oradata /oracle/bak
2. 修改控制文件
#dba登录, 设置输出格式,不然看不清, 查看当前数据文件位置和 spfile 的位置
sqlplus / as sysdba
col member format a80;
select name from v$controlfile;
show parameter spfile;
控制文件
NAME -------------------------------------------------------------------------------- home/oracle/app/oracle/oradata/helowin/control01.ctl
/home/oracle/app/oracle/flash_recovery_area/helowin/control02.ctl
spfile
NAME TYPE VALUE ------------------------------------ ----------- ------------------------------ spfile string /home/oracle/app/oracle/produc t/11.2.0/dbhome_2/dbs/spfilehe lowin.ora
# pfile 是个二进制文件,不能修改,要从spfile建立一个pfile,再进行修改
create pfile from spfile; // 建立 pfile
shutdown immediate // 停止数据库
exit
# 然后将 control01 和 control02 复制到 /oracle/ctl 目录
mv /home/oracle/app/oracle/oradata/helowin/control01.ctl /oracle/ctl/
mv /home/oracle/app/oracle/flash_recovery_area/helowin/control02.ctl /oracle/ctl/
# 修改生成的 pfile
vim $ORACLE_HOME/dbs/inithelowin.ora
# 修改后使用 pfile 重启,并从pfile创建spfile,之后再重启,就ok了。
sqlplus / as sysdba
startup pfile=$ORACLE_HOME/dbs/inithelowin.ora
select name from v$controlfile;
create spfile from pfile;
shutdown immediate
startup
select name from v$controlfile;
控制文件修改完毕
NAME -------------------------------------------------------------------------------- /oracle/ctl/control01.ctl
/oracle/ctl/control02.ctl
3. 修改数据文件位置
#停机并重启
shutdown immediate
exit
#将所有数据文件复制到新目录下
mv /home/oracle/app/oracle/oradata/helowin/sysaux01.dbf /oracle/oradata/
mv /home/oracle/app/oracle/oradata/helowin/users01.dbf /oracle/oradata/
mv /home/oracle/app/oracle/oradata/helowin/example01.dbf /oracle/oradata/
mv /home/oracle/app/oracle/oradata/helowin/undotbs01.dbf /oracle/oradata/
mv /home/oracle/app/oracle/oradata/helowin/system01.dbf /oracle/oradata/
mv /home/oracle/app/oracle/oradata/helowin/temp01.dbf /oracle/oradata/
# 进入 sqlplus, 用 mount 模式启动,并修改数据文件的位置,再打开数据库
sqlplus / as sysdba
startup mount
alter database rename file '/home/oracle/app/oracle/oradata/helowin/sysaux01.dbf' to '/oracle/oradata/sysaux01.dbf';
alter database rename file '/home/oracle/app/oracle/oradata/helowin/users01.dbf' to '/oracle/oradata/users01.dbf';
alter database rename file '/home/oracle/app/oracle/oradata/helowin/example01.dbf' to '/oracle/oradata/example01.dbf';
alter database rename file '/home/oracle/app/oracle/oradata/helowin/undotbs01.dbf' to '/oracle/oradata/undotbs01.dbf';
alter database rename file '/home/oracle/app/oracle/oradata/helowin/system01.dbf' to '/oracle/oradata/system01.dbf';
alter database rename file '/home/oracle/app/oracle/oradata/helowin/temp01.dbf' to '/oracle/oradata/temp01.dbf';
alter database open;
select name from v$datafile;
数据文件已切换到新位置
NAME -------------------------------------------------------------------------------- /oracle/oradata/system01.dbf
/oracle/oradata/sysaux01.dbf
/oracle/oradata/undotbs01.dbf
/oracle/oradata/users01.dbf
/oracle/oradata/example01.dbf
4. 修改日志文件
修改日志文件比较复杂,先要创建几个日志文件,然后把当前激活的日志文件改到新的日志文件上,删除原有的日志文件,在新位置建立新的日志文件,然后再激活回来,基本上是这个逻辑。
select group#,members,bytes/1024/1024,status from v$log;
# 你看到的结果可能是这个样子,其中 1,2,3 是日志文件序号
GROUP# MEMBERS BYTES/1024/1024 STATUS ---------- ---------- ---------------
1 1 50 CURRENT
2 1 50 UNUSED
3 1 50 UNUSED
#新增日志文件
alter database add logfile group 4 ('/oracle/oradata/redo04.log') size 50M;
alter database add logfile group 5 ('/oracle/oradata/redo05.log') size 50M;
alter database add logfile group 6 ('/oracle/oradata/redo06.log') size 50M;
#添加完后
GROUP# MEMBERS BYTES/1024/1024 STATUS ---------- ---------- ----------------
1 1 50 CURRENT
2 1 50 UNUSED
3 1 50 UNUSED
4 1 50 UNUSED
5 1 50 UNUSED
6 1 50 UNUSED
#切换日志组,需要多次切换才可能将1,2,3设置为 inactive,inactive的可以删除
alter system switch logfile;
#调整成这个样子就可以切换了
GROUP# MEMBERS BYTES/1024/1024 STATUS ---------- ----------------
1 1 50 ACTIVE
2 1 50 ACTIVE
3 1 50 ACTIVE
4 1 50 ACTIVE
5 1 50 CURRENT
6 1 50 UNUSED
#保存修改 , 删除原有位置上的日志组
alter system checkpoint;
alter database drop logfile group 1;
alter database drop logfile group 2;
alter database drop logfile group 3;
exit
rm -rf /home/oracle/app/oracle/oradata/helowin/redo01.log
rm -rf /home/oracle/app/oracle/oradata/helowin/redo02.log
rm -rf /home/oracle/app/oracle/oradata/helowin/redo03.log
#增加新的日志组
sqlplus / as sysdba
alter database add logfile group 1 ('/oracle/oradata/redo01.log') size 50M;
alter database add logfile group 2 ('/oracle/oradata/redo02.log') size 50M;
alter database add logfile group 3 ('/oracle/oradata/redo03.log') size 50M;
# 继续调整,直到1号日志组为当前为止
alter system switch logfile;
#结果可能是
GROUP# MEMBERS BYTES/1024/1024 STATUS ---------- - ----------------
1 1 50 CURRENT
2 1 50 ACTIVE
3 1 50 ACTIVE
4 1 50 ACTIVE
5 1 50 ACTIVE
6 1 50 ACTIVE
#保存修改,大功告成
alter system checkpoint;
5. 修改字符集
默认的字符集是 UTF-8, 不幸的是我们的数据库用的的 GBK,因此要调整。注意,一定要在上面几个步骤完成后再做,不然就白做了。
#修改闪回设置,修改字符集
select userenv('language') from dual;
shutdown immediate;
startup mount;
alter system enable restricted session;
alter system set job_queue_processes=0;
alter system set aq_tm_processes=0;
alter database flashback off;
alter database open;
show parameter recovery;
alter system reset db_recovery_file_dest scope=spfile sid='*';
alter system reset db_recovery_file_dest_size scope=spfile sid='*';
alter database character set internal_use ZHS16GBK;
shutdown immediate
startup
exit
至此,oracle 设置完毕,接下来你就可以放心大胆的去恢复你的数据库,部署应用。最后,退出容器后不要忘了commit
docker commit -m "注释" 容器ID 你的镜像名:latest
如果你要提交到阿里云的私有仓库保存起来,可以先在阿里云上建立一个仓库,然后为你的镜像打个tag,再push,就ok了。
docker login --username=你的淘宝账号 registry.cn-hangzhou.aliyuncs.com
#输入密码
docker tag 你本机的镜像名:标签 registry.cn-hangzhou.aliyuncs.com/仓库名/镜像名:latest
docker push registry.cn-hangzhou.aliyuncs.com/仓库名/镜像名:latest
如果运行容器有乱码问题,可以这样启动
docker run -e LANG=zh_CN.utf8 -d --name 名称 --privileged=true -p 8080:8080 镜像名
· 总结
1. 工作中积累很重要。
2. 遇到困难不要轻易放弃。