微服務架構中將SpringBoot項目打包Docker鏡像

微服務架構中將SpringBoot項目打包Docker鏡像

目前主流的互聯網公司採用的架構設計應該都比較超前,微服務,容器和雲原生等基礎架構應該都有采用和進行二次開發。在微服務架構設計中,項目發佈時需要將項目打包成容器鏡像,這一步是最基本的操作。

下面我們介紹下,如何將SpringBoot項目打包成Docker容器鏡像,通過筆記的形式記錄下來方便以後查閱。將SpringBoot項目打包成Docker容器鏡像主要分為兩部分:

  1. 添加Maven插件
  2. 定義Dockerfile

下面通過一個詳細的例子來介紹下具體的內容。

微服務架構中將SpringBoot項目打包Docker鏡像

添加Maven插件

在maven的pom.xml中添加我們需要的插件,這裡我們採用dockerfile-maven-plugin,當然也可以選擇其他的插件,不同的插件的使用方法可能不太一樣

<code> 

<

plugin

>

<

groupId

>

com.spotify

groupId

>

<

artifactId

>

dockerfile-maven-plugin

artifactId

>

<

executions

>

<

execution

>

<

id

>

default

id

>

<

goals

>

<

goal

>

build

goal

>

<

goal

>

push

goal

>

goals

>

execution

>

executions

>

<

configuration

>

<

repository

>

${docker.repostory}/${project.artifactId}

repository

>

<

tag

>

${project.version}

tag

>

<

buildArgs

>

<

JAR_FILE

>

target/${project.build.finalName}.jar

JAR_FILE

>

buildArgs

>

configuration

>

plugin

>

/<code>

dockerfile-maven-plugin插件主要使用了兩個goal:

  • build是指構建Docker容器鏡像;
  • push是將構建的Docker容器鏡像推送到公有或者私有鏡像倉庫中;

dockerfile-maven-plugin插件的configuration說明如下:

  • repository定義一個公有或者私有的鏡像倉庫;
  • tag是Docker鏡像的版本號;
  • buildArgs是向Dockerfile傳遞參數,該節點下面的子節點標籤可以自定義,因為該節點標籤的數據類型是Map;
  • JAR_FILE是自定義標籤,定義了Maven打包後jar文件的位置,該參數會在Dockerfile中用到;
微服務架構中將SpringBoot項目打包Docker鏡像

定義Dockerfile

接下來我們就需要定義Dockerfile了。那麼,Dockerfile是什麼呢?

Dockerfile 是一個用來構建鏡像的文本文件,文本內容包含了一條條構建鏡像所需的指令和說明。

Dockerfile常用的指令有如下幾種:

COPY

複製指令,從上下文目錄中複製文件或者目錄到容器裡指定路徑。格式:

<code>COPY [--chown=

<

user

>

:

<

group

>

]

<

源路徑1

>

...

<

目標路徑

>

COPY [--chown=

<

user

>

:

<

group

>

] ["

<

源路徑1

>

",... "

<

目標路徑

>

"]/<code>

[--chown=:]:可選參數,用戶改變複製到容器內文件的擁有者和屬組。

:源文件或者源目錄,這裡可以是通配符表達式,其通配符規則要滿足 Go 的 filepath.Match 規則。例如:

<code>

COPY

hom* /mydir/

COPY

hom?.txt /mydir/

/<code>

:容器內的指定路徑,該路徑不用事先建好,路徑不存在的話,會自動創建。

ADD

ADD 指令和 COPY 的使用格式一致(同樣需求下,官方推薦使用 COPY)。功能也類似,不同之處如下:

  • ADD 的優點:在執行 為 tar 壓縮文件的話,壓縮格式為 gzip, bzip2 以及 xz 的情況下,會自動複製並解壓到 。
  • ADD 的缺點:在不解壓的前提下,無法複製 tar 壓縮文件。會令鏡像構建緩存失效,從而可能會令鏡像構建變得比較緩慢。具體是否使用,可以根據是否需要自動解壓來決定。

CMD

類似於 RUN 指令,用於運行程序,但二者運行的時間點不同:

  • CMD 在docker run 時運行。
  • RUN 是在 docker build。

作用:為啟動的容器指定默認要運行的程序,程序運行結束,容器也就結束。CMD 指令指定的程序可被 docker run 命令行參數中指定要運行的程序所覆蓋。

注意:如果 Dockerfile 中如果存在多個 CMD 指令,僅最後一個生效。格式:

<code>

CMD

CMD

[

""

,

""

,

""

,...]

CMD

[

""

,

""

,...] # 該寫法是為 ENTRYPOINT 指令指定的程序提供默認參數/<code>

推薦使用第二種格式,執行過程比較明確。第一種格式實際上在運行的過程中也會自動轉換成第二種格式運行,並且默認可執行文件是 sh。

ENTRYPOINT

類似於 CMD 指令,但其不會被 docker run 的命令行參數指定的指令所覆蓋,而且這些命令行參數會被當作參數送給 ENTRYPOINT 指令指定的程序。

但是, 如果運行 docker run 時使用了 --entrypoint 選項,此選項的參數可當作要運行的程序覆蓋 ENTRYPOINT 指令指定的程序。

優點:在執行 docker run 的時候可以指定 ENTRYPOINT 運行所需的參數。

注意:如果 Dockerfile 中如果存在多個 ENTRYPOINT 指令,僅最後一個生效。格式:

<code>

ENTRYPOINT

[

""

,

""

,

""

,...]

/<code>

可以搭配 CMD 命令使用:一般是變參才會使用 CMD ,這裡的 CMD 等於是在給 ENTRYPOINT 傳參,以下示例會提到。

示例:

假設已通過 Dockerfile 構建了 nginx:test 鏡像:

<code>

FROM

nginx ENTRYPOINT [

"nginx"

,

"-c"

] CMD [

"/etc/nginx/nginx.conf"

] /<code>

1、不傳參運行

<code> 

docker run nginx:

test

/<code>

容器內會默認運行以下命令,啟動主進程。

<code>

nginx

-c /etc/nginx/nginx.conf/<code>

2、傳參運行

<code>

docker run nginx:

test

-c /etc/nginx/new.conf

/<code>

容器內會默認運行以下命令,啟動主進程(/etc/nginx/new.conf:假設容器內已有此文件)

<code>nginx -c /etc/nginx/

new

.conf/<code>

ENV

設置環境變量,定義了環境變量,那麼在後續的指令中,就可以使用這個環境變量。格式:

<code>ENV 

<

key

>

<

value

>

ENV

<

key1

>

=

<

value1

>

<

key2

>

=

<

value2

>

.../<code>

以下示例設置 NODE_VERSION = 7.2.0 , 在後續的指令中可以通過 $NODE_VERSION 引用:

<code>

ENV

NODE_VERSION

7

.

2

.

0

RUN curl -SLO

"https://nodejs.org/dist/v

$NODE_VERSION

/node-v

$NODE_VERSION

-linux-x64.tar.xz"

\ && curl -SLO

"https://nodejs.org/dist/v

$NODE_VERSION

/SHASUMS256.txt.asc"

/<code>

ARG

構建參數,與 ENV 作用一致。不過作用域不一樣。ARG 設置的環境變量僅對 Dockerfile 內有效,也就是說只有 docker build 的過程中有效,構建好的鏡像內不存在此環境變量。

構建命令 docker build 中可以用 --build-arg = 來覆蓋。格式:

<code>ARG 

<

參數名

>

[=

<

默認值

>

]/<code>

VOLUME

定義匿名數據卷。在啟動容器時忘記掛載數據卷,會自動掛載到匿名卷。

作用:

  • 避免重要的數據,因容器重啟而丟失,這是非常致命的。
  • 避免容器不斷變大。

格式:

<code>

VOLUME

[

""

,

""

...]

VOLUME

/<code>

在啟動容器 docker run 的時候,我們可以通過 -v 參數修改掛載點。

EXPOSE

僅僅只是聲明端口。

作用:

  • 幫助鏡像使用者理解這個鏡像服務的守護端口,以方便配置映射。
  • 在運行時使用隨機端口映射時,也就是 docker run -P 時,會自動隨機映射 EXPOSE 的端口。

格式:

<code>EXPOSE 

<

端口1

>

[

<

端口2

>

...]/<code>

WORKDIR

指定工作目錄。用 WORKDIR 指定的工作目錄,會在構建鏡像的每一層中都存在。(WORKDIR 指定的工作目錄,必須是提前創建好的)。

docker build 構建鏡像過程中的,每一個 RUN 命令都是新建的一層。只有通過 WORKDIR 創建的目錄才會一直存在。格式:

<code>WORKDIR 

<

工作目錄路徑

>

/<code>

USER

用於指定執行後續命令的用戶和用戶組,這邊只是切換後續命令執行的用戶(用戶和用戶組必須提前已經存在)。格式:

<code>USER 

<

用戶名

>

[:

<

用戶組

>

]/<code>

我們自定義的Dockerfile內容結構大致如下:

<code>

FROM

openjdk:

8

MAINTAINER xiaobaoqiang 163.com> ARG JAR_FILE ADD

${JAR_FILE}

"/root/nacos-discovery-provider.jar"

ENTRYPOINT [

"java"

,

"-jar"

,

"/root/nacos-discovery-provider.jar"

] EXPOSE

8081

/<code>
  • FROM是指從哪個基礎鏡像開始構建我們自己的鏡像,這裡我們使用openjdk版本1.8;
  • MAINTAINER是指製作該鏡像的作者;
  • ARG構建參數,這裡我們使用了JAR_FILE,該參數是從Maven的dockerfile-maven-plugin插件傳遞過來的;
  • ADD將Mavne打包後的jar文件複製到Docker容器中;
  • ENTRYPOINT是指容器啟動時需要運行的程序指令;
  • EXPOSE是指容器啟動後需要暴露的端口,該參數一般情況下與springboot配置文件中的server.port保持一致;

驗證

所有的準備工作和配置文件已經完成,下面通過maven打包的形式來驗證下:

<code>mvn clean 

package

/<code>
微服務架構中將SpringBoot項目打包Docker鏡像

驗證結果

看到如上日誌信息,則表示我們打包構建Docker鏡像成功。

<code>

[root@instance01

~]#

docker

images

|

grep

nacos-discovery-provider

10.0

.0

.10

:5000/nacos-discovery-provider

0.0

.1

65dcbdd91921

2

minutes

ago

554MB

/<code>

通過docker命令可以查看我們剛構建的容器鏡像。

通過這種Mavne插件和Dockerfile再結合jenkins就可以完全實現CI/CD持續集成持續發佈功能,大大縮短我們在敏捷項目中的發佈時間,提升我們的工作效率。


不積跬步,無以至千里;不積小流,無以成江海!


分享到:


相關文章: