HOME | EDIT | RSS | INDEX | ABOUT | GITHUB

如何部署 Scala 代码

我们产品Scala用过很多种方式部署.

两年多前

的代码库, 都是

  1. sbt-assembly 打成 uber jar(肥包, 也就是包含所有依赖), 大概 50-100M
  2. 把 jar 包 压到带 jvm 的 docker 里, push 到 register
  3. K8s 从 register 拉 docker

用过的同学都知道, 这个打肥包的过程非常非常的慢, 而且还需要一个诡异的配置告诉assembly如何merge 这对于新人来说是何等的 卧槽 黑人问号???

assemblyMergeStrategy in assembly := {
  case PathList("META-INF", xs @ _*) => MergeStrategy.discard
  case x => MergeStrategy.first
}

所以, 一点也不好用, 没用过的也不要用它了

  • 打包慢
  • 包大
  • uber jar包不能放registry, 只能给部署用, 所以别的服务怎么依赖这个jar
  • merge策略可能会导致诡异的运行时问题

一年前

的代码用的是 sbt-native-packager

这个工具很强大, 能打成 N 种 安装包

  • tar
  • deb
  • dmg
  • msi
  • docker
  • graalvm

这也太强了, 马上就觉得 assembly什么破烂玩意, 这个才是真正的打包工具.

用法非常简单, 对于我们来说只要docker, 安装插件然后

sbt docker:publishLocal

就完事了, push 到 register 就用了.

真是省事!

现在

用的是 Coursier

都说了 sbt-native-packager 那么好用了, 为啥还要换?

Coursier 相对 native packager 有更多的好处

  • 快: 有缓存, 而且sbt用的也是coursier, 共享缓存, 一起快
  • 快: 只打包应用, 不是 uber jar, 小了非常多, 打包速度也快, 上传也快
  • 还是快: CI 在部署前都不需要打包成docker, 这样前面的测试会很快,他们只用拉应用jar包,非常小,所有依赖又有缓存

然我们来看看怎么用 coursier 打包.

你不需要任何插件来发布 jar 包

直接:

sbt publish

假设你发布的包叫 `com.abc:heheda2.12:1.0`

如果跑测试要运行这个jar包只需要

coursier launch com.abc:heheda_2.12:1.0

所以大量的时间就省下来了 真正部署前根本不需要docker image, 而大部分时间 CI 只跑 Pull Request 的测试而不会部署 .

而在真正 master 部署时, 我们可以用 coursier 在 docker 里把依赖先安装好.

首先需要一个 coursier 的 docker image 这完全可以扔 docker hub 上, 但是我懒

FROM openjdk:8u222-slim

ARG VERSION

RUN apt update && apt install -y curl

WORKDIR /usr/local/bin

RUN curl -Lo coursier https://git.io/coursier-cli && chmod +x coursier

# Add and use user coursieruser
RUN groupadd --gid 1001 coursieruser && useradd --gid 1001 --uid 1001 coursieruser --shell /bin/bash
RUN chown -R coursieruser:coursieruser /opt
RUN mkdir /home/coursieruser && chown -R coursieruser:coursieruser /home/coursieruser
RUN mkdir /logs && chown -R coursieruser:coursieruser /logs
USER coursieruser

WORKDIR /home/coursieruser

RUN coursier --help

在给应打包docker时

FROM mycoursier
ARG version

RUN coursier bootstrap com.abc:heheda_2.12:$version -o heheda

CMD ./heheda

如果你的包在私有registry

FROM mycoursier
ARG version
ARG csuser
ARG cstoken

RUN env COURSIER_REPOSITORIES="central|sonatype:releases|https://$csuser:$cstoken@my.jarregistry.com" \
    coursier bootstrap com.abc:heheda_2.12:$version -o heheda

CMD ./heheda

Footnotes:

1

这对于新人来说是何等的 卧槽 黑人问号???

2

真正部署前根本不需要docker image, 而大部分时间 CI 只跑 Pull Request 的测试而不会部署

3

这完全可以扔 docker hub 上, 但是我懒