優化Docker鏡像,加速應用部署,教你幾個小竅門
Docker 包含三個基本概念,分別是鏡像(Image)、容器(Container)和倉庫(Repository)。Docker 鏡像可以看作是一個特殊的文件系統,除了提供容器運行時所需的程序、庫、資源、配置等文件外,還包含了一些為運行時準備的一些配置參數(如匿名卷、環境變量、用戶等)。鏡像是 Docker 運行容器的前提,是Docker的核心。要想利用Docker鏡像快速構建一個高性能的應用,首先你要制作一個好的鏡像。
如何制作一個好的鏡像?下面教你幾個小訣竅。
一、明確指定鏡像版本,管理更方便
為了讓版本管理起來更方便,應用部署速度更快,在創建鏡像的過程中,建議工程師們明確指定包含版本或者其他輔助信息的tag。如果不指定鏡像tag,默認會使用latest。這樣,每次啟動應用實例時,都需要去鏡像倉庫檢查鏡像是否更新。這種方式不利于版本管理,對應用啟動速度也有一定影響。
二、減小鏡像體積
1、使用alpine版本的基礎鏡像,來減小鏡像體積,以保證部署和擴容速度。
alpine是一個高度精簡但又包含了基本工具的輕量級Linux發行版,本身的Docker鏡像只有4~5M大小,各開發語言和框架都有基于alpine制作的基礎鏡像。因此,在開發自己應用的鏡像時,要選擇這些鏡像作為基礎鏡像,這樣可以大大減小鏡像的體積。
如下是各種語言對應的基礎鏡像:
- Java(Spring Boot): - openjdk:8-jdk-alpine,openjdk:8-jre-alpine等
- Java(Tomcat) - tomcat:8.5-alpine等
- Nodejs - node:9-alpine, node:8-alpine等
- Python - python:3-alpine, python:2-alpine等
- PHP - 基于php:7-fpm-alpine,php:5-fpm-alpine等鏡像添加nginx,參考https://hub.docker.com/r/trafex/alpine-nginx-php7/
- Ruby:ruby:2-alpine等
- Go/可執行文件 - 直接基于alpine鏡像,把編譯后的可執行文件打入鏡像。因為alpine不同于普通的Ubuntu/Centos等發行版,需要靜態編譯和鏈接應用代碼,例如Go需要關閉cgo:CGO_ENABLED=0 go build ...
- 靜態頁面 - nginx:1-alpine等
2、保證Dockerfile中的清理命令在同一行,也可以減小鏡像體積。
Dockerfile的每條指令都會產生一個文件層,文件層越多鏡像體積就越大。因此,對于不需要產生文件層的命令,要盡量合并到一起。比如,組件的安裝清理就可以放在一條命令里面。如下:
三、減小鏡像傳輸大小
Docker在build鏡像的時候,如果某個命令相關的內容沒有變化,會使用上一次緩存(cache)的文件層,在上傳到鏡像倉庫時,這一層也就不需要上傳了。利用這一點,在添加應用的時候可以分層添加,具體操作如下:
(1)將不變或者變化很少的體積較大的依賴庫和經常修改的自有代碼分開。
(2)因為cache緩存在運行Dockerbuild命令的本地機器上,因此,建議固定使用某臺機器來進行Docker build,以便利用cache。
舉個例子:
在構建Spring Boot應用鏡像,我們可以通過以下操作來進行分層。
1、在Dockerfile所在目錄,解壓縮maven生成的jar包
- unzip <path-to-app-jar>.jar -d app
2、在Dockerfile中我們把應用的內容分成4個部分COPY到鏡像里面:其中前面3個基本不變,第4個是經常變化的自有代碼。最后一行是解壓縮后,啟動spring boot應用的方式。如下:
四、避免使用進程管理程序來保證應用健康運行
在應用的某個實例崩潰或者非正常退出時,很多進程管理程序并不退出,導致平臺無法檢測到應用已經不可用,進而無法重啟應用。所以,要避免使用這類進程管理程序來啟動鏡像。
五、保證數據和日志持久化存儲
1、避免使用本地存儲。應用鏡像啟動后,文件系統是臨時的,崩潰后即被銷毀。持久化數據,文件等需要存儲到SDS,FDS等后端存儲服務中
2、應用日志不能寫到本地文件,需要寫到標準輸出或者標準錯誤,平臺負責收集、匯總和后續的各種處理























