Docker筆記(五):整一個自己的映象

【空山新雨】發表於2019-07-18

原文地址:http://blog.jboost.cn/2019/07/17/docerk-5.html

 

獲取映象的途徑有兩個,一是從映象倉庫獲取,如官方的Docker Hub,二是自定義。上文已經介紹如何從映象倉庫獲取映象,本文基於一個Springboot專案,來介紹自定義一個映象的基本流程。

1. 定製映象的本質

我們知道映象是分層儲存的,映象的構建也是一層一層進行的,一層構建完後,就變為只讀,在其上再構建下一層。因此定製映象,實際上就是定義每一層要乾的事,比如執行某個命令,設定一個環境變數,宣告一個暴露埠等等。然後在構建時,按照各層的定義,一層一層地完成構建,最終形成一個包含這些層的映象。

2. Dockerfile檔案

Docker中定義各層要乾的事的檔案叫Dockerfile,它是一個文字檔案,包含了一條條的指令,每一條指令對應一層映象,指令的內容就描述了這一層該如何構建。如下示例了一個非常簡單的Dockerfile,

FROM nginx
RUN echo '<h1>Hello jboost!</h1>' > /usr/share/nginx/html/index.html

 

我們定製映象,必須要以某一個映象為基礎,在其上構建自己需要的層,如上示例中,我們是以nginx映象為基礎,然後在第二層定製了我們自己的內容——修改index.html的內容為<h1>Hello jboost!</h1>,這樣執行容器開啟nginx主頁時就不會顯示預設的頁面內容了。 

上面示例中接觸了Dockerfile的兩個指令

  • FROM:FROM指令指定基礎映象,每一個定製映象必須要有一個基礎映象,所以必須要有一條FROM指令,並且是Dockerfile的第一條指令
  • RUN:RUN指令指定需要執行的命令,後面接的命令就像是shell指令碼一樣可執行

Dockerfile還提供了許多其它指令,後續我們再集中介紹,本文只對接觸到的指令做簡單說明。

3. 自定義一個映象

這部分以一個Springboot專案為基礎,介紹自定義一個映象涉及的基本環節。專案地址為:https://github.com/ronwxy/swagger-register ,該專案是一個Swagger API文件註冊服務,其它專案可將Swagger API資訊註冊到該服務,進行統一檢視與管理。

3.1 定義Dockerfile檔案

首先,我們在專案的根目錄下建立一個Dockerfile檔案(檔名就叫Dockerfile),其內容為:

FROM openjdk:8-jdk-alpine
ENV PROFILE=dev
RUN mkdir /app /logs
COPY ./target/swagger-register-1.0.0-SNAPSHOT.jar /app/app.jar
WORKDIR /app
VOLUME /register-data
EXPOSE 11090
CMD ["java", "-Dspring.profiles.active=${PROFILE}", "-jar", "app.jar"]

 

從上往下依次介紹如下 

  • 第一行:FORM openjdk:8-jdk-alpine, 表示以openjdk:8-jdk-alpine這個映象為基礎映象,因為這是一個Springboot專案所以必須要有jdk支援,我們在定製映象時,可以找一個最適合的映象作為基礎映象。
  • 第二行:ENV PROFILE=dev, 定義了一個環境變數,這個環境變數可以在後面被引用
  • 第三行:RUN mkdir /app /logs,通過mkdir命令建立了兩個目錄,用來儲存jar執行檔案及日誌
  • 第四行:COPY ./target/swagger-register-1.0.0-SNAPSHOT.jar /app/app.jar 將target目錄下的jar包複製到/app目錄下,並且進行重新命名
  • 第五行:WORKDIR /app, 指定工作目錄為/app,後面各層的當前目錄就是指定的工作目錄
  • 第六行:VOLUME /register-data, 定義一個匿名資料卷,前面說過寫操作不要直接在容器內進行,而要改為寫掛載的資料卷目錄,這個定義可在執行容器時通過 -v 來覆蓋。
  • 第七行:EXPOSE 11090, 宣告瞭執行容器時提供的服務埠,也僅僅是個宣告而已,只是告訴使用的人要對映這個埠,通過 -p 可對映埠。
  • 第八行:CMD [“java”, “-Dspring.profiles.active=${PROFILE}”, “-jar”, “app.jar”], 指定了容器啟動命令,因為是一個Springboot專案,所以就是一個java -jar的執行命令,容器啟動的時候就會執行該命令來執行Springboot服務,這裡引用了第二行定義的環境變數PROFILE

3.2 配置maven外掛

定義好Dockerfile後,為了方便構建映象,我們可以藉助maven的dockerfile外掛dockerfile-maven-plugin,在pom.xml的build部分加入配置如下

<build>
    <plugins>
        <plugin>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-maven-plugin</artifactId>
        </plugin>
        <!-- Docker maven plugin -->
        <plugin>
            <groupId>com.spotify</groupId>
            <artifactId>dockerfile-maven-plugin</artifactId>
            <version>1.4.10</version>
            <configuration>
                <repository>${docker.image.prefix}/${project.artifactId}</repository>
                <buildArgs>
                    <JAR_FILE>target/${project.build.finalName}.jar</JAR_FILE>
                </buildArgs>
            </configuration>
        </plugin>
        <!-- Docker maven plugin -->
    </plugins>
</build>

 

repository指定了映象的名稱,docker.image.prefix需要properties部分進行定義,我這裡是springboot

3.3 構建映象

下載原始碼:https://github.com/ronwxy/swagger-register.git ,然後在專案的根目錄下執行如下命令(前提是本地已經裝好了docker與maven及jdk)

mvn clean package -Dmaven.test.skip=true dockerfile:build


該命令首先會執行mvn clean package -Dmaven.test.skip=true對專案進行打包,生成./target/swagger-register-1.0.0-SNAPSHOT.jar檔案,然後基於當前目錄下的Dockerfile檔案進行構建,如下圖所示 

docker-build

由上圖可看出,該映象構建分八步(對應Dockerfile的八行指令),每一步生成一個映象層,每一層都有唯一的ID。由圖中也可以看出,除了COPY之類的命令外,每一層的構建實際上是先基於上一層啟動一個容器,然後執行該層定義的操作,再移除這個容器來實現的,如第八步中

Step 8/8 : CMD ["java", "-Dspring.profiles.active=${PROFILE}", "-jar", "app.jar"]
[INFO] 
[INFO]  ---> Running in f4acd0b53bca
[INFO] Removing intermediate container f4acd0b53bca
[INFO]  ---> a9ee579f2d62

先啟動一個ID為f4acd0b53bca的容器,在其中執行CMD所定義的命令,然後再移除容器f4acd0b53bca,最後生成ID為a9ee579f2d62的映象。 

構建完後,我們就可以在本地映象中通過docker iamges看到我們定製的映象了,如圖
docker-image

圖中springboot/swagger-register映象即為我們剛剛構建好的定製映象。

3.4 啟動容器

我們可以通過以下命令來啟動一個剛才定製映象的容器

docker run -d --name swagger-register -p 11090:11090 -v /home/jenkins/swagger-register/register-data:/register-data -v /home/jenkins/swagger-register/logs:/logs --restart=always springboot/swagger-register:latest

其中: 

  • -d 表示以後臺程式方式執行
  • –name 指定容器名稱
  • -p 指定埠對映,左邊為宿主機埠,右邊為容器服務埠
  • -v 指定資料卷掛載,左邊為宿主機目錄,右邊為容器目錄
  • –restart=always 表示在docker啟動時自動啟動該容器

關於容器相關的內容後面詳細介紹,這裡不展開說明了。啟動容器後, 我們就可以瀏覽器開啟地址 http://宿主機ip:11090/doc.html 來訪問服務了(開啟頁面後內容是空的,因為沒有任何服務註冊Swagger API, 相關內容可參考 swagger api文件集中化註冊管理

4. 總結

本文介紹了一個基於Springboot專案的Docker映象定製及使用過程,對映象的構建過程,及Dockerfile的基本指令以及容器的執行做了基本介紹。後續會對Dockerfile的其它指令及Dockerfile的一些最佳實踐進行更為詳細的介紹,歡迎關注。


我的個人部落格地址:http://blog.jboost.cn
我的微信公眾號:jboost-ksxy (一個不只有技術乾貨的公眾號,歡迎關注,及時獲取更新內容)
—————————————————————————————————————————————————————
微信公眾號

相關文章