原文地址: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檔案進行構建,如下圖所示
由上圖可看出,該映象構建分八步(對應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
看到我們定製的映象了,如圖
圖中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 (一個不只有技術乾貨的公眾號,歡迎關注,及時獲取更新內容)
—————————————————————————————————————————————————————