Docker筆記(五):整一個自己的鏡像


原文地址:http://blog.jboost.cn/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 (一個不只有技術干貨的公眾號,歡迎關注,及時獲取更新內容)
—————————————————————————————————————————————————————
微信公眾號

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM