「走进k8s」Docker 的多阶段构建-JavaSpringboot(11)

上次主要说了docker的常用图形化管理工具,不知道各位老铁跟这我的节奏一起练习了吗?docker的口号:Build, Ship and Run,Buildonce,Runanywhere。不知道老铁考虑过一个问题吗?如果我们把源码也打入镜像的话这样是不是增加了docker的镜像的大小,处于安全的角度如果打了war包或者jar到镜像里面的话,也让他人查看到你了你的源码。

(一)实例springboot

比如我们现在有一个最简单的 springboot,需要构建一个最小的Docker 镜像

  • idea配置springboot

为了方便所有老铁,这个演示过程也做了

修改SpringbootApplication

package com.idig8.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.context.annotation.Configuration;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;

@Controller
@SpringBootApplication
@Configuration
public class SpringbootApplication {
    @RequestMapping("hello")
    @ResponseBody
    public String hello(){
        return "hello world!";
    }


    public static void main(String[] args) {
        SpringApplication.run(SpringbootApplication.class, args);
    }

}

  • pom.xml文件
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.1.6.RELEASE</version>
        <relativePath/> <!-- lookup parent from repository -->
    </parent>
    <groupId>com.idig8</groupId>
    <artifactId>springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>
    <name>springboot</name>
    <description>Demo project for Spring Boot</description>

    <properties>
        <java.version>1.8</java.version>
        <!-- 指定启动类 -->
        <start-class>com.idig8.springboot.SpringbootApplication</start-class>
    </properties>

    <dependencies>
        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-web</artifactId>
        </dependency>

        <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-test</artifactId>
            <scope>test</scope>
        </dependency>
    </dependencies>


    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
    </build>

</project>

项目的目录结构

启动项目:http://localhost:8080/hello

(二)多阶段构建

  • ①3种实际使用的流程容器使用流程
  1. 主机安装必须jdk,maven。通过主机自身的maven打包生成jar或者war。启动一个jdk8以上的容器,通过挂载jar或者war运行起来。(操作复杂不利于脚本)
  2. 启动一个容器,容器自带jdk和maven,挂载源码的方式编译打包生成对应的jar或者war,直接在这个容器内生成,把源码打到容器内。(镜像特别大)
  3. 启动2个容器,A容器自带jdk和maven,A容器内挂载源码,编译生成jar或者war,通过docker copy命令把生成后的jar或者war从容器内拷贝到宿主机上。然后B容器自带jdk或者tomcat,直接将上一步的jar和war拷贝到容器内直接进行运行,这样A容器很大,但是他不需要上传到它只做编译使用,B容器生成的镜像小,只做运行使用。
    这样就导致B容器很小符合docker最小化原则。

第一,第二适应于小项目无法批量使用除非写shell脚本无法大规模使用。针对第三种更加简单的方式来实现上面的镜像构建过程呢?Docker 17.05版本以后,官方就提供了一个新的特性:Multi-stage builds(多阶段构建)。 使用多阶段构建,可以在一个 Dockerfile 中使用多个 FROM 语句。每个 FROM 指令都可以使用不同的基础镜像,并表示开始一个新的构建阶段。你可以很方便的将一个阶段的文件复制到另外一个阶段,在最终的镜像中保留下你需要的内容即可。

  • ②上传项目
yum -y install lrzsz
yum -y install zip unzip
cd ~
mkdir test2
rz
ll

不要勾选upload files as ASC

  • ③解压项目
unzip springboot.zip
ls
rm -rf springboot.zip

  • ④编写多构建Dockerfile
cd springboot
vi Dockerfile

编写Dockerfile

FROM maven:3.6.1-jdk-8 AS build-env
ADD . /java/src/app
WORKDIR /java/src/app
RUN mvn clean package -Ptest -Dmaven.test.skip=true
RUN cp /java/src/app/target/*.jar /java/src/app/app.jar


FROM openjdk:8-jre
ENV SPRING_OUTPUT_ANSI_ENABLED=ALWAYS 
    JAVA_OPTS=""
COPY --from=build-env /java/src/app/app.jar  /usr/local/bin/app-server/app.jar
CMD echo "The application will start " && 
    java ${JAVA_OPTS} -Djava.security.egd=file:/dev/./urandom -jar /usr/local/bin/app-server/app.jar
EXPOSE 8080

构建阶段是没有命令的,我们可以通过它们的索引来引用它们,第一个 FROM 指令从0开始,我们也可以用AS指令为阶段命令,比如我们这里的将第一阶段命名为build-env,然后在其他阶段需要引用的时候使用–from=build-env参数即可。

  • ⑤构建Dockerfile
docker build -t zhugeaming/docker-multi-java-demo:latest .

  • ⑥查看效果

http://192.168.66.100:8080/hello

PS:也可以在springboot目录里面放置一个settings.xml文件,在mvn编译的时候连接指定的maven私服,这样就节省效率。

mvn  -s "settingsXXX.xml" clean package -Ptest -Dmaven.test.skip=true
>>原创文章,欢迎转载。转载请注明:转载自IT人故事会,谢谢!
>>原文链接地址:「走进k8s」Docker 的多阶段构建-JavaSpringboot(11)
上一篇: 下一篇:

发表评论

电子邮件地址不会被公开。 必填项已用*标注