天天看點

Spring Boot:使用Dockerfile将JAR建構成鏡像

Dockerfile

不了解​

​Dockerfile​

​的基本文法,可以參考下面幾篇部落格:

  • ​​Docker:Dockerfile之FROM、ARG、LABEL、MAINTAINER、RUN、CMD指令詳解​​
  • ​​Docker:Dockerfile之ADD、COPY、WORKDIR、USER、EXPOSE指令詳解​​
  • ​​Docker:Dockerfile之ENV、ENTRYPOINT、VOLUME、ONBUILD、STOPSIGNAL指令詳解​​

安裝​

​Docker​

​:

  • ​​CentOS:安裝Docker​​

項目代碼

項目結構圖:

Spring Boot:使用Dockerfile将JAR建構成鏡像

​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 https://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.6.2</version>
    </parent>

    <packaging>jar</packaging>

    <groupId>com.kaven</groupId>
    <artifactId>springboot</artifactId>
    <version>0.0.1-SNAPSHOT</version>

    <name>springboot</name>
    <description>springboot</description>

    <properties>
        <java.version>1.8</java.version>
    </properties>

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

    <build>
        <plugins>
            <plugin>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-maven-plugin</artifactId>
            </plugin>
        </plugins>
        <finalName>hello-world</finalName>
    </build>
</project>      

打包成​

​JAR​

​:

<packaging>jar</packaging>      

​application.properties​

​:

server.port=8080      

​Spring Boot​

​​應用的預設啟動端口也是​

​8080​

​,這裡隻是為了示範。

​HelloWorldController​

​:

package com.kaven.springboot.controller;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
public class HelloWorldController {

    @GetMapping("/hello-world")
    public String helloWorld() {
        return "Hello World";
    }
}      

啟動類:

package com.kaven.springboot;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class SpringbootApplication {

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

使用​

​Maven​

​​打包​

​Spring Boot​

​​項目,直接使用​

​IDEA​

​的快捷鍵。

Spring Boot:使用Dockerfile将JAR建構成鏡像

輕按兩下即可打包​

​Spring Boot​

​​項目,如下圖所示,生成了​

​hello-world.jar​

​檔案。

Spring Boot:使用Dockerfile将JAR建構成鏡像

該檔案的名稱由​

​pom.xml​

​的如下配置指定:

<build>
        <finalName>hello-world</finalName>
    </build>      

建構鏡像

​Dockerfile​

​:

FROM openjdk:8-jdk-alpine
ENV PORT=8080
EXPOSE ${PORT}
RUN mkdir /usr/local/work
WORKDIR /usr/local/work
COPY hello-world.jar ./app.jar
ENTRYPOINT java -jar ./app.jar --server.port=${PORT}      

上傳檔案到虛拟機。

Spring Boot:使用Dockerfile将JAR建構成鏡像
[root@192 ~]# ls
anaconda-ks.cfg  Dockerfile  hello-world.jar
[root@192 ~]# docker build -t kaven/app:v1 .
Sending build context to Docker daemon  17.57MB
Step 1/7 : FROM openjdk:8-jdk-alpine
8-jdk-alpine: Pulling from library/openjdk
e7c96db7181b: Pull complete 
f910a506b6cb: Pull complete 
c2274a1a0e27: Pull complete 
Digest: sha256:94792824df2df33402f201713f932b58cb9de94a0cd524164a0f2283343547b3
Status: Downloaded newer image for openjdk:8-jdk-alpine
 ---> a3562aa0b991
Step 2/7 : ENV PORT=8080
 ---> Running in 416d1fad537b
Removing intermediate container 416d1fad537b
 ---> 63661c95ad05
Step 3/7 : EXPOSE ${PORT}
 ---> Running in e5904ad809c2
Removing intermediate container e5904ad809c2
 ---> 6375175d08fd
Step 4/7 : RUN mkdir /usr/local/work
 ---> Running in 8e63e0f8c201
Removing intermediate container 8e63e0f8c201
 ---> 141bc0602eb5
Step 5/7 : WORKDIR /usr/local/work
 ---> Running in bc3cb4d134c9
Removing intermediate container bc3cb4d134c9
 ---> 5d35babe551c
Step 6/7 : COPY hello-world.jar ./app.jar
 ---> 725b98b42c0d
Step 7/7 : ENTRYPOINT java -jar ./app.jar --server.port=${PORT}
 ---> Running in c7dc784db206
Removing intermediate container c7dc784db206
 ---> 36f926b2a1f5
Successfully built 36f926b2a1f5
Successfully tagged kaven/app:v1      
  • ​​Docker:Docker Image及Image指令詳解​​

檢視​

​Docker​

​已有鏡像資訊。

[root@192 ~]# docker images
REPOSITORY   TAG            IMAGE ID       CREATED          SIZE
kaven/app    v1             36f926b2a1f5   48 seconds ago   122MB
openjdk      8-jdk-alpine   a3562aa0b991   2 years ago      105MB      

運作鏡像,即建立并啟動容器。

[root@192 ~]# docker run -d --name app -e PORT="8888" -p 8888:8888 kaven/app:v1
e5f189df0d1077fb571fc4892c47462efc529f5f21f9f11d106ed35650acb566      
  • ​​Docker:Docker Container及Container指令詳解​​

檢視容器是否啟動成功,很顯然啟動成功了(​

​Up 16 seconds​

​)。

[root@192 ~]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                                                 NAMES
e5f189df0d10   kaven/app:v1   "/bin/sh -c 'java -j…"   17 seconds ago   Up 16 seconds   8080/tcp, 0.0.0.0:8888->8888/tcp, :::8888->8888/tcp   app      

主控端請求接口。

[root@192 ~]# wget http://localhost:8888/hello-world
--2022-01-27 14:17:40--  http://localhost:8888/hello-world
正在解析主機 localhost (localhost)... ::1, 127.0.0.1
正在連接配接 localhost (localhost)|::1|:8888... 已連接配接。
已發出 HTTP 請求,正在等待回應... 200 
長度:11 [text/plain]
正在儲存至: “hello-world”

100%[=======================================================================================================================================================================>] 11          --.-K/s 用時 0s      

2022-01-27 14:17:40 (2.24 MB/s) - 已儲存 “hello-world” [11/11])

[root@192 ~]# ls
anaconda-ks.cfg  Dockerfile  hello-world  hello-world.jar
[root@192 ~]# cat hello-world
Hello World      

關閉防火牆,讓區域網路内的主機可以請求接口。

[root@192 ~]# systemctl stop firewalld
[root@192 ~]# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: enp0s3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether 08:00:27:04:21:5b brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.4/24 brd 192.168.1.255 scope global noprefixroute dynamic enp0s3
       valid_lft 77546sec preferred_lft 77546sec
    inet6 240e:381:4465:a200:d831:219:83:2618/64 scope global noprefixroute dynamic 
       valid_lft 213562sec preferred_lft 127162sec
    inet6 fe80::78c7:a5b1:1ea9:9800/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default 
    link/ether 02:42:67:b8:89:e7 brd ff:ff:ff:ff:ff:ff
    inet 172.17.0.1/16 brd 172.17.255.255 scope global docker0
       valid_lft forever preferred_lft forever
    inet6 fe80::42:67ff:feb8:89e7/64 scope link 
       valid_lft forever preferred_lft forever
73: veth01ba79d@if72: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master docker0 state UP group default 
    link/ether 6a:20:9d:ea:5b:be brd ff:ff:ff:ff:ff:ff link-netnsid 0
    inet6 fe80::6820:9dff:feea:5bbe/64 scope link 
       valid_lft forever preferred_lft forever      

本地請求接口成功。

Spring Boot:使用Dockerfile将JAR建構成鏡像

将應用建構成鏡像的好處,就是可以使用雲原生技術,比如使用容器編排工具對應用進行管理,這些以後再進行介紹。

[root@192 ~]# systemctl start firewalld
[root@192 ~]# docker run -d --name app2 -e PORT="9999" -p 9000:9999 kaven/app:v1
1f011919d65354a3861e420dc1c366efe34fe9b10501ad9896a2b443764d4dcf
[root@192 ~]# docker ps
CONTAINER ID   IMAGE          COMMAND                  CREATED          STATUS          PORTS                                                 NAMES
1f011919d653   kaven/app:v1   "/bin/sh -c 'java -j…"   19 seconds ago   Up 19 seconds   8080/tcp, 0.0.0.0:9000->9999/tcp, :::9000->9999/tcp   app2
e5f189df0d10   kaven/app:v1   "/bin/sh -c 'java -j…"   12 minutes ago   Up 11 minutes   8080/tcp, 0.0.0.0:8888->8888/tcp, :::8888->8888/tcp   app      
[root@192 ~]# wget http://localhost:9000/hello-world
--2022-01-27 14:28:53--  http://localhost:9000/hello-world
正在解析主機 localhost (localhost)... ::1, 127.0.0.1
正在連接配接 localhost (localhost)|::1|:9000... 已連接配接。
已發出 HTTP 請求,正在等待回應... 200 
長度:11 [text/plain]
正在儲存至: “hello-world.1”

100%[=======================================================================================================================================================================>] 11          --.-K/s 用時 0s      

2022-01-27 14:28:53 (2.36 MB/s) - 已儲存 “hello-world.1” [11/11])

[root@192 ~]# cat hello-world.1
Hello World