专栏首页jeremy的技术点滴分发JavaWeb项目之docker方案

分发JavaWeb项目之docker方案

最近做了个小的Java Web脚手架工程。工程项目虽小,但算是一个很典型的Java Web项目,依赖于数据库,Java写的后端代码,JavaScript写的前端代码。本来写了一个说明,告诉用户如何将这个工程跑起来,很自然想到有好几步:

  • 安装前后端编译工具
  • 安装数据库,并初始化数据库结构
  • 根据数据库的具体信息,修改项目中的配置文件
  • 编译前端代码
  • 编译后端代码,最终形成war包
  • 将war包部署至应用服务器

想了下,真的好麻烦。突然想到可以使用docker简化应用的分发,于是有了以下尝试,这里记录一下。

改造工程

原来加载mysql连接信息配置文件的方式改造了一下,以适应在docker引擎中引用mysql。

db.xml

...
<bean id="propertyConfigurer" class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
    <property name="locations">
        <list>
            <value>classpath:jdbc.properties</value>
            <value>classpath:env.properties</value>
            <value>file:///external/env_overwrite.properties</value>
        </list>
    </property>
    <property name="ignoreResourceNotFound" value="true" />
    <property name="searchSystemEnvironment" value="true" />
    <property name="systemPropertiesModeName" value="SYSTEM_PROPERTIES_MODE_OVERRIDE" />
</bean>
...

jdbc.properties

jdbc_url=jdbc:mysql://${MYSQL_PORT_3306_TCP_ADDR}:${MYSQL_PORT_3306_TCP_PORT}/${MYSQL_ENV_MYSQL_DATABASE}?useUnicode=true
jdbc_user=root
jdbc_password=${MYSQL_ENV_MYSQL_ROOT_PASSWORD}
jdbc_driverClass=com.mysql.jdbc.Driver

env.properties

MYSQL_PORT_3306_TCP_ADDR=127.0.0.1
MYSQL_PORT_3306_TCP_PORT=3306
MYSQL_ENV_MYSQL_DATABASE=ssm-db
MYSQL_ENV_MYSQL_ROOT_PASSWORD=123456

这里设置systemPropertiesModeName属性为SYSTEM_PROPERTIES_MODE_OVERRIDE,这样在解析一个占位符的时候,会先用系统属性来尝试,如果系统属性里没有才会用env.properties文件里定义的。

docker相关配置

项目下新建了dockerfiles目录,该目录下有一个docker-compose.yml文件,另外一个initdb目录下放数据库初始化脚本, 一个wars目录下放项目最后打的war包。

proj
  - dockerfiles
    - initdb
      - initdb.sql
    - wars
      - proj.war
    - docker-compose.yml
  - src
    - main
      - frontend
      - java
      - resources
      - webapp
  - pom.xml

docker-compose.yml

version: '2'

services:

ssm-mysql:

image: 'mysql'

volumes:

- ./initdb:/docker-entrypoint-initdb.d

environment:

- MYSQL_DATABASE=ssm-db

- MYSQL_ROOT_PASSWORD=123456

ssm-web:

image: 'jetty:9-alpine'

depends_on:

- ssm-mysql

links:

- ssm-mysql

volumes:

- ./wars:/var/lib/jetty/webapps

ports:

- "8080:8080"

environment:

- MYSQL_PORT_3306_TCP_ADDR=ssm-mysql

- MYSQL_PORT_3306_TCP_PORT=3306

- MYSQL_ENV_MYSQL_DATABASE=ssm-db

- MYSQL_ENV_MYSQL_ROOT_PASSWORD=123456

docker-compose.yml文件里定义了两个docker service, ssm-mysql是数据库服务,ssm-web是Web容器服务。

这里遇到了一坑,本来一个容器link另一个容器时,会从另一个容器得到一些环境变量,所以ssm-web服务的环境变量声明原本是不需要的,但去掉之后发现ssm-web服务跑不起来,好像是根本没有读到原本应该得到的环境变量。查了下原因,最后原因如下:

links with environment variables: As documented in the environment variables reference, environment variables created by links have been deprecated for some time. In the new Docker network system, they have been removed. You should either connect directly to the appropriate hostname or set the relevant environment variable yourself, using the link hostname:

web:
  links:
    - db
  environment:
    - DB_PORT=tcp://db:5432

看来以后还是不能依赖于links带来的变量。

改造pom.xml文件

最后稍微改造了下pom.xml文件

pom.xml

...
<!-- 打war包前安装npm依赖及编译前端代码 -->
<plugin>
    <groupId>org.codehaus.mojo</groupId>
    <artifactId>exec-maven-plugin</artifactId>
    <version>1.3.2</version>
    <executions>
        <execution>
            <id>install_npm_dependences</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>exec</goal>
            </goals>
            <configuration>
                <executable>yarn</executable>
                <workingDirectory>src/main/frontend</workingDirectory>
            </configuration>
        </execution>
        <execution>
            <id>build_frontend</id>
            <phase>prepare-package</phase>
            <goals>
                <goal>exec</goal>
            </goals>
            <configuration>
                <executable>npm</executable>
                <workingDirectory>src/main/frontend</workingDirectory>
                <arguments>
                    <argument>run</argument>
                    <argument>build</argument>
                </arguments>
            </configuration>
        </execution>
    </executions>
</plugin>

<!-- 将编译后的前端代码也打入war包 -->
<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-war-plugin</artifactId>
    <version>3.0.0</version>
    <configuration>
        <webResources>
            <resource>
                <!-- this is relative to the pom.xml directory -->
                <directory>src/main/frontend_react/build</directory>
                <!-- the default value is ** -->
                <includes>
                    <include>**/*</include>
                </includes>
                <!-- there's no default value for this -->
                <excludes>
                    <exclude>asset-manifest.json</exclude>
                    <exclude>**/*.css.map</exclude>
                    <exclude>**/*.js.map</exclude>
                </excludes>
            </resource>
        </webResources>
    </configuration>
</plugin>

<!-- 将最后打出的war包拷贝至dockerfiles/wars目录 -->
<plugin>
    <artifactId>maven-antrun-plugin</artifactId>
    <version>1.8</version>
    <executions>
        <execution>
            <phase>package</phase>
            <configuration>
                <target>
                    <copy file="${basedir}/target/${project.artifactId}.war" tofile="${basedir}/dockerfiles/wars/${project.artifactId}.war" />
                </target>
            </configuration>
            <goals>
                <goal>run</goal>
            </goals>
        </execution>
    </executions>
</plugin>
...

总结

像上述这样改造后,分发项目就变得很简单了。

  • 在工程根目录下执行mvn package完成war的构建
  • dockerfiles目录下执行docker-compose up
  • 使用浏览器访问http://${docker_host_ip}:8080

进一步想,其实很多依赖组件较多的项目都可以考虑这样分发。记得以前做的一个项目依赖了mysql, mongodb, redis, mq, zookeeper,当时每个新加入团队的成员至少要花大半天来搭建开发环境,如果工程这样组织的话,一个新人就能很快将项目运行起来。

本工程源码地址:http://git.oschina.net/jeremy-xu/ssm-scaffold

参考

http://javablog.blog.163.com/blog/static/20971116420127109200710/ https://docs.docker.com/compose/compose-file/ https://yeasy.gitbooks.io/docker_practice/content/compose/install.html https://hub.docker.com/_/mysql/ https://hub.docker.com/_/jetty/

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • kubernetes中部署mysql高可用集群

    很多软件后端使用的存储都是mysql,当这些软件系统在生产环境部署时,都会面临一个严峻问题,需要在生产环境中部署一个高可用的mysql集群服务。刚好在最近一周的...

    jeremyxu
  • 保存mysql InnoDB的auto_increment值另类方案

    jeremyxu
  • 使用docker in docker

    工作中需要在容器里操作docker镜像,而且又不想污染宿主机上的docker镜像,找到了docker in docker(dind)的方案,这里记录一下。

    jeremyxu
  • mysql使用基础 sql语句(一)

    命令行输入mysql -u root -p,回车再输入密码,进入mysql。 终端命令以分号作为一条语句的结束,可分为多行输入,只需在最后加上分号即可。如下图:...

    欠扁的小篮子
  • php 学习笔记之搭建开发环境(mac版) 原

    下面我们将搭建最简单的 php 开发环境,每一步都会验证上一步的操作结构,请一步一步跟我一起搭建吧!

    雪之梦技术驿站
  • vs2015连接mysql数据库准备步骤以及相关错误

    数据库下载地址https://downloads.mysql.com/archives/community/

    花狗Fdog
  • MySQL的安装步骤

    MySQL5.6.43下载地址:链接: https://pan.baidu.com/s/140YxXOMwNh5EkzMb9wcHhg 提取码: 2333

    GhostCN_Z
  • mysql_install_db初始化数据库失败的解决方案

    用户1456517
  • 小白学习MySQL - 数据库软件和初始化安装

    作为个人学习环境来说,搭建一套VMWare的环境,算是性价比最高的一种选择,当然你可以购买一些公有云服务器(有些则是免费的,例如Oracle Cloud,可参考...

    bisal
  • mysql 表的完整性约束

    郭楷丰

扫码关注云+社区

领取腾讯云代金券