使用Docker-compose 编排Maximo容器环境

  • Post author:
  • Post category:其他




使用Docker-compose 编排Maximo容器环境



1. 写在前面

​ 前期公司针对Maximo测试系统项目进行容器化改造有一段时间,迭代Weblogic镜像中增加了自动部署目录下的JAVA项目功能,解决了Java中文字库显示、JVM时区等问题。公司基于Weblogic带域的docker镜像也迭代到了V3.2的大版本。基本上Weblogic的镜像已经满足Maximo的生产环境使用。

​ 随着Maximo上开发的业务逐渐增多,关联的容器也逐渐增加。从原来单一的Weblogic+Oracle DB容器架构,变成了双Weblogic+Tomcat+Nginx+Oracle DB的架构。这就意味着原来搭建测试环境只用敲两个docker命令,变成了现在需要敲5个docker命令启动容器,每个Docker镜像还得使用Link命令进行关联。这就增加了单个容器镜像变更时,运维操作的复杂度。

​ 为了减少docker link命令的操作次数,规范Maximo容器环境的代码化,采用Docker-compose组件对Maximo容器环境进行编排。



2. 前期准备



2.1 Maximo业务组件拆解

​ 公司原有Maximo容器化的组件有Weblogic和Oracle,仅适合单体业务测试开发使用,并不适用于生产环境,如下图。

在这里插入图片描述

​ 原生的Maximo环境中采用的是WebSphere 集群+Apache组件组成。但WAS组件、WAS集群容器化难度较大,一方面Linux的WAS版本(JDK1.6)网络上并不好下载,另一方面WAS许多配置需要图形化操作,相比之下Weblogic可以使用WLTS工具在命令行下进行配置。此外公司Maximo正式系统业务中还有Tomcat业务,JDK版本与weblogic不同,若不采用容器化部署,需要另外部署一台含JDK1.7环境的虚拟机进行隔离。

在这里插入图片描述

​ 容器化Maximo采用Weblogic搭建集群,但若使用Weblogic原生的方式搭建集群,势必会增加容器镜像和网络的复杂度。最终采用Nginx+Weblogic搭建集群的方式进行生产环境的容器化编排,两个Weblogic节点,可以满足正式系统灰度发布更新。


在这里插入图片描述



2.2 业务组件版本

软件 版本
docker-ce >=17.05
docker-compose >=1.23.2
jdk 1.6
weblogic 11g
Oracle Database 11g
Oracle instantclient 10c
Weblogic镜像(自建) harbor.gdphdc.com/weblogic/wls-11g-jdk6:v3.0
Tomcat镜像(JDK7) tomcat:7
Oracle Database镜像(自建) harbor.gdphdc.com/oracle/oracle-11g:latest
Oracle instantclient镜像(自建) harbor.gdphdc.com/oracle/database-instantclient:10.2.0.5
Nginx镜像 nginx:stable



2.3 项目目录架构

── docker-compose-maximo						
│   ├── database								//数据库持久化目录
│   ├── dmp										//数据库dump文件存放目录
│   ├── init									//数据库初始化存放脚本目录
│   ├── doclinks								//数据库dump文件存放目录
│   ├── logs									//日志目录
│   ├── images									//项目镜像存放目录
│   ├── weblogic01								//Weblogic 节点1 APP目录
│   │ └── maximo.ear
│   ├── weblogic02								//Weblogic 节点2 APP目录
│   │ └── maximo.ear
│   ├── nginx									//Nginx配置目录
│   │ └── default.conf
│   └── tomcat									//Tomcat,巡点检适配项目
│     └── cxfservice.war
│   ├── docker-compose-without-oracle.yaml		//生产用docker-compose.yaml
│   ├── docker-compose.yaml						//测试用docker-compose.yaml
│   ├── clean.sh								//重置项目脚本
│   ├── export-images.sh						//导出镜像脚本
│   ├── import-images.sh						//导入镜像脚本,供无docker仓库环境使用
│   ├── import.sh								//同步生产数据库到测试环境脚本
│   ├── install.sh
│   ├── README.MD
│   ├── start.sh
│   ├── stop.sh




3. 再次重构Weblogic镜像



3.1 减小镜像体积

​ 在Maximo容器化初试的文章里,我曾经打造过一个Weblogic镜像,但是由于经验不足,Dockerfile写的不规范,最终导致生成的Weblogic镜像高达5G多,在pull 新镜像的时候时间非常的长,后来根据网上的文章了解,Docker AUFS的每一层用于保存镜像的上一版本和当前版本之间的差异。即使在Dockerfile进行了删除操作,上一层的文件仍然会占用空间,镜像拥有的层越多,最终的镜像就越大。

​ 起初优化镜像体积的方法通过&&合并命令来减少RUN语句、删除apt更新缓存等操作减少相关层。采用这种方法优化,Weblogic镜像从5G减少到了2.7G,但是效果依然不太理想。此时还有一部分没有必要存在于镜像的文件被包含到了镜像中。比如在安装Weblogic时,首先需要COPY Weblogic安装包到镜像中,形成一个层约600Mb,然后使用RUN命令进行安装,这又形成了一个大约为700Mb的镜像层,在这之后,无论怎么删除掉安装包,其600Mb安装包依然占据了镜像空间,这一部分无法使用&&合并来进行优化

​ 好在自从Docker 17.05.0-ce 开始Docker 官方提供了简便的多阶段构建 (

multi-stage

build) 方案,这就可以将jdk的环境,Weblogic安装的环境解耦,将安装完成后的二进制文件复制到最终的镜像中,从而减少安装的空间。

​ 此时优化过的Weblogic镜像,仅有900多M,加上全部的Windows字体文件、Weblogic域文件等层最终只有1.34G,空间足足少了一半有多,最终的dockerfile构建示意图如下。

在这里插入图片描述



3.2 自动部署项目脚本

​ Weblogic基础镜像编制完后,若直接做成镜像启动容器,还需要手动进入到:7001/console页面中对项目进行部署,部署的相关配置保存在容器文件系统当中。这样一来有个缺点,一旦容器被销毁,所有的部署配置将被清空,不利于运维。解决方案有两种:

  1. 在Dockerfile中ADD项目文件,并引用WLTS脚本将项目文件离线部署在weblogic域当中中。
  2. 将APP项目作为目录映射在docker外,使其持久化,在Dockerfile的ADD一个entrypoint脚本,每次启动容器时先调用脚本部署离线部署项目文件夹下的文件。再启动Weblogic

​ 两种方案各有利弊,方案1优点在于启动快,适用于项目直接以镜像的方式进行交付,但通用性较差。方案2通用性较好,但每次启动调用WTLS离线部署会占用容器启动时间。这里我们采用了方案2,编写一套启动脚本和WLST部署APP脚本。

entrypoint.sh

#!/bin/bash
echo $APP_NAME 
echo $APP_PKG_FILE
echo $APP_PKG_LOCATION

if [[ ! $APP_PKG_LOCATION ]] ; then
    echo "部署环境变量为空或不合法,跳过自动部署"
else 
    echo "启动离线部署"
    wlst.sh -skipWLSModuleScanning /u01/oracle/app-deploy.py
fi

startWebLogic.sh

app-deploy.py

import os

# Deployment Information 从环境变量中获取部署变量信息
# ==============================================

domainhome = os.environ.get('DOMAIN_HOME', '/u01/oracle/weblogic/user_projects/domains/base_domain/')
admin_name = os.environ.get('ADMIN_NAME', 'AdminServer')
appdir     = os.environ.get('APP_PKG_LOCATION', '/u01/app')

filetypes=[".jar",".war",".ear"]
files=os.listdir(appdir)


# Read Domain in Offline Mode 离线读取Weblogic域
# ==============================================
readDomain(domainhome)

# Create Application 部署APP
# ===============================================
cd('/')

for file in files:
    for types in filetypes:
        if os.path.splitext(file)[-1] == types:
            try:
                appname=file.rstrip(os.path.splitext(file)[-1])
                app = create(appname, 'AppDeployment')
                app.setSourcePath(appdir + '/' + file)
                app.setStagingMode('nostage')
                # Assign application to AdminServer
                # ================================
                assign('AppDeployment', appname, 'Target', admin_name)
                print(file,"Deploy Sucessed!")
                break
            except Exception:
                print(file,"Deploy failed!")
                break
            

# Update Domain, Close It, Exit
# ==========================
updateDomain()
closeDomain()
exit()



3.2 环境变量规划

​ 由于采用Docker-compose组件进行编排,可以先在Weblogic基础镜像中设置环境变量的默认值,后续再由不同的Docker-compose脚本传入Weblogic容器中。

1、不可变环境变量

​ 这部分不可变的环境变量如JAVA_HOME、CLASSPATH、BEA_HOME、DOMAIN_HOME等直接在Dockerfile内写入。

2、可变环境变量

​ 这部分可变的环境变量可以在Dockerfile内写入空值或默认值,也可以不写,但在实际的docker-compose文件中必须指定,如JVM启动参数USER_MEN_ARGS、以及3.2中提到的APP_PKG_LOCATION(APP包文件位置)



3.3 持久化数据规划

​ 持久化数据意味着这部分文件数据,不随着容器的生命周期结束而消失。这部分文件需要使用docker-compose映射到相关的目录,需要规划持久化数据有

  1. Weblogic 中相关的日志文件,用于故障排查这部分文件位于

    /u01/oracle/weblogic/user_projects/domains/base_domain/servers/AdminServer/logs/

  2. Weblogic 中APP部署目录,这部分文件位于

    /u01/app

  3. Maximo 中上传附件Doclinks的目录

    /u01/app/maximo/doclinks



4. Nginx容器配置



4.1 持久化数据规划

​ 为了方便调试,Nginx镜像采用官方镜像,并没有另外构建,默认配置文件default.conf映射在了容器外,方便日后拓展修改。同时,需要读取Weblogic中共享出来的doclinks的目录,作为下载服务器。



4.2 Doclinks文件下载服务器及负载均衡配置

​ Nginx在此项目有两个作用,第一是作为Apache的替代,作为doclinks附件的下载。另外一个作用则是作为Weblogic的前端负载均衡。这里有几个要注意的地方,由于官方Nginx镜像默认的编码没有设置,而Maximo中部分用户上传的文件名是采用中文命名。在Windows机器请求Url时不能命中,会显示404,需要增加相关编码配置。

...
server {
    listen       80;
    server_name  maximo;
    charset utf-8,gbk;
...

​ 在负载均衡的配置中,由于Maximo项目并没有第三方组件对Session进行存储,为了不让请求在多个节点跳跃(具体表现为Maximo会话超时,请重新登录),需要采用ip_hash的算法方式进行负载均衡,同时需要在应用weblogic.xml 中配置Session复制

<?xml version="1.0" encoding="GBK"?>
   <weblogic-web-app xmlns="http://www.bea.com/ns/weblogic/90">
   <session-descriptor>
   <persistent-store-type>replicated</persistent-store-type>
   <sharing-enabled>true</sharing-enabled>
   </session-descriptor>
</weblogic-web-app>



4.3 完整配置

#上游服务器设置,这里服务器应该采用docker-compose中的服务名而不是ip
upstream maximo {       
      server  weblogic01:7001;
      server  weblogic02:7001;
      ip_hash;
    }    
server {
    listen       80;
    server_name  maximo;
	#设置编码
    charset utf-8,gbk; 
	#文件下载服务器,转发/doclinks请求
    location /doclinks {
        root   /usr/share/nginx/html;
        index  index.html index.htm;
    }    
    #转发/maximo请求到weblogic
    location /maximo {
        proxy_pass   http://maximo;
        proxy_set_header    X-Real-IP  $remote_addr;
        proxy_set_header    Host       $host;
        proxy_set_header   X-Forwarded-For  $proxy_add_x_forwarded_for;
        proxy_buffer_size 4k;
        proxy_buffers 4 32k;
        proxy_busy_buffers_size 64k;
        proxy_temp_file_write_size 64k;
        proxy_max_temp_file_size 512m;        
    }

    error_page   500 502 503 504  /50x.html;
    location = /50x.html {
        root   /usr/share/nginx/html;
    }

}



5. Tomcat容器及数据库容器配置

​ 由于tomcat仅仅作为一个resultful风格的适配器,较为简单,除持久化webapps目录外没有额外配置,略。

​ Oracle 11g-ee的容器的构建参照了网上的项目,https://github.com/ufoscout/docker-oracle-11g ,此处略



6. Oracle数据库导出及脚本



6.1 Oracle工具镜像

​ 由于生产系统的Oracle数据库版本较低,为了方便开发人员导出数据库数据而不需要另外再安装Oracle,这里构造了一个Oracle导出工具的镜像。需要从网上下载oracle-instantclient-basic-10.2.0.5-1.x86_64.rpm,oracle-instantclient-devel-10.2.0.5-1.x86_64.rpm,oracle-instantclient-sqlplus-10.2.0.5-1.x86_64.rpm几个文件,并构建镜像,镜像脚本如下

From centos

COPY /install /install

WORKDIR /install

RUN rpm -ivh oracle-instantclient-basic-10.2.0.5-1.x86_64.rpm && \
    rpm -ivh oracle-instantclient-devel-10.2.0.5-1.x86_64.rpm && \
    rpm -ivh oracle-instantclient-sqlplus-10.2.0.5-1.x86_64.rpm && \
    echo /usr/lib/oracle/10.2.0.5/client64/lib > /etc/ld.so.conf.d/oracle-instantclient10.2.0.5.conf && ldconfig && \
    cp exp /usr/lib/oracle/10.2.0.5/client64/bin/exp && \
    cp imp /usr/lib/oracle/10.2.0.5/client64/bin/imp && chmod -R 775 /usr/lib/oracle/10.2.0.5/client64/bin/ && \
    mkdir -p /usr/lib/oracle/10.2.0.5/rdbms/mesg/ && \ 
    cp expus.msb /usr/lib/oracle/10.2.0.5/rdbms/mesg/expus.msb && \
    cp expus.msb /usr/lib/oracle/10.2.0.5/rdbms/mesg/impus.msb


ENV PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/lib/oracle/10.2.0.5/client64/bin
ENV ORACLE_HOME=/usr/lib/oracle/10.2.0.5/
ENV NLS_LANG='simplified chinese_china.ZHS16GBK'

CMD ['/bin/bash']



6.2 Oracle数据导入导出脚本

​ bash写的比较乱,将就着用,关键的数据已用【】替代

DATABASE=`docker ps |grep harbor.gdphdc.com/oracle/oracle-11g:latest | awk '{print $1}'`
echo "获取数据库容器名"
echo $DATABASE

echo "1.生产同步数据到dmp文件夹"
echo "2.导入数据(导入dmp文件夹下pheam.dmp phuser1.dmp)"
echo "3.导入Maximo工程文件"
echo "4.同步doclinks"
echo -n "请选择操作:"

read  num

if [[ $num =~ ^-?[1-4]+$ ]]; then
  if [[ $num = 2 ]]; then
    echo "-------导入数据------"
    docker exec -u root -it $DATABASE  bash -c "chown oracle:oracle -R /dumpfile";
    docker exec -u oracle -it $DATABASE  bash -c "imp maximo/maximo@localhost:1521/EE.oracle.docker  fromuser=【正式系统用户】 touser=【测试系统用户】 file=/dumpfile/pheam.dmp log=/dumpfile/pheam.imp.log"
    exit;
  fi
  
  if [[ $num = 1 ]]; then
    echo "------清空数据-------"
    echo "Oracle用户名:"
    read USERNAME
    echo "Oracle密码:"
    read PASSWORD
    echo "Oracle IP:"
    read IP
    echo "SID名称:"
    read SID
    echo "端口:"
    read PORT
    echo "链接: $USERNAME/$PASSWORD@$IP:$PORT/$SID"

#导出pheam
    docker run --rm  --privileged=true -v $PWD/dmp:/tmp  harbor.gdphdc.com/oracle/database-instantclient:10.2.0.5 \
    exp $USERNAME/$PASSWORD@$IP:$PORT/$SID file=/tmp/pheam.dmp log=/tmp/pheam.exp.log owner=pheam grants=Y indexes=Y compress=Y buffer=1064000 rows=Y

#导出phuser1
    docker run --rm  --privileged=true -v $PWD/dmp:/tmp  harbor.gdphdc.com/oracle/database-instantclient:10.2.0.5 \
    exp $USERNAME/$PASSWORD@$IP:$PORT/$SID file=/tmp/phuser1.dmp log=/tmp/phuser1.exp.log owner=phuser1 grants=Y indexes=Y compress=Y buffer=1064000 rows=Y
    exit;
  fi

  if [[ $num = 3 ]]; then
    echo "-----复制工程文件------"
    scp  -r root@【正式系统】:/docker-compose-maximo/maximo/MAXIMO.ear $PWD/maximo/MAXIMO.ear
    exit;
  fi

  if [[ $num = 4 ]]; then
    echo "-----复制文档文件------"
    rsync   -avP 【正式系统】:/docker-compose-maximo/doclinks $PWD/
    exit;
  fi

else
 echo "输入错误"
fi



7. 业务编排

​ 重点来了,使用docker-compose业务编排,要求在数据库启动后,weblogic才开始启动,同时,使用服务名,各个容器都可以访问对方



7.1 docker-compose安装及配置

yum install epel-release -y
yum install docker-compose -y



7.2 docker-compose.yaml

version: "3"
services:
##节点1
  weblogic01:
    image: harbor.gdphdc.com/weblogic/wls-11g-jdk6:v3.2
    ports:
      - "7001:7001"
      - "13400:13400"
    networks:
      - maximo
    environment: 
      -  "USER_MEM_ARGS=-Xms1024m -Xmx4096m -XX:MaxPermSize=512m"
      -  "JAVA_OPTIONS=$JAVA_OPTIONS  -Dfile.encoding=utf-8 "
      -  "APP_PKG_LOCATION=/u01/app"
    volumes:
      - ./weblogic01:/u01/app
      - ./logs/weblogic01:/u01/oracle/weblogic/user_projects/domains/base_domain/servers/AdminServer/logs/
      - ./doclinks:/u01/app/maximo/doclinks
    deploy:
      replicas: 1
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
    depends_on:
      - db

##节点2
  weblogic02:
    image: harbor.gdphdc.com/weblogic/wls-11g-jdk6:v3.2
    ports:
      - "7002:7001"
      - "13401:13400"
    networks:
      - maximo
    environment: 
      -  "USER_MEM_ARGS=-Xms1024m -Xmx4096m -XX:MaxPermSize=512m"
      -  "JAVA_OPTIONS=$JAVA_OPTIONS  -Dfile.encoding=utf-8 "
      -  "APP_PKG_LOCATION=/u01/app"
    volumes:
      - ./weblogic02:/u01/app
      - ./logs/weblogic02:/u01/oracle/user_projects/domains/base_domain/servers/AdminServer/logs/
      - ./doclinks:/u01/app/maximo/doclinks
    deploy:
      replicas: 1
      update_config:
        parallelism: 1
        delay: 10s
      restart_policy:
        condition: on-failure
    depends_on:
      - db


  nginx:
    image: nginx:stable
    environment:
      - "LANG=en_US.UTF-8"
    ports:
      - "80:80"
    volumes:
      - ./doclinks:/usr/share/nginx/html/doclinks:ro
      - ./nginx:/etc/nginx/conf.d:ro
    links:
      - weblogic01
      - weblogic02
    networks:
      - maximo

  tomcat:
    image: tomcat:7
    ports:
      - "8080:8080"
    networks:
      - maximo
    volumes:
      - ./tomcat:/usr/local/tomcat/webapps
      - ./doclinks:/doclinks
      - ./logs/tomcat:/usr/local/tomcat/logs
      - /etc/localtime:/etc/localtime:ro
    environment:
      - "JAVA_OPTS=$JAVA_OPTS -Dfile.encoding=UTF8  -Duser.timezone=GMT+08"
  db:
    image: harbor.gdphdc.com/oracle/oracle-11g:latest
    volumes:
      - ./database:/u01/app/oracle/
      - ./init:/docker-entrypoint-initdb.d/
      - ./dmp:/dumpfile
    networks:
      - maximo
    ports:
      - "1521:1521"
    environment:
      - "CHARACTER_SET=ZHS16GBK" 

networks:
  maximo:
    driver: overlay



8.环境基本操作



8.1 第一次启动

进入项目文件夹运行命令:

docker-compose up -d

或运行脚本

sh install.sh

启动后可以通过docker-compose logs命令查看日志或使用以下命令查看容器日志



8.2 停止

进入项目文件夹运行命令:

docker-compose stop

或运行脚本

sh stop.sh



8.3 启动

进入项目文件夹运行命令:

docker-compose start

或运行脚本

sh start.sh



8.4 清除

进入项目文件夹运行命令

docker-compose down

rm -rf database/*



9.导入数据



9.1 Oracle数据导入&初始化

数据库初始化的脚本位于 init/init.sql 该脚本在第一次启动数据库时被调用。

数据库导入导出脚本为import.sh

数据库导出文件位于dmp/文件夹下,导出文件为pheam.dmp phuser.dmp。

由于生产数据库的版本为Oracle 10g 版本较低,需要使用database-instantclient-10g的版本导出。可以调用import.sh 按照提示操作。将会在文件夹下生成pheam.dmp phuser.dmp两个文件,也可自行使用Oracle 10g的 imp exp工具进行导出后放置dmp/文件夹下,命名为pheam.dmp phuser.dmp



9.2 Maximo部署

maximo部署文件夹位于maximo/下,该文件夹在weblogic容器中映射目录为/u01/app/maximo/

将生产上的MAXIMO.ear文件夹拷贝至此,部署前需修改MAXIMO.ear/properties.jar/maximo.properties文件修改如下:

mxe.system.reguser=MAXREG
mxe.system.regpassword=maxreg
mxe.db.driver=oracle.jdbc.OracleDriver
#修改Oracle链接
mxe.db.url=jdbc:oracle:thin:@db:1521/EE.oracle.docker
mxe.encrypted=false
mxe.rmi.port=0
#修改Oracle数据库拥有者
mxe.db.schemaowner=maximo
mxe.adminuserid=MAXADMIN
mxe.adminuserloginid=maxadmin
#修改Oracle数据库账户
mxe.db.user=maximo
#修改Oracle数据库密码
mxe.db.password=maximo
mxe.registry.port=13400
mxe.name=MaximoServer
mxe.int.dfltuser=MXINTADM
maximo.int.dfltuserpassword=mxintadm
mxe.encrypted=false

启动环境,MAXIMO.ear自动部署并运行。



10.日志查看

整个docker-compose日志可使用docker-compose logs查看

实时查看各个容器日志

#查看数据库日志
docker logs -f docker-compose-maximo_db_1
#查看weblogic日志
docker logs -f  docker-compose-maximo_weblogic_1
#查看tomcat日志
docker logs -f  docker-compose-maximo_tomcat_1

查看从某一时刻开始的各个容器日志时可以使用docker logs –since 和 –until参数



11.镜像导入导出

镜像文件备份位于images/文件夹下

镜像导出,运行export-images.sh

镜像导入,运行import-images.sh



版权声明:本文为deerjoe原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。