月泉的博客

也许是“新时代的开发姿势”

月泉 DockerJava姿势分享

在写博客的同时也录制了视频,视频和文章结合食用效果更佳

Bilibili: https://www.bilibili.com/video/av47825907

油管:https://www.youtube.com/watch?v=2o3CsiSbnV0&list=PLfQ4vem9sCASf5iePYCIOEqycobbWSVic

缘起

大概是在2~3年前,当时我在一家小型互联网创业公司,身处于技术氛围很不错的技术团队中,我们使用 Rails 来构建产品,整个产品是一个单体架构,但随着业务的变更与增长,我们在开发过程中所依赖的服务越来越多,毕竟不是每一家公司都有条件给予开发团队一个共享的开发环境,导致我们在开发的时候需要启动很多服务,在团队加入新人时,也需要告知新人应安装什么和启动什么,当自己电脑环境重装是也需要重复以上步骤,重复且很繁琐又易导致团队开发环境不统一。

最早期我们开发只需要启动 ServerPostgresqlRedis,由于业务需求的原因,又需要使用到图形数据库,所以我们需要启动的服务又增加了一个,变成了 ServerPostgresqlRedisNeo4j,再然后新增了队列 Sidekiq;这意味着每个人的机器器也要安装这些服务。团队规模虽然不大,但每个人身上的职责很多,业务之间也偶而交叉;再者,无论是 Rails 还是 Neo4j 在那个时候社区都很活跃,新也很频繁,所以为了保证开改环境一致,每个人需要同步更新所有依赖。

除了上述问题,还存在一个问题——团队内每个人在开发过程中,所使用的系统平台不一致,有的小伙伴使用 Windows ,有的使用 MacOS,有一句说一句,Rails 在Windows下是真的不好玩,有一些环境也没有提供 Windows 版本,于是我尝试过使用虚拟机,效果不佳,然后我们又继续尝试使用了 Vargrant,虽然解决了平台的问题,但是是真的卡!那时候Docker也才出来没多久,火热的趋势还在增长,再过了不久佳哥把开发环境及生产环境给 Docker 化了,后续超哥和我也加入对开发环境的 Docker 配置进行了想法上的改进及后续的维护,这一操作完成以后从此无论团队是加入新人或是像我这种因为Mac硬盘小1-2个月就要格盘重装的男人都得到了一种“酣畅淋漓”的感觉。

那时候我就在思考 Java 我该如何做到开发容器化呢?于是当时试了试,实现了以后发觉有点蠢还不如不容器化直到上周在和超哥聊天的过程中得知下周IDEA要发布新版本了,特性上支持 Debug inside Docker,我们在此前也尝试过将Java容器化开发但效果不好,总而言之言而总之,超哥又在昨天告诉我 IDEA 新版本2019.1发布正式版了,于是我昨天晚上(2019年3月28号),琢磨了近一晚上,也算是探索出了一种 Java Docker 化的开发姿势。

按照以往的经验,我大致总结了我们团队之前解决的问题(包括不限于):

  • 平台不统一
  • 开发环境版本不一致
  • 每次开机需要重复的去启动一些服务
  • 新人安装环境通常需要半天至一天
  • 开发环境与本机环境的隔离

我提出的这种姿势我不知道能够解决多少和带来多少问题,还缺少一些岁月的考验;所以我在这里先斗胆以文章的方式分享我所探索的方式来起一个引子,诸君参考。

姿势

预备姿势

需自行准备

  1. 预先安装Docker
  2. 配置IDEA中的Docker链接,Setting->Docker

Windows Docker的 Expose daemon on tcp://localhost:2375 without TLS默认是关闭的,需要手动打开

就目前而言开发Web项目,最常见的2种方式就是使用 SpringBoot或是使用传统的 J2EESpringBootWeb默认依赖嵌入式容器启动,J2EE项目通常使用外置的Servlet容器启动。

  • SpringBoot 容器化开发姿势
  • 传统J2EE 容器化开发姿势

本文将会对这2种方式进行分享,来帮助大家达到一种触类旁通的效果

SpringBoot 容器化开发姿势

预备

首先准备一个项目

Maven配置如下:

<dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>
		<!-- 开发工具依赖,本文将会使用热部署,所以需要依赖 -->
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            <scope>runtime</scope>
        </dependency>
    </dependencies>

先启动项目,验证项目的正确性同时也取一个巧

容器化运行

项目运行无误,创建docker-compose.yml文件(ps: 这里我习惯用docker-compose,读者也可自行选择使用K8或者是Dockerfile)

version: '3.1'
services:
  jdk:
  	# 使用官方JDK镜像
    image: openjdk
    ports:
      #将宿主机的8080端口与容器的8080端口进行映射
      - 8080:8080
    volumes:
      #将IDEA的编译目录target映射值容器中的/app/路径下
      - ./target/:/app/
      #将本地的maven仓库映射至容器中的/repository路径下
      - C:\Users\yuequ\.m2\repository:/repository/
    command: [
              'java',
              '-Dfile.encoding=UTF-8',
              '-classpath',
              # 这一段是classpath,下文会告知如何以取巧的方式得知
              '.....................',
              'org.yuequan.springboot.docker.SpringBootWithDockerApplication'
  ]

关于项目运行时需要添加那些依赖可使用IDE取巧

寻找至-classpath后的参数

复制,然后将路径都替换成映射至容器内部的路径即可,这里需要注意的是WindowsLinux平台下的分隔符是不一样的,需要将;替换成:

接着创建一个docker运行来测试容器编排是否正确,项目是否能够在容器中正常运行

建议在启动前先添加一个maven的编译,其实这里可以扩展点非常多,熟悉前端的读者肯定这时候还会先编译一下sass或者是执行webpack等前端或者其它的编译任务参与,而这些任务大多都可以以watch的形式启动,无疑中将前后端的协作变得更加的灵活和方便

点击OK,然后保存,运行它

接着选择容器看下启动日志

接着可以访问http://localhost:8080访问一下

容器化调试

现在能够在容器内运行了,但是还存在一个问题,我如何对它进行调试呢?

首先停止容器

因为目前IDEA与容器的调试还存在一些BUG,所以每次以调试的形式启动时都需要将server的容器删除掉,这里我不用说大家应该也能明白其它的容器不用删这个道理吧(指有多个容器编排时,比如: PostgreSQLRedisKafka等等)。

配置一个Remote的运行来调试容器内的代码,注意这个特性是在IDEA2019.1以后才有的,否则只能使用传统的远程调试

同理,添加编译任务

选择配置然后保存

保存,将复制的那一段远程调试启动的参数添加至docker-compose.yml文件中

接着创建一个Action,并加以断点

接着点击启动

然后在下方有2个控制台,一个是Debug的一个是Docker

访问测试一下http://localhost:8080/hello

OK,调试也没有问题了,注意如果每次以Debug的重新启动时,需要将server容器给删除然后再启动,这里或许是一个BUG

热部署

当然在开发过程中热部署会给我们带来极大的便利性,还记得我在依赖中引入的devtools的依赖吗?有了它我们每次改动代码只需要利用IDEA的自动编译或者是手动的执行Build即可

传统J2EE容器化开发姿势

由于我个人精力有限最近事情也比较多,感兴趣的可以看视频了解传统J2EE容器化的开发姿势,文中不做过多的叙述。

传送门在此:

​ bilibili: https://www.bilibili.com/video/av47825907/?p=4

​ 油管:https://www.youtube.com/watch?v=3LdXgeymI-E&list=PLfQ4vem9sCASf5iePYCIOEqycobbWSVic&index=4

结束语

以上就是我使用IDEA进行Java容器化开发的探索成果,之后我也会分享一个完整开发-测试-上线的完整的编排流程。

我对容器化开发充满了畅想,我坚信它能够为我们开发或是上线运维都带来极大的便利性。

Emmmm………,多了的想法以后再补吧,夜深了,我该休息了。

月泉
伪文艺中二青年,热爱技术,热爱生活。