写点什么

玩转不同语言的 Docker 打包方式

作者:Kevin_913
  • 2023-11-06
    广东
  • 本文字数:1800 字

    阅读完需:约 6 分钟

玩转不同语言的Docker打包方式

关于 Docker 不同语言打包方式。


目前容器化应用越来越广泛,这里汇总几种语言常见的 docker 打包方式。

Java

Java 相对其他语言来讲,相对其他语言来讲,会根据 JVM 的类型分为不同的打包方式。


  • HotSpot VM 这个方式会以某一个 jdk 作为基础镜像,然后复制打包后的可执行你 jar 到容器内运行,相对而言,这个方式 Dockerfile 会比较简单,但由于基础镜像为 jdk 镜像,所以生成的镜像体积相对会大。下面示例以 openjdk 作为基础镜像,创建一个自己的镜像,生成后的镜像体积在 500M 左右。


FROM openjdk:17
ARG workspace
COPY $workspace/target/*-fat.jar /app/app.jarWORKDIR /app
EXPOSE 8888ENTRYPOINT ["java","-jar", "./app.jar" ]
复制代码


  • GraalVMGraalVM 提供的 native-image 支持将 java 的项目生成一个不同平台的可执行文件,不依赖于 JVM 来运行,所以利用 multiple stage 的方式,可以创建体积小的镜像,也由于 GraalVM 是用的 AOT 方式,所以它的应用启动速度会明显快于 HotSpot VM 创建的应用的启动速度,但由于在创建 docker 镜像的时候会把 class 文件编译成机器语言,包括静态文件处理,反射的处理等,所以整个过程花费时间相对 HotSpot VM 的编译过程要长。下面是两个示例,都是利用 native-image 作为 build 镜像,最后用一个包含 glibc 或者 musl 的基础镜像运行可执行程序,生成的镜像体积在 50M 左右。

  • 基于生成好的 jar 包创建 docker image,利用 native-image 命令将 jar 包生成不依赖 JVM 的可执行文件。

  ## Stage 1 : build with maven builder image with native capabilities  FROM container-registry.oracle.com/graalvm/native-image:17 AS build
ARG workspace
COPY $workspace/target/*-fat.jar /app/app.jar WORKDIR /app RUN native-image -jar app.jar
## Stage 2 : create the final image, need a glibc or musl alpine FROM frolvlad/alpine-glibc COPY --from=build /app/demo /app/application EXPOSE 8888 WORKDIR /app/ ENTRYPOINT [ "/app/application" ]
复制代码
  • 基于项目打包 docker image,应用在 CI/CD 工具中,在项目中包含 maven wrapper 以及对于的 maven 运行脚本,让项目不依赖于平台的 maven 来进行编译,对于 HotSpot VM 的编译同样可以采取相同的方式。

  ## Stage 1 : build with maven builder image with native capabilities  FROM container-registry.oracle.com/graalvm/native-image:17 AS build
ARG workspace
COPY $workspace/mvnw /code/mvnw COPY $workspace/.mvn /code/.mvn COPY $workspace/pom.xml /code/ WORKDIR /code
COPY $workspace/src /code/src RUN ./mvnw package -DskipTests
## Stage 2 : create the final image, need a glibc or musl alpine FROM frolvlad/alpine-glibc COPY --from=build /code/target/demo /app/application
EXPOSE 8888 WORKDIR /app/ ENTRYPOINT [ "/app/application" ]
复制代码

Golang

Golang 支持将代码编译成不依赖于语言的可执行文件,所以打包方式跟 GraalVM 类似,而且 Golang 不需要像 native-image 那样需要对字节码做额外的检查和转换,所以整个 build 耗时相对而言不算太慢,生成的镜像体积也基本在几十 M 以内。示例:


FROM golang:1.19-alpine AS buildWORKDIR /work/
RUN chown 1001 /work \ && chmod "g+rwX" /work \ && chown 1001:root /workCOPY go.* /work/COPY main.go /work/COPY src /work/src/
WORKDIR /work/RUN go mod downloadRUN go build -o .
FROM alpine:latestWORKDIR /COPY --from=build /work /workEXPOSE 9000
WORKDIR /work/ENTRYPOINT ["./blog-api"]
复制代码

Python

本身就是一个脚本语言,有 python 环境就可以运行,如果需要用容器方式来运行,只需要准备一个 python 的基础镜像,可以按照 conda 的 env 来创建基础镜像,包含项目的一些基础依赖。示例,打包一个 flask 项目。


FROM registry.cn-hangzhou.aliyuncs.com/kevin-proxy/ml-py:v1
WORKDIR /codeEXPOSE 6000COPY *.py /code/CMD ["gunicorn", "app:app", "-c", "./gunicorn.conf.py"]
复制代码

前端

前端依赖于一个 web 容器来运行,所以需要选择一个 web 容器作为基础镜像,然后将编译好的文件复制到容器就可以生成镜像。示例,用 nginx 作为 web 容器打包 vue 编译后的项目,需要修改 nginx.conf 指定 html 目录。


FROM nginx:alpine as prod
WORKDIR /work/
COPY dist/ /work/COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
复制代码


发布于: 刚刚阅读数: 4
用户头像

Kevin_913

关注

纸上得来终觉浅,绝知此事要躬行。 2019-02-25 加入

专注于代码和设计15+年。 主要涉及Java,Golang,云平台。

评论

发布
暂无评论
玩转不同语言的Docker打包方式_docker build_Kevin_913_InfoQ写作社区