DockerCon 2017: Docker新特性初體驗
DockerCon2017已經結束了,從去年的版本到現在,Docker產生了很多的變化。Docker的開發者們一直強調他們希望Docker的體驗越簡單越好。觀察下最近幾個月Docker的新特性,你會發現所言非虛,DockerCon2017大會也向我們展示了這一點。下麵介紹下Docker最近幾個月發布的新特性
多階段構建
構建一個鏡像一般需要多個階段。
- 編譯你的應用
- 然後跑測試
- 當測試通過時,你將你的應用打包成可部署的軟件包
- 最後你把軟件包添加到鏡像裏麵
你可以將這些步驟都放進一個Dockerfile中,但是這會導致鏡像膨脹,加入了很多最終產品不需要的內容。例如編譯和構建的框架,Docker鏡像存儲需要的空間也會變得很大。
一個解決方法是在Docker外麵編譯測試打包應用程序,或者使用多個Dockerfile。你可以用一個Dockerfile來編譯測試打包你的應用,用另外一個Dockerfile來添加之前打好的軟件包,並做最終的交付。
然而,整個構建的過程通過一個腳本捆綁在一起,而並不是以Docker的方式來執行構建。
Docker對於添加新的特性或者語法到Dockerfile中是謹慎的,當他們最終決定著手通過一個簡單而優雅的方式來解決這個構建的問題。通過引入多階段構建(multi-stage builds)
,使得通過使用多個FROM
指令來定義多個構建的階段成為可能。示例如下
# First stage to build the application
FROM maven:3.5.0-jdk-8-alpine AS build-env # build-env構建階段的開始
ADD ./pom.xml pom.xml
ADD ./src src/
RUN mvn clean package # build-env 構建階段在此結束
# Final stage to define our minimal runtime
FROM FROM openjdk:8-jre # 新的構建階段的開始
COPY --from=build-env target/app.jar app.jar
RUN java -jar app.jar
每一次使用FROM
指令時,相當於定義了一個新的構建階段,一直到下一個FROM
指令之前或者到文件的結束為止,執行的指令均屬於該構建階段。通過AS
指令來給這一構建階段命名,同時指定了該階段使用的基礎鏡像。在接下來的構建階段,可以使用COPY --from=<stage>
指令來拷貝之前構建階段的軟件製成品到當前構建階段,繼續進行構建,直到最後一個構建階段生成的鏡像,才是最終的交付鏡像。通過對最終構建階段的基礎鏡像選擇,可以隻讓交付鏡像包含最小的運行時和需要交付軟件製成品,使得鏡像變小,上傳下載更加迅速。
該特性是Docker 17.05版本的一部分,敬請期待,待版本穩定後,容器服務也會支持該特性
在FROM
指令中使用參數指定鏡像版本
在Dockerfile中使用參數,並不是一件新鮮的事物,我們已經可以使用ARG
指令來傳遞參數給構建過程,這些參數的值在Dockerfile中是可變的,經常被用來傳遞版本號,密碼,例如SSH的密鑰等。現在通過參數來指定基礎鏡像的版本也成為了可能,示例如下:
ARG GO_VERSION=1.8
FROM golang:${GO_VERSION}
ADD . /src
WORKDIR /src
RUN go build
CMD ["/bin/app"]
通過使用上麵的Dockerfile,我們可以構建基於另外一個GO語言版本的鏡像:
$ docker build --arg=GO_VERSION=1.7 .
清理Docker資源
使用Docker的開發者經常會抱怨Docker占用了太多的存儲空間,如果不定期清理,這確實是個問題。Docker增加了docker system
子命令來檢查磁盤的使用空間,同時清理無用的資源。
下麵的命令列出了磁盤使用情況:
$ docker system df
TYPE TOTAL ACTIVE SIZE RECLAIMABLE
Images 7 5 1.247GB 769MB (61%)
Containers 7 2 115.9MB 99.23MB (85%)
Local Volumes 1 1 85.59MB 0B (0%)
你可以使用prune
來清理不再需要的資源:
$ docker system prune
WARNING! This will remove:
- all stopped containers
- all volumes not used by at least one container
- all networks not used by at least one container
- all dangling images
Are you sure you want to continue? [y/N] y
隻清理特定子係統的資源也是支持的:
$ docker image/container/volume/network prune
指定端口時增加可讀性
由於指定端口的語法讓人困惑,Docker的使用者經常在理解和定義一個容器發布的端口時有困難。當你在使用或者定義容器的端口時,可能的格式如下:
ports:
- 3000
- 3000-3005
- 49100:22
- 9090-9091:8080-8081
- 127.0.0.1:8001:8080-8081
- 6060:7060/udp
當使用客戶端時,這些語法還比較容易理解,但是當你需要在一個compose模版中定義許多這樣的端口時,可讀性就會變得很差。為了解決這一問題,現在你可以使用一個更加詳細的格式來定義端口:
ports:
- target: 6060 # 容器端口
published: 7060 # 映射到主機暴露的端口
protocol: udp # 使用的協議
指定數據卷時增加可讀性
跟端口一樣,數據卷(volume)
也有類似的語法:
volumes:
- /var/lib/mysql
- /opt/data:/var/lib/mysql
- ./cache:/tmp/cached
- datavolume:/var/lib/mysql
- ~/configs/etc/configs/:ro
也增加了一個更加詳細的語法來聲明和指定數據卷(volume)
:
volumes:
- type: bind
source: ~/configs
target: /etc/configs
read_only: true
最後更新:2017-04-25 16:00:39