企业应用容器化改造方式 中提到了企业容器化改造的三种方式。其中最理想化的肯定是第三种,先微服务化改造,再容器化。不过这种方式改动较大,实现起来比较费时。一般会先通过第一步,先把应用做成容器大单体。因为后面要为公司内部写《云原生最佳实践》,所以这里就先弄一个简单的例子搞一个大单体的示例。这里就以 Cloud Foundry的Spring Music应用为例。

一、应用的简单使用

Spring Music是一个在Cloud Foundry上的使用数据库的样例应用,它使用Spring框架,基于Spring Boot开发。应用启动非常简单。

1. 环境准备

1yum -y install java-11-openjdk mariadb-server
2systemctl start mariadb

注意这里安装好mariadb后,不需配置密码。

2. Gradle编译和程序启用

Gradle是继Maven之后的新一代构建工具,它采用基于groovy的DSL语言作为脚本,相比传统构建工具通过XML来配置而言,最直观上的感受就是脚本更加的简洁、优雅。

1wget https://downloads.gradle-dn.com/distributions/gradle-7.4.2-bin.zip
2echo 'export PATH=$PATH:/opt/gradle-7.4.2/bin' > /etc/profile
3source /etc/profile
4
5git clone https://github.com/cloudfoundry-samples/spring-music
6gradlew clean assemble
7java -jar -Dspring.profiles.active=mysql build/libs/spring-music.jar

spring-music
spring-music

3. 其他

该程序支持的数据库不止一种:

1java -jar -Dspring.profiles.active=<profile> build/libs/spring-music.jar
2</profile>

where <profile> is one of the following values:

  • mysql
  • postgres
  • mongodb
  • redis

使用mongodb的命令如下:

1./mongod --fork --dbpath /opt/mongodata/ --logpath /opt/mongolog/mongod.log  --port 27017

注:spring-boot应用除了可以编译成直接jar包运行,也支持tomcat部署,如果需要tomcat部署,可以通过以下方式下载。

1wget https://github.com/garystafford/spring-music/raw/build-artifacts/spring-music.war

二、大单体容器化改造

程序准备,这里先把所有的程序准备在一个目录里,如下:

 1[root@ecs-82f5]/srv# ll
 2total 383720
 3drwxr-xr-x 10 root root      4096 Jun 14 00:09 apache-tomcat-8.5.79
 4-rw-r--r--  1 root root  10592120 May 16 23:49 apache-tomcat-8.5.79.tar.gz
 5-rw-r--r--  1 root root       503 Jun 14 22:37 Dockerfile
 6-rw-r--r--  1 root root       515 Jun 14 22:35 Dockerfile.bak
 7drwxr-xr-x  8   10  143      4096 Sep  6  2017 jdk1.8.0_151
 8-rw-r--r--  1 root root 189736377 Jan  9  2018 jdk-8u151-linux-x64.tar.gz
 9drwxr-xr-x  3 root root      4096 Jun 11 00:23 mongodb-linux-x86_64-3.6.23
10-rw-r--r--  1 root root 102958054 Mar 17  2021 mongodb-linux-x86_64-3.6.23.tgz
11-rw-r--r--  1 root root       467 Jun 14 00:39 nginx.conf
12drwxr-xr-x  7 root root      4096 Jun  9 01:33 spring-music
13-rw-r--r--  1 root root  61304062 Jun 14 05:20 spring-music-1.0.jar
14-rw-r--r--  1 root root  28298839 Jun 11 00:23 spring-music.war
15-rw-r--r--  1 root root       477 Jun 15 07:07 start.sh

编写Dockerfile内容:

 1FROM ubuntu:latest
 2COPY jdk1.8.0_151 /opt/jdk/
 3COPY spring-music-1.0.jar /opt/spring-music-1.0.jar
 4COPY start.sh /opt/start.sh
 5COPY mongodb-linux-x86_64-3.6.23/bin/mongod /opt/mongod
 6
 7ENV  JAVA_HOME=/opt/jdk
 8RUN apt-get update \
 9    && apt-get -y install nginx \
10    && rm -rf /var/lib/apt/lists/* \
11    && export JAVA_HOME \
12    && chmod +x  /opt/mongod \
13    && mkdir /opt/mongodata /opt/mongolog
14COPY nginx.conf /etc/nginx/nginx.conf
15EXPOSE 80
16#ENTRYPOINT ["bash"]
17ENTRYPOINT ["sh","/opt/start.sh"]

现网使用过程中,一般不会直接把java程序暴漏出去,需要通过nginx进行反向代理spring-music应用,nginx.conf内容如下:

 1[root@ecs-82f5]/srv# cat nginx.conf
 2worker_processes  1;
 3events {
 4    worker_connections  65535;
 5}
 6http {
 7    include       mime.types;
 8    default_type  application/octet-stream;
 9    sendfile        on;
10    keepalive_timeout  65;
11    server {
12        listen       80;
13        server_name  localhost;
14        location / {
15            proxy_pass   http://127.0.0.1:8080;
16        }
17        error_page   500 502 503 504  /50x.html;
18        location = /50x.html {
19            root   html;
20        }
21    }
22}

start.sh脚本内容如下:

 1[root@ecs-82f5]/srv# cat start.sh
 2#!/bin/bash
 3# -------------------------------
 4set -e
 5
 6#export JAVA_HOME=/opt/jdk
 7#export JRE_HOME=/opt/jdk/jre
 8#export CLASSPATH=.:$JAVA_HOME/lib:/dt.jar:$JAVA_HOME/lib/tools.jar
 9#source /etc/profile
10service nginx start
11/opt/mongod --fork --dbpath /opt/mongodata/ --logpath /opt/mongolog/mongod.log  --port 27017
12#/opt/jdk/bin/java -jar -Dspring.profiles.active=mysql /opt/spring-music-1.0.jar
13/opt/jdk/bin/java -jar -Dspring.profiles.active=mongodb /opt/spring-music-1.0.jar

通过docker build -t tag .编译出的结果如下:

1[root@ecs-82f5]/srv# docker images|grep testimage
2testimage                                              v1.0         f8cc56655f7a   32 hours ago   699MB
3swr.la-north-2.myhuaweicloud.com/test-swr/testimage    v1.0         f8cc56655f7a   32 hours ago   699MB

运行结果如下:

1[root@ecs-82f5]/srv# docker run -it -d testimage:v1.0 -p 80:80
26662e122003c239192b19835e553a136e907a6d300e01ec8dffffe8c3817fa3b
3[root@ecs-82f5]/srv# docker ps
4CONTAINER ID   IMAGE           COMMAND                  CREATED         STATUS         PORTS NAMES
56662e122003c   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