关于自动化构建的总结(一)

197 阅读3分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第1天,点击查看活动详情


背景

  1. 拥有比较常见的项目交付工具链
    • Gitlab
    • Maven
    • Jenkins
    • Docker
  2. 公司最近启动一个不大不小的项目
    • 大在 项目场景是实现 数据收集关联
    • 小在 只有我一个人进行开发
  3. 原有构建流程人为操作节点过多
    • 代码更新
    • 人为合并
    • 点击构建
    • 重启发布
  4. 我懒 减少人为干预项目交付节点,减少风险

问题点

  1. Gitlab与Jinkins自动化交互
  2. Jinkins与Docker交互
  3. 构建、打包、发布过程的通知与管理
  4. 代码运行环境依赖对镜像容器的启动命令,容易出现配置风险

解决思路

  1. Gitlab利用Webhooks 针对代码变动节点 主动与Jinkins进行交互
  2. Jinkins利用自身的构建环境进行项目构建以及镜像打包、发布
  3. Jinkins利用 SSH 插件注入到 运行服务器进行镜像更新
  4. 减少使用Docker remote进行对docker操作
    • 因为笔者一个在阿里云上买的玩具服务器不知不觉被挖了一个月XMP
  5. 利用Jinkins自带通知插件进行过程通报
    • 虽然企业微信通知插件方便, 但是啰嗦 + 无法自定义内容显得有点难以进行更详细的信息通知

开始改造

代码篇

  • Dockerfile改造

FROM openjdk:11.0-jre
VOLUME /tmp
ADD *.jar app.jar
RUN sh -c 'touch /app.jar'
# 设定环境变量
ARG PROFILES_ENV
ENV PROFILES_ENV ${PROFILES_ENV}
RUN echo "设置镜像环境: ${PROFILES_ENV}"
ENV JAVA_OPTS=""
# 复制宿主机时区
RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime && echo 'Asia/Shanghai' >/etc/timezone
# 设定入口
ENTRYPOINT [ "sh", "-c", "java $JAVA_OPTS -Dspring.profiles.active=$PROFILES_ENV -Djava.security.egd=file:/dev/./urandom -jar /app.jar" ]
笔者自己使用的Dockerfile, 有兴趣的同学可以举一反三加五花八门的配置

其实核心配置就几行:

# 设定变量环境,使其可被打包时配置
ARG PROFILES_ENV
ENV PROFILES_ENV ${PROFILES_ENV}
# 将镜像入口命令添加对运行环境的配置
-Dspring.profiles.active=$PROFILES_ENV

其中: - JAVA_OPTS 这东西也是为了配置扩展性而生, 便于添加容器 JVM 运行参数

  • 切肤之痛

    • 针对父子模块的项目, 如果需要对Dockerfile进行统一, 比较推荐下列方案

父模块 / common包 (怎么叫不是重点!!!!)

<plugin>
    <artifactId>maven-remote-resources-plugin</artifactId>
    <version>1.7.0</version>
    <executions>
        <execution>
            <goals>
                <goal>bundle</goal>
            </goals>
        </execution>
    </executions>
    <configuration>
        <includes>
            <include>**/*</include>
        </includes>
    </configuration>
</plugin>

子模块

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-remote-resources-plugin</artifactId>
    <version>1.7.0</version>
    <configuration>
        <resourceBundles>
            <resourceBundle>com.example:common:${com.example.common.version}
            </resourceBundle>
        </resourceBundles>
    </configuration>
    <executions>
        <execution>
            <goals>
                <goal>process</goal>
            </goals>
        </execution>
    </executions>
</plugin>
需要注意的是: 
    子模块中 resourceBundle 标签内的值必须再次检查!!!
    各位也不是第一次吃过 CV大法 的亏了吧
    
还有需要注意的是:
    父模块中的 include 标签表达式最好粒度尽量细, 不然子模块会多出很多奇奇怪怪的文件

大概可以这么总结

  • 使用Dockerfile参数针对项目镜像打包进行环境定义
  • 对于大型项目

    比如说:

    • 架构人员给了你一个common包
    • 又或者你自己想玩一下微服务
      • 结果做着做着发现需要抽离公共代码
      • 然后抽着抽着发现需要common包 建议使用上文的切肤之痛方案

先写着这么多,后面继续补充

其实还是笔者是一边做一边写

可大可小的项目

啧啧