一、应用容器化的方法
应用容器化,常见的方法有三种:
以上三种方式:
第一种本地构建最常见,也比较简单,但效率太低。
第二种方式是通过CI构建。这种方式则是比较传统的方法。需要指出的:CI/CD的实现,与容器并无必然的联系。在容器火之前,很多客户也基于Jenkins和虚拟机实现了CD/CD。只是容器轻量级的优势,更容易实现CI/CD。
在红帽Openshift中,我们可以通过CI构建实现容器镜像。这种构建方式,实际上是在openshift中部署Jenkins Slave Pod,在Slave Pod实现构建。红帽提供四种Jenkins Slave Pod的镜像(根据应用开发语言的不同),有基于maven的,有基于nodejs的、基于.net的、也有基础镜像(使用者基于基础镜像进行构建)。
第三种方式是通过S2I的方式构建应用镜像。这种方式有第二种方式构建的优点(构建好的应用客户实现CI),并且比第二种方式效率更高、适用多种开发语言。
二、基于S2I的应用容器化的方法
接下来,我们展现通过六个步骤,实现S2I的方式构建一个tomcat容器应用镜像。
我们先看下图:
为了方便理解,我将整个过程分为六个步骤。
2. 选定base image
也就是说,我们选则一个最初的原始docker image。在基础镜像的选择上,也需要一些考量。比如:我可以选择一个docker.io上的tomcat 镜像直接用,也可以选择一个centos的docker image安装tomcat。
3. 编写S2I脚本。
S2I有四个脚本。在S2I脚本的编写中,我的经验是采取“反推法”。也就是应用镜像运行起来,到底需要assmble和run做什么,这两个脚本就应该怎么写。
在这个阶段,我们还需要书写Dockerfile,准备基于第二步选定的base image构建新的builder image。Dockerfile中需要定义S2I脚本的拷贝和执行,base image的名称、和应用相关的一些目录权限、用户和权限等。
4.生成builder image
5.选定源码库
6.根据选定的代码地址和builder image,构建应用镜像并部署。
接下来,我们按照这5个步骤,展开讨论。
第一步:安装S2I命令行工具:
我将S2I的命令行工具安装到一个RHEL上。安装方法如下:
#curl -L -O https://github.com/openshift/source-to-image/releases/download/v1.1.3/source-to-image-v1.1.3-ddb10f1-linux-386.tar.gz
#tar -xzvf source-to-image-v1.1.3-ddb10f1-linux-386.tar.gz
#mv {s2i,sti} /usr/bin/
#s2i version
查看版本:
第二步:选定base image
本实验的目的是:基于S2I构建一个tomcat容器应用镜像。
我们至少有两种方法:
1.选择docker.io上的tomcat镜像
2.选择centos的镜像,然后在dockerfile中指定安装tomcat
这两种方式,我都进行了尝试。从效果看,第二种更灵活。因为在一个centos的base image上,想装什么都可以;而在docker.io上,有一些linux的命令是没有的,如tar,这些命令在后面应用的安装过程中会用到。
经过权衡,base image选择 openshift/base-centos7。
第三步:. 编写S2I脚本并书写Docker file。
一个符合S2I/B2I的building image,在bin目录下,是需要包含如下四个脚本的:
1.assemble脚本:
这个脚本负责将外部代码库的代码下载到本地,并且进行编译打包。
The assemble script is responsible for building the application artifacts from source and placing them into the appropriate directories inside the image. The workflow for the assemble script
2 run脚本:
这个脚本负责运行assemble编译好的应用。
The run script is responsible for executing your application.
3 save-artifacts脚本
save-artifacts脚本负责将构建所需要的所有依赖包收集到一个tar文件中。save-artifacts的好处是可以加速构建的过程。
4 usage脚本
usage脚本是告诉使用者如果使用镜像。
在S2I的四个脚本中,通常我们只会用到assemble和run两个脚本。
实际上脚本的书写,和应用是关系很大的。
在本实验中:
请记住如下脚本中的"WAR's copied"输出,这在后文中将作为应用build成功的标志。
assemble 脚本的作用,就是将代码库的代码,拷贝到$CATALINA_HOME/webapps下去运行。$CATALINA_HOME变量在dockerfile中被指定成/tomcat
[root@master bin]# cat assemble
cp -Rf /tmp/src/. $CATALINA_HOME/webapps
echo "WAR's copied"
run脚本的作用,就是当build包的应用镜像部署成功以后,启动镜像中的tomcat应用。
[root@master bin]# cat run
${CATALINA_HOME}/bin/catalina.sh run
[root@master bin]# cat usage
#!/bin/bash -e
cat <<EOF
This is not an application image, please refer this documentation on using this image
https://github.com/debianmaster/openshift-s2i-example.git
EOF
[root@master bin]# cat save-artifacts
#curl -o $CATALINA_HOME/webapps/ROOT.war -O ${WAR_FILE_URL}
接下来,编写Dockerfile,该文件分为四大部分:
第一部分:指定base image并安装一些rpm:
第二部分:安装jdk和tomcat
第三部分:创建用户、目录,并将S2I的四个脚本拷贝到指定的目录:
第四步:生成builder image
生成builder image,image的名字叫tomcat8-jdk8。
#docker build -t tomcat8-jdk8 .
镜像构建步骤中,S2I的脚本会被拷贝过去:
镜像构建成功:
用镜像启动容器,确认一下这是我们想要的:
#docker run -it 6ad8c28d1079 /bin/bash
确认assemble和run两个脚本已经拷贝到docker image的指定目录:
截止到目前,builder image已经创建好了。
将这个镜像打tag,push到我实验环境的harbor镜像仓库中:
#docker tag tomcat8-jdk8 node.example.com:5443/david/tomcat8-jdk8
#docker push node.example.com:5443/david/tomcat8-jdk8
我们根据生成的builder image生成image stream ,tomcat8-jdk8davidwei
#oc import-image --from=node.example.com:5443/david/tomcat8-jdk8 tomcat8-jdk8davidwei -n openshift --scheduled=true --confirm
第五步:选定源码库
我们使用如下代码仓库的代码:
https://github.com/debianmaster/sample-binaries.git
这个代码是一个war包:
查看war包中的index.html:
查看hello.jsp中的代码:
第六步:根据选定的代码地址和builder image,构建应用镜像并部署
接下来,我们使用S2I的方式部署应用。
创建一个新的项目:
[root@master bin]# oc new-project redhat
指定builder image的image stream和代码的git地址:
# oc new-app tomcat8-jdk8davidwei~https://github.com/debianmaster/sample-binaries.git --name='tomcat8-jdk8-war'
上面命令的含义是:指定tomcat8-jdk8为builder image 的image stream,指定代码仓库为https://github.com/debianmaster/sample-binaries.git,生成名字为tomcat8-jdk8-war的应用。
查看bc pod:
查看build的过程:
在下图中最后一行 WAR's copied,这其实就是assemble脚本执行成功后的输出:
镜像构建成功以后,会先push到docker registry中:
然后会根据build成功的镜像,触发dc,也就是部署一个应用的容器:
应用部署完成以后,我们给它加一个route:
添加解析后,通过浏览器访问这个应用的地址,显示的内容就是第五步我们手工查看war包的内容,证明应用部署成功。
最后一步,我们根据刚部署成功的应用,生成一个template,以便后续S2I部署使用起来更方便:
[root@master bin]# oc export is,bc,dc,svc --as-template=tomcat8-jdk8 > ./david.yml
[root@master bin]# oc create -f ./david.yml
这样,后续我们部署这个应用的时候,可以直接用模板部署:
参考文档:
https://github.com/debianmaster/openshift-java-s2i-example