Docker Getting started with Java

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
RDS MySQL Serverless 高可用系列,价值2615元额度,1个月
简介: Docker Getting started with Java

image.pngimage.pngDocker 官网提供了 python,nodejs,java 3种不同编程语言的 Language-specific guides 学习指南。该指南详细说明了如何编写 Dockerfile 文件,部署 Docker 容器以及构建 CI/CD pipline。

本文介绍该指南了Java 部分的内容。

前提要求

  • Java OpenJDK 版本在 15 以上。
  • 安装 Docker。
  • 安装 Git 客户端。
  • IntelliJ IDEA 客户端.

在本机运行项目

克隆项目源代码:

git clone https://github.com/spring-projects/spring-petclinic.git
cd spring-petclinic

在项目文件中包含了一个嵌入式的 Maven 版本,因此不需要在机器上单独安装 Maven。Maven 将管理所有的项目过程(编译,测试,打包等)。使用下面命令来启动项目:

./mvnw spring-boot:run

mvnw 全名是 Maven Wrapper,它的原理是在 maven-wrapper.properties 文件中记录你要使用的 Maven 版本,当用户执行 mvnw 命令时,如果发现当前用户的 Maven 版本和期望的版本不一致,那么就下载期望的版本,然后用期望的版本来执行 mvn 命令。

该命令将会下载依赖,构建项目,并且启动项目。image.png

快速开始

现在已经可以确认我们的应用程序可以在本机正常运行了,接下来我们通过一个简单的示例将该项目构建为 Docker 镜像,然后用镜像运行容器。

构建镜像

编写 Dockerfile

Dockerfile 是一个文本文档,包含了构建镜像需要调用的所有命令。Docker 读取 Dockerfile 中的命令并依次执行它们,每一条指令都会提交为一个镜像层,下一条指令都是基于上一条指令构建的。

在项目的根目录下创建名为 Dockerfile 的文件,文件内容如下:

# syntax=docker/dockerfile:1
FROM openjdk:16-alpine3.13
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
CMD ["./mvnw", "spring-boot:run"]

现在解释一下每一行的作用:

  • Dockerfile 的第一行是语法解析器指令,该指令指示 docker build 在解析 Dockerfile 时使用什么语法。解释器指令可以不写,但是如果写了就必须出现在 Dockerfile 的第一行。 解释器指令建议使用docker/dockerfile:1,因为它总是指向 version 1 语法的最新版本,BuildKit 会在构建镜像之前自动检测语法更新,确保使用的是最新版本。
  • 指定构建的基础镜像,这里我们使用 openjdk 作为我们的基础镜像,上面已经安装的 maven 以及 Java 应用程序所需要的依赖包:
FROM openjdk:16-alpine3.13
  • 创建一个工作目录,Docker 后续的命令将使用此路径作为当前目录。相当于在容器中 mkdir /app 创建了一个目录,然后 cd /app 进入该目录。
WORKDIR /app
  • 拷贝所需的文件到容器中:
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
  • 在构建镜像时运行命令,拷贝 pom.xml 和 mvnw 文件到容器中,就可以运行下面的命令下载所需要 maven 依赖:
RUN ./mvnw dependency:go-offline
  • 拷贝项目源代码到容器中:
COPY src ./src
  • 容器启动时执行的命令,该命令在构建镜像时不会执行:
CMD ["./mvnw", "spring-boot:run"]

构建镜像

使用 docker build 命令构建镜像,指定镜像名为 java-docker,tag 为 v1.0.0:

docker build --tag java-docker:v1.0.0  .


image.png细心的同学可能会注意到 docker build 命令最后还有一个 ..其实是指定了镜像构建过程中的上下文环境的目录。注意这个 . 并不是表示 Dockerfile 文件的路径,-f 参数才是用来指定 Dockerfile 的路径的(当 Dockerfile 名字为不为 Dockerfile/dockerfile 或者不在执行 docker build 命令的目录下,才需要使用 -f 参数指定 Dockerfile 文件)。

那么什么是上下文环境呢?

Docker 在运行时分为 Docker引擎(服务端守护进程) 以及客户端工具,我们日常使用各种 docker 命令,其实就是在使用客户端工具与 Docker 引擎 进行交互。那么当我们使用 docker build 命令来构建镜像时,这个构建过程其实是在 Docker 引擎中完成的,而不是在本机环境。

那么如果在 Dockerfile 中使用了一些 COPY 等指令来操作文件,如何让 Docker引擎 获取到这些文件呢?

这里就有了一个镜像构建上下文的概念,当构建的时候,由用户指定构建镜像的上下文路径,而 docker build 会将这个路径下所有的文件都打包上传给 Docker 引擎,引擎内将这些内容展开后,就能获取到所有指定上下文中的文件了。比如说 Dockerfile 中的 COPY ./package.json /project,其实拷贝的并不是本机目录下的 package.json 文件,而是 Docker 引擎中展开的构建上下文中的文件,所以如果拷贝的文件超出了构建上下文的范围,Docker引擎是找不到那些文件的。

查看构建好的镜像:

❯ docker images
REPOSITORY                                         TAG       IMAGE ID       CREATED          SIZE
java-docker                                        v1.0.0    f479e93b9881   22 minutes ago   574MB

启动容器

使用刚刚构建好的镜像来启动容器:

  • -d:后台运行。
  • -p:将容器的端口映射到宿主机的端口,-p [host port]:[container port]
  • --name:容器的名字。
  • 最后跟上镜像名。
docker run -d -p 8080:8080 --name java-docker java-docker:v1.0.0

查看运行的容器:

❯ docker ps
CONTAINER ID   IMAGE                COMMAND                  CREATED         STATUS         PORTS                                       NAMES
21ed2e02c63f   java-docker:v1.0.0   "./mvnw spring-boot:…"   3 seconds ago   Up 2 seconds   0.0.0.0:8080->8080/tcp, :::8080->8080/tcp   java-docker

浏览器输入 http://localhost:8080 来访问应用程序:image.png完成测试后,清理现场:

docker rm -f java-docker

构建本地开发环境

前面的示例中,我们已经可以通过容器的方式部署我们的服务了。但是刚刚的服务只是一个单体服务,接下来我们会分别通过手动部署和 Docker Compose 两种方式部署Java 应用服务 和 MySQL 数据库服务两个有关联的服务。

手动部署服务

在容器中运行 MySQL 数据库服务

首先创建两个 volume,用于持久化存储 MySQL 的数据和配置:

docker volume create mysql_data
docker volume create mysql_config

然后创建一个网络,Java 应用程序和数据库的容器将使用该网络相互通信,该网络被称为用户自定义的桥接网络,在自定义的桥接网络中,容器之间可以使用 DNS 名称互相通信(Docker 默认自带的桥接网络不能使用 DNS 名称通信)。

docker network create mysqlnet

启动数据库容器:

  • -v:挂载 volume。
  • --network:指定使用的网络。
  • --name:容器名。
  • -e:设置环境变量,MYSQL_ROOT_PASSWORD 必须设置。
  • -p:将容器的端口映射到宿主机的端口,-p [host port]:[container port]
  • 最后跟上镜像名。
docker run -it --rm -d -v mysql_data:/var/lib/mysql \
-v mysql_config:/etc/mysql/conf.d \
--network mysqlnet \
--name mysqlserver \
-e MYSQL_USER=petclinic -e MYSQL_PASSWORD=petclinic \
-e MYSQL_ROOT_PASSWORD=root -e MYSQL_DATABASE=petclinic \
-p 3306:3306 mysql:8.0.23

在容器中运行 Java 应用服务

修改应用程序的 Dockerfile 文件,修改最后 CMD 的指令即可,修改后的文件如下:

# syntax=docker/dockerfile:1
FROM openjdk:16-alpine3.13
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql"]

构建镜像:

docker build --tag java-docker:v1.0.1 .

启动容器:

docker run --rm -d \
--name springboot-server \
--network mysqlnet \
-e MYSQL_URL=jdbc:mysql://mysqlserver/petclinic \
-p 8080:8080 java-docker:v1.0.1

使用以下命令来测试 API 接口,Java 应用服务会去查询 MySQL 数据库并返回结果:

curl  --request GET \
  --url http://localhost:8080/vets \
  --header 'content-type: application/json'

你应该能看到以下返回结果:

{"vetList":[{"id":1,"firstName":"James","lastName":"Carter","specialties":[],"nrOfSpecialties":0,"new":false},{"id":2,"firstName":"Helen","lastName":"Leary","specialties":[{"id":1,"name":"radiology","new":false}],"nrOfSpecialties":1,"new":false},{"id":3,"firstName":"Linda","lastName":"Douglas","specialties":[{"id":3,"name":"dentistry","new":false},{"id":2,"name":"surgery","new":false}],"nrOfSpecialties":2,"new":false},{"id":4,"firstName":"Rafael","lastName":"Ortega","specialties":[{"id":2,"name":"surgery","new":false}],"nrOfSpecialties":1,"new":false},{"id":5,"firstName":"Henry","lastName":"Stevens","specialties":[{"id":1,"name":"radiology","new":false}],"nrOfSpecialties":1,"new":false},{"id":6,"firstName":"Sharon","lastName":"Jenkins","specialties":[],"nrOfSpecialties":0,"new":false}]}%

完成测试后,清理现场:

docker rm -f mysqlserver
docker rm -f springboot-server
docker volume rm mysql_data
docker volume rm mysql_config
docker network rm mysqlnet

使用 Docker Compose 部署服务

刚刚手动部署的方式我们需要事先创建 volume,network 等资源,我们可以使用 Docker Compose 来部署多个容器服务,将多个服务以及所需的资源定义在一个 docker-compose.yml 文件,只需要一条命令就可以快速部署服务。

安装 Docker Compose

curl -L https://get.daocloud.io/docker/compose/releases/download/1.24.0/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
chmod +x /usr/local/bin/docker-compose

编写 dockcer-compose.yaml 文件

version: '3.8'
services:
  petclinic:  #自定义服务名,Java服务
    build:  #上下文环境
      context: .
    ports: #暴露到主机的端口号
      - 8000:8000
      - 8080:8080
    networks: #容器使用的网络
      - mysqlnet
    environment:  #环境变量
      - SERVER_PORT=8080
      - MYSQL_URL=jdbc:mysql://mysqlserver/petclinic
    volumes: #挂载主机当前目录到容器/app目录
      - ./:/app
    #启动容器后执行的命令
    command: ./mvnw spring-boot:run -Dspring-boot.run.profiles=mysql -Dspring-boot.run.jvmArguments="-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000"  
  mysqlserver: #自定义服务名,MySQL服务
    image: mysql:8.0.23 #使用的镜像名
    ports:
      - 3306:3306
    networks:
      - mysqlnet
    environment:
      - MYSQL_ROOT_PASSWORD=
      - MYSQL_ALLOW_EMPTY_PASSWORD=true
      - MYSQL_USER=petclinic
      - MYSQL_PASSWORD=petclinic
      - MYSQL_DATABASE=petclinic
    volumes: #使用volmue
      - mysql_data:/var/lib/mysql
      - mysql_config:/etc/mysql/conf.d
volumes: #创建volume
  mysql_data:
  mysql_config:
networks: #创建network
  mysqlnet:

通过 Docker Compose 启动服务

使用 docker-compose 命令启动服务,Docker 会自动帮我们创建好需要的 volume 和 network 资源并启动容器:

  • -f:Docker Compose 默认的文件名为 docker-compose.yml, docker-compose.yaml, compose.yml, compose.yaml,如果文件名不是这几个,需要使用 -f 参数指定文件名。
  • up:启动服务。
  • -d:在后台运行。
  • --build:启动的时候重新构建镜像。
docker-compose -f docker-compose.dev.yml up -d --build

image.png查看 Docker Compose 运行的容器:

❯ docker-compose -f docker-compose.dev.yml ps
             Name                           Command               State                                         Ports
------------------------------------------------------------------------------------------------------------------------------------------------------------
spring-petclinic_mysqlserver_1   docker-entrypoint.sh mysqld      Up      0.0.0.0:3306->3306/tcp,:::3306->3306/tcp, 33060/tcp
spring-petclinic_petclinic_1     ./mvnw spring-boot:run -Ds ...   Up      0.0.0.0:8000->8000/tcp,:::8000->8000/tcp, 0.0.0.0:8080->8080/tcp,:::8080->8080/tcp

使用以下命令来测试 API 接口:

curl  --request GET \
  --url http://localhost:8080/vets \
  --header 'content-type: application/json'

你应该能看到以下返回结果:

{"vetList":[{"id":1,"firstName":"James","lastName":"Carter","specialties":[],"nrOfSpecialties":0,"new":false},{"id":2,"firstName":"Helen","lastName":"Leary","specialties":[{"id":1,"name":"radiology","new":false}],"nrOfSpecialties":1,"new":false},{"id":3,"firstName":"Linda","lastName":"Douglas","specialties":[{"id":3,"name":"dentistry","new":false},{"id":2,"name":"surgery","new":false}],"nrOfSpecialties":2,"new":false},{"id":4,"firstName":"Rafael","lastName":"Ortega","specialties":[{"id":2,"name":"surgery","new":false}],"nrOfSpecialties":1,"new":false},{"id":5,"firstName":"Henry","lastName":"Stevens","specialties":[{"id":1,"name":"radiology","new":false}],"nrOfSpecialties":1,"new":false},{"id":6,"firstName":"Sharon","lastName":"Jenkins","specialties":[],"nrOfSpecialties":0,"new":false}]}%

远程调试

保留前面 Docker Compose 的运行环境,接下来使用 Intellij IDEA 远程调试程序。Run menu > Edit Configuration,添加 Remote JVM Debug。image.pngimage.pngimage.pngimage.pngimage.png客户端使用以下命令发起请求:

curl --request GET --url http://localhost:8080/vets

程序会在断点处暂停,你可以检查和观察变量,设置条件断点,查看堆栈跟踪等。image.png测试完成后,清理现场,Docker 会删除容器以及 volume,network 等资源:

docker-compose -f docker-compose.dev.yml down

单元测试

测试是现代软件开发的重要组成部分。测试对于不同的开发团队来说意味着很多事情。测试包含单元测试、集成测试和端到端测试。在本指南中,我们将看看如何在 Docker 中运行单元测试。以下红色部分是单元测试的代码位置:image.png使用前面已经构建的 java-docker:v1.0.1 镜像来运行容器,启动容器时使用 ./mvnw test 运行单元测试:

docker run -it --rm --name springboot-test java-docker:v1.0.1 ./mvnw test

完成单元测试后,输出结果如下:image.png

多阶段构建

Docker 允许我们在 Dockerfile 中使用多个 FROM 语句,而每个 FROM 语句都可以使用不同基础镜像,每一个 FROM 代表一个构建阶段。下面这个 Dockerfile 中定义了 base,test,development 和 production 4 个构建阶段,我们可以自由选择构建镜像阶段,比如我只想做单元测试,那么我就只选择 test 阶段,如果我想要构建生产环境使用的镜像,那么就选择 production阶段。

# syntax=docker/dockerfile:1
FROM openjdk:16-alpine3.13 as base
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
FROM base as test #test构建阶段,名字自定义
CMD ["./mvnw", "test"]
FROM base as development
CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql", "-Dspring-boot.run.jvmArguments='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000'"]
FROM base as build
RUN ./mvnw package
FROM openjdk:11-jre-slim as production
EXPOSE 8080
COPY --from=build /app/target/spring-petclinic-*.jar /spring-petclinic.jar
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/spring-petclinic.jar"]

多阶段构建单元测试

我们在构建镜像的时候可以使用 --target,表示只运行 test 这个构建阶段。

docker build -t java-docker:v1.0.2 --target test .

根据输出结果可以看到,在 test 阶段后面的部分并没有执行:image.pngimage.png上面的步骤稍微有一些麻烦,我们先构建了镜像,然后再通过镜像启动容器来完成单元测试,我们可以通过修改 Dockerfile 文件来做一些优化:

# syntax=docker/dockerfile:1
FROM openjdk:16-alpine3.13 as base
WORKDIR /app
COPY .mvn/ .mvn
COPY mvnw pom.xml ./
RUN ./mvnw dependency:go-offline
COPY src ./src
FROM base as test #test构建阶段,名字自定义
RUN ["./mvnw", "test"] #将CMD改为RUN
FROM base as development
CMD ["./mvnw", "spring-boot:run", "-Dspring-boot.run.profiles=mysql", "-Dspring-boot.run.jvmArguments='-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=*:8000'"]
FROM base as build
RUN ./mvnw package
FROM openjdk:11-jre-slim as production
EXPOSE 8080
COPY --from=build /app/target/spring-petclinic-*.jar /spring-petclinic.jar
CMD ["java", "-Djava.security.egd=file:/dev/./urandom", "-jar", "/spring-petclinic.jar"]

CMD 指令是在启动容器时执行的,在构建镜像期间不会执行,我们可以将单元测试的指令改成 RUN,RUN指令在构建镜像的时候运行,并且在失败的时候会停止构建。这样我们只需要使用 docker build 命令在构建镜像的时候就完成的了单元测试:

docker build -t java-docker:v1.0.3 --target test .


image.pngimage.pngimage.png



image.png

version: '3.8'
services:
  petclinic:
    build:
      context: .
      target: production #指定production阶段
    ports:
      - 8000:8000
      - 8080:8080
    networks:
      - mysqlnet
    environment:
      - SERVER_PORT=8080
      - MYSQL_URL=jdbc:mysql://mysqlserver/petclinic
    volumes:
      - ./:/app
  mysqlserver:
    image: mysql:8.0.23
    ports:
      - 3306:3306
    networks:
      - mysqlnet
    environment:
      - MYSQL_ROOT_PASSWORD=
      - MYSQL_ALLOW_EMPTY_PASSWORD=true
      - MYSQL_USER=petclinic
      - MYSQL_PASSWORD=petclinic
      - MYSQL_DATABASE=petclinic
    volumes:
      - mysql_data:/var/lib/mysql
      - mysql_config:/etc/mysql/conf.d
volumes:
  mysql_data:
  mysql_config:
networks:
  mysqlnet:

启动服务:

docker-compose -f docker-compose.dev.yml up -d --build


image.pngGitHub Actions 是 GitHub 的持续集成服务,于2018年10月推出。GitHub Actions 的基本概念如下:

  • workflow(工作流程):持续集成一次运行的过程,就是一个 workflow。
  • job(任务):一个 workflow 由一个或多个 jobs 构成,含义是一次持续集成的运行,可以完成多个任务。
  • step(步骤):每个 job 由多个 step 构成,一步步完成。
  • action(动作):每个 step 可以依次执行一个或多个命令(action)。

GitHub Actions 的配置文件叫做 workflow 文件,存放在代码仓库的.github/workflows目录。workflow 文件采用 YAML 格式,文件名可以任意取,但是后缀名统一为.yml,比如 foo.yml。一个库可以有多个 workflow 文件。GitHub 只要发现.github/workflows目录里面有.yml文件,就会自动运行该文件。

GitHub 做了一个官方市场,可以搜索到他人提交的 actions,每个 action 就是一个独立的脚本。如果你需要某个 action,不必自己写复杂的脚本,直接引用他人写好的 action 即可。例如我们可以找到关于 docker 操作的一系列 action:image.png接下来将实现 GitHub Action CI / CD 流程。

创建镜像仓库 Access Token

登录 Docker Hub,依次点击 Account Setting > Security > New Access Token,创建一个 Access Token,用于 Github Action 推送镜像。image.pngimage.pngimage.pngimage.png

创建 Github Action Workflow

在仓库中点击 Actions > Set up this workflow 为该仓库,创建一个 Github Action Workflow。image.png

文件内容如下:

# workflow的名称,如果省略该字段,默认为当前workflow的文件名。
name: Java docker CI to Docker Hub
# 定触发workflow的条件,当推送tag时,才会触发workflow
on:
  push:
    tags:
      - "v*.*.*"
# 表示要执行的任务
jobs:
  build:
    # 使用GitHub托管的ubuntu实例来构建镜像
    runs-on: ubuntu-latest
    steps:
     # 检验仓库并且下载到runner(ubuntu实例)
      - name: Check Out Repo
        uses: actions/checkout@v2 #uses表示使用别人定义好的action
     # 登录Docker Hub
      - name: Login to Docker Hub
        uses: docker/login-action@v1
        with:
          # 使用之前在Github中定义的环境变量
          username: ${{ secrets.DOCKER_HUB_USERNAME }}
          password: ${{ secrets.DOCKER_HUB_ACCESS_TOKEN }}
     # 构建缓存,减少构建时间,为它不必重新下载所有镜像
      - name: Cache Docker layers
        uses: actions/cache@v2
        with:
          path: /tmp/.buildx-cache
          key: ${{ runner.os }}-buildx-${{ github.sha }}
          restore-keys: |
            ${{ runner.os }}-buildx-
     # 创建builder实例,BuildKit 是下一代的镜像构建组件,是 docker build 的扩展
      - name: Set up Docker Buildx
        id: buildx
        uses: docker/setup-buildx-action@v1
      # 获取push的tag值作为镜像的tag 
      - name: Get Commit Tag
        run: echo "GIT_TAG=`echo $(git describe --tags --abbrev=0)`" >> $GITHUB_ENV
      # 构建并推送镜像
      - name: Build and push
        id: docker_build
        uses: docker/build-push-action@v2
        with:
          context: ./
          file: ./Dockerfile
          # 使用前面创建的builder实例构建docker镜像
          builder: ${{ steps.buildx.outputs.name }}
          push: true
          tags: ${{ secrets.DOCKER_HUB_USERNAME }}/java-docker:${{ env.GIT_TAG }}
          # 使用缓存
          cache-from: type=local,src=/tmp/.buildx-cache
          cache-to: type=local,dest=/tmp/.buildx-cache
     # 打印镜像摘要
      - name: Image digest
        run: echo ${{ steps.docker_build.outputs.digest }}

推送代码

初始化本地仓库,并且提交代码到 Github 上。

#初始化本地仓库
git init 
#建立远程仓库
git remote add origin https://github.com/cr7258/spring-petclinic.git
#添加要push到远程仓库的文件或文件夹  
git add .  
#提交到本地仓库
git commit -m "java docker" 
#拉取远程仓库代码
git pull origin master --allow-unrelated-histories
#将本地仓库push到远程仓库mater分支
git push -u origin master

由于我们在 Github Action 的 workflow 配置文件中设置了只有推送 tag 时才会触发 workflow,因此刚才的推送代码并不会触发 workflow。接下来推送 tag 来触发 workflow:

git tag -a v1.0.11
git push origin v1.0.11

查看推送的 tag:image.pngimage.png

参考链接


相关实践学习
如何在云端创建MySQL数据库
开始实验后,系统会自动创建一台自建MySQL的 源数据库 ECS 实例和一台 目标数据库 RDS。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助     相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
|
8天前
|
存储 Java 开发者
成功优化!Java 基础 Docker 镜像从 674MB 缩减到 58MB 的经验分享
本文分享了如何通过 jlink 和 jdeps 工具将 Java 基础 Docker 镜像从 674MB 优化至 58MB 的经验。首先介绍了选择合适的基础镜像的重要性,然后详细讲解了使用 jlink 构建自定义 JRE 镜像的方法,并通过 jdeps 自动化模块依赖分析,最终实现了镜像的大幅缩减。此外,文章还提供了实用的 .dockerignore 文件技巧和选择安全、兼容的基础镜像的建议,帮助开发者提升镜像优化的效果。
|
13天前
|
存储 缓存 Java
Java应用瘦身记:Docker镜像从674MB优化至58MB的实践指南
【10月更文挑战第22天】 在容器化时代,Docker镜像的大小直接影响到应用的部署速度和运行效率。一个轻量级的Docker镜像可以减少存储成本、加快启动时间,并提高资源利用率。本文将分享如何将一个Java基础Docker镜像从674MB缩减到58MB的实践经验。
24 1
|
4月前
|
存储 Java Docker
使用Docker部署Java应用的最佳实践
使用Docker部署Java应用的最佳实践
|
1月前
|
消息中间件 NoSQL Kafka
Flink-10 Flink Java 3分钟上手 Docker容器化部署 JobManager TaskManager Kafka Redis Dockerfile docker-compose
Flink-10 Flink Java 3分钟上手 Docker容器化部署 JobManager TaskManager Kafka Redis Dockerfile docker-compose
33 4
|
1月前
|
Kubernetes Cloud Native 流计算
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
Flink-12 Flink Java 3分钟上手 Kubernetes云原生下的Flink集群 Rancher Stateful Set yaml详细 扩容缩容部署 Docker容器编排
68 0
|
3月前
|
jenkins 持续交付 开发工具
"引爆效率革命!Docker+Jenkins+GIT+Tomcat:解锁持续集成魔法,一键部署Java Web应用的梦幻之旅!"
【8月更文挑战第9天】随着软件开发复杂度的增加,自动化变得至关重要。本文通过实例展示如何结合Docker、Jenkins、Git与Tomcat建立高效的持续集成(CI)流程。Docker确保应用环境一致性;Jenkins自动化处理构建、测试和部署;Git管理源代码版本;Tomcat部署Web应用。在Jenkins中配置Git插件并设置项目,集成Docker构建Tomcat应用镜像并运行容器。此外,通过自动化测试、代码质量检查、环境隔离和日志监控确保CI流程顺畅,从而显著提高开发效率和软件质量。
74 3
|
4月前
|
Java Docker 容器
Java演进问题之ZGC的优点和缺点如何解决
Java演进问题之ZGC的优点和缺点如何解决
|
4月前
|
Java Scala 流计算
实时计算 Flink版产品使用问题之Docker镜像中的Java路径和容器内的Java路径不一致,是什么导致的
实时计算Flink版作为一种强大的流处理和批处理统一的计算框架,广泛应用于各种需要实时数据处理和分析的场景。实时计算Flink版通常结合SQL接口、DataStream API、以及与上下游数据源和存储系统的丰富连接器,提供了一套全面的解决方案,以应对各种实时计算需求。其低延迟、高吞吐、容错性强的特点,使其成为众多企业和组织实时数据处理首选的技术平台。以下是实时计算Flink版的一些典型使用合集。
|
4月前
|
存储 Java Docker
使用Docker部署Java应用的最佳实践
使用Docker部署Java应用的最佳实践
|
4月前
|
Java 持续交付 Docker
如何在Java中使用Docker
如何在Java中使用Docker