在 企业应用容器化改造方式 中提到了企业容器化改造的三种方式。其中最理想化的肯定是第三种,先微服务化改造,再容器化。不过这种方式改动较大,实现起来比较费时。一般会先通过第一步,先把应用做成容器大单体。因为后面要为公司内部写《云原生最佳实践》,所以这里就先弄一个简单的例子搞一个大单体的示例。这里就以 Cloud Foundry的Spring Music应用为例。
一、应用的简单使用
Spring Music是一个在Cloud Foundry上的使用数据库的样例应用,它使用Spring框架,基于Spring Boot开发。应用启动非常简单。
1. 环境准备
yum -y install java-11-openjdk mariadb-server
systemctl start mariadb
注意这里安装好mariadb后,不需配置密码。
2. Gradle编译和程序启用
Gradle是继Maven之后的新一代构建工具,它采用基于groovy的DSL语言作为脚本,相比传统构建工具通过XML来配置而言,最直观上的感受就是脚本更加的简洁、优雅。
wget https://downloads.gradle-dn.com/distributions/gradle-7.4.2-bin.zip
echo 'export PATH=$PATH:/opt/gradle-7.4.2/bin' > /etc/profile
source /etc/profile
git clone https://github.com/cloudfoundry-samples/spring-music
gradlew clean assemble
java -jar -Dspring.profiles.active=mysql build/libs/spring-music.jar
3. 其他
该程序支持的数据库不止一种:
java -jar -Dspring.profiles.active=<profile> build/libs/spring-music.jar
where <profile>
is one of the following values:
- mysql
- postgres
- mongodb
- redis
使用mongodb的命令如下:
./mongod --fork --dbpath /opt/mongodata/ --logpath /opt/mongolog/mongod.log --port 27017
注:spring-boot应用除了可以编译成直接jar包运行,也支持tomcat部署,如果需要tomcat部署,可以通过以下方式下载。
wget https://github.com/garystafford/spring-music/raw/build-artifacts/spring-music.war
二、大单体容器化改造
程序准备,这里先把所有的程序准备在一个目录里,如下:
[root@ecs-82f5]/srv# ll
total 383720
drwxr-xr-x 10 root root 4096 Jun 14 00:09 apache-tomcat-8.5.79
-rw-r--r-- 1 root root 10592120 May 16 23:49 apache-tomcat-8.5.79.tar.gz
-rw-r--r-- 1 root root 503 Jun 14 22:37 Dockerfile
-rw-r--r-- 1 root root 515 Jun 14 22:35 Dockerfile.bak
drwxr-xr-x 8 10 143 4096 Sep 6 2017 jdk1.8.0_151
-rw-r--r-- 1 root root 189736377 Jan 9 2018 jdk-8u151-linux-x64.tar.gz
drwxr-xr-x 3 root root 4096 Jun 11 00:23 mongodb-linux-x86_64-3.6.23
-rw-r--r-- 1 root root 102958054 Mar 17 2021 mongodb-linux-x86_64-3.6.23.tgz
-rw-r--r-- 1 root root 467 Jun 14 00:39 nginx.conf
drwxr-xr-x 7 root root 4096 Jun 9 01:33 spring-music
-rw-r--r-- 1 root root 61304062 Jun 14 05:20 spring-music-1.0.jar
-rw-r--r-- 1 root root 28298839 Jun 11 00:23 spring-music.war
-rw-r--r-- 1 root root 477 Jun 15 07:07 start.sh
编写Dockerfile内容:
FROM ubuntu:latest
COPY jdk1.8.0_151 /opt/jdk/
COPY spring-music-1.0.jar /opt/spring-music-1.0.jar
COPY start.sh /opt/start.sh
COPY mongodb-linux-x86_64-3.6.23/bin/mongod /opt/mongod
ENV JAVA_HOME=/opt/jdk
RUN apt-get update \
&& apt-get -y install nginx \
&& rm -rf /var/lib/apt/lists/* \
&& export JAVA_HOME \
&& chmod +x /opt/mongod \
&& mkdir /opt/mongodata /opt/mongolog
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
#ENTRYPOINT ["bash"]
ENTRYPOINT ["sh","/opt/start.sh"]
现网使用过程中,一般不会直接把java程序暴漏出去,需要通过nginx进行反向代理spring-music应用,nginx.conf内容如下:
[root@ecs-82f5]/srv# cat nginx.conf
worker_processes 1;
events {
worker_connections 65535;
}
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
server {
listen 80;
server_name localhost;
location / {
proxy_pass http://127.0.0.1:8080;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}
}
}
start.sh脚本内容如下:
[root@ecs-82f5]/srv# cat start.sh
#!/bin/bash
# -------------------------------
set -e
#export JAVA_HOME=/opt/jdk
#export JRE_HOME=/opt/jdk/jre
#export CLASSPATH=.:$JAVA_HOME/lib:/dt.jar:$JAVA_HOME/lib/tools.jar
#source /etc/profile
service nginx start
/opt/mongod --fork --dbpath /opt/mongodata/ --logpath /opt/mongolog/mongod.log --port 27017
#/opt/jdk/bin/java -jar -Dspring.profiles.active=mysql /opt/spring-music-1.0.jar
/opt/jdk/bin/java -jar -Dspring.profiles.active=mongodb /opt/spring-music-1.0.jar
通过docker build -t tag .
编译出的结果如下:
[root@ecs-82f5]/srv# docker images|grep testimage
testimage v1.0 f8cc56655f7a 32 hours ago 699MB
swr.la-north-2.myhuaweicloud.com/test-swr/testimage v1.0 f8cc56655f7a 32 hours ago 699MB
运行结果如下:
[root@ecs-82f5]/srv# docker run -it -d testimage:v1.0 -p 80:80
6662e122003c239192b19835e553a136e907a6d300e01ec8dffffe8c3817fa3b
[root@ecs-82f5]/srv# docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
6662e122003c testimage:v1.0 "sh /opt/start.sh -p…" 4 seconds ago Up 3 seconds 80/tcp trusting_lalande
三、组件容器化
这个示例里大单体实际上是比组件化难,因为这里如果按组件拆分会更简单,因为nginx、mongodb(或mariadb)都是现成的,只有spring-music才需要单独容器化操作。
组件化的拆分也可以参考AWS SA GARY STAFFORD的文章:Spring Music Revisited: Java-Spring-MongoDB Web App with Docker 1.12