如何評價Docker最新版本1.6?
有哪些新特性?是否可以用在生產環境中
有嚴重的問題,內存泄露,container狀態有問題。
生產環境中不要用1.6,要麼1.5, 要麼等1.7
Docker 1.6.0的發布,絕對是Docker圈的重磅炸彈。表面上看,這些改動大大完善了Docker的功能,然而細看這些特性,筆者倒是感受到Docker在醞釀著什麼驚人的大招。
首先,來看一下筆者對Docker 1.6.0新特性的理解。
一.Builder方面1. 允許從一個鏡像ID開始build新鏡像
換言之,Dockerfile中的FROM命令後面可以緊跟一個鏡像ID。好處是Dockerfile的書寫變得靈活,在熟悉Docker鏡像原理的情況下,可以大大提高Docker鏡像build的效率。簡單場景如下,Dockerfile中有兩條RUN命令,第一條命令非常耗時,且運行成功了,而第二條命令失敗。此情形下,完全可以藉助前者完成的鏡像繼續build。當然有人會提到本地image cache的問題同樣可以解決該問題,但是image cache的弊端就是只能本地有效。
2. Build鏡像時允許添加限制參數
這個改動,筆者的感受是:久旱逢甘露,但是僅僅是幾滴。Docker對於docker run命令的限制,即啟動容器時做的資源等種種限制,目前看來還是差強人意。但需要清楚的是,docker build流程中對於RUN命令,Docker Daemon本身也會啟動一個容器,並通過commit容器打成鏡像。此時,如果對於運行RUN命令的容器沒有限制,後果可想而知。為什麼說「甘露」僅僅是幾滴,原因是:docker run命令的限制參數目前還沒有全部集成至docker build,而通過Docker Daemon來統一化配置又缺乏靈活。
二.Client方面:支持Windows考慮到廣大的Windows用戶群體,這肯定是好事一樁,但筆者竊以為Docker官方對Win粉的愛也只能到這裡了。
三. Runtime方面1. 容器label與鏡像label
Label的概念,不知道大家對她是否似曾相識。早在很早之前,Docker Daemon就支持添加label,用於記錄Docker Daemon的角色。Label使得Docker Daemon帶有角色,從而Swarm可以方便的通過角色進行Docker的管理。而如今,label可以添加到容器和鏡像,原來由Docker外的軟體或者人腦記錄的容器角色,現在可以顯性的放在容器的label中了,大大環節容器角色的管理。更大的好處是,label可以在邏輯上關聯容器,會不會在邏輯上有「組」的概念?
2. 容器的–cgroup-parent參數
將容器A的cgroup指定到容器B的cgroup內,從而嵌套情況下,A、B的受限效果將建立管理。容器host網路模式或者other container模式使得容器的隔離留有選擇餘地,為Docker場景模式的探索帶來更大的可能性。如今cgroup都嵌套之後,容器與容器間的粘性再一次被放到檯面上,畢竟不是所有容器從邏輯上講是完全隔離的。這一點,絕對是可挖掘性巨大的特性。
3. logging driver
Docker接管了容器的日誌管理。從實現的角度來說,貌似不難,這個需求應該也是巨大的。只是苦了那些立志佔領Docker容器日誌市場的小廠商,如logspout就被Docker很禮貌的請出了遊戲。
4. 通過鏡像ID下載鏡像
這一特性的推出,也許在Private Registry中發揮的效果更大。熟悉了鏡像原理之後,你會發現,公有的環境下,很少有人會去關注repo下tag化鏡像的某個parent鏡像包含哪些內容,這一點也很不現實。私有registry就不一樣了,私有鏡像的製作,環節、內容自己應該都清楚,如此一來,通過鏡像ID下載鏡像,意義會逐漸體現出來。
5. –ulimit參數–default-ulimit
千呼萬喚等出來,安全利器。先來看看兩者的區別吧,簡單來講,–ulimit的使用僅僅與docker run命令;若不指定–ulimit,–default-ulimit才會在docker run的情況下有效。再看這倆參數的作用:限制容器的資源使用情況,那就不是簡單的CPU、Mem了。相信大家肯定一直聽說,容器技術有一點弊病就是容器和宿主機共享內核,CPU、Mem等的隔離度有缺陷,其實共享內核的缺陷遠不僅如此,內核的資源是否還應該包括,文件數、進程數、信號數、管道數、系統調用等?那麼問題出現了,namespace和cgroup並沒有考慮到所有的情況,而ulimit可以站出來暫時讓Docker的安全避避風聲。簡單的測試如下:若調小–default-ulimit的文件數參數之後,進入容器查看ulimit –a,open files參數就變小了,大家可以測試一番。
容器粘性關於調度,容器安全牽扯內核,鏡像的靈活,如果您還不知道鏡像是什麼原理,就out啦。
有關Docker 1.6的詳細介紹,請參考官方博客:
Docker 1.6: Engine Orchestration Updates, Registry 2.0, Windows Client Preview
轉自 -深度解析 Docker 1.6.0
不謝邀。這個問題我一定要回答~下面是我前段時間寫的微信公眾號文章,正好談到了這個問題。
原文鏈接:Docker 1.6新體驗
近日,Docker發布了最新版本Docker 1.6。和前一版本相比,新版本的Docker有了一系列振奮人心的重大更新,體驗有了極大的提升。下面我們就來看看這些新特性。
對Windows的支持
在之前的版本中,Docker的運行依賴於一些Linux特有的內核特性,所以,它不能直接運行在非Linux的操作系統之上。以Mac OSX為例,為了解決這一問題,有以下兩種方案:
- 在宿主操作系統中安裝Linux虛擬機,在其中運行Docker引擎。
- 使用Boot2Docker
事實上,上述兩種方案本質上是一致的。在第一種方式里,用戶需要處理好宿主機、虛擬機以及容器的網路拓撲結構,還需要不時地使用SSH登錄到虛擬機中,對Docker容器進行管理。而在第二種方式里,Boot2Docker並非真正的Docker引擎,而是一個輕量級的VirtualBox虛擬機(其中已包含Docker)和一個管理工具。和第一種方式相比,Boot2Docker的最大作用,是大大簡化了Docker容器的部署和管理。
回到Windows的情況。這次發布的新版本,對Windows的支持,其實只不過是提供了Windows下的Boot2Docker而已。
如何使用
首先,需要設置相應的環境變數:
set DOCKER_HOST=tcp://&
set DOCKER_CERT_PATH="C:Users\%USERPROFILE%.boot2dockercertsoot2docker-vm"
set DOCKER_TLS_VERIFY=1
然後,在cmd.exe中運行以下命令:
備註- 如前所述,由於Docker Engine本質上還是基於Linux內核的,所以,除非真正的Windows版Docker Engine被開發出來,用戶依然只能在Docker中運行基於Linux的容器。
- 由於Docker容器是在VirtualBox虛擬機下運行的,所以會有一定的性能損失。
鏡像和容器的標籤
和Git類似,在Docker裡面,鏡像和容器使用一個64位元組的hash id作為唯一標識。使用下面這兩個命令可以體會這一點:
docker ps --no-trunc
docker images --no-trunc
在Docker 1.6中,用戶可以為容器或鏡像添加LABEL,大大提升Docker的管理便捷程度。
為了給鏡像添加標籤,可以在Dockerfile中使用LABEL命令:
FROM ubuntu
LABEL name=zephyre
Build之後,就可以用過下面這個命令,根據標籤查找鏡像了:
docker images -f label=name=zephyre
如果從上述鏡像啟動容器,則該標籤會應用在容器之上,並且可以用和上面類似的語法進行搜索:
docker run --name test test echo "I am bar"
docker inspect -f "" test
docker ps -a -f label=name=zephyre
我們甚至還可以在啟動容器的時候,添加多個標籤:
docker run --name test2 -l name=foobar test echo "I am foo"
Logging Driver
Docker容器的日誌處理,一向是個令人頭疼的問題。
我們先回顧一下在之前的版本中,Docker是如何保存日誌的。眾所周知,docker logs $CID可以用來查看容器CID產生的日誌。這條命令的背後,是Docker引擎將容器的標準輸出重定向到一個json格式的文件中。
$ CID=$(docker run -d ubuntu echo "Hello")
$ echo $CID
5594248e11b7d4d40cfec4737c7e4b7577fe1e665cf033439522fbf4f9c4e2d5
$ sudo cat /var/lib/docker/containers/$CID/$CID-json.log
{"log":"Hello
","stream":"stdout","time":"2015-03-30T00:34:58.782658342Z"}
而對於容器自身寫入的日誌文件,一般來說,有下面幾種方式來處理:
- 在容器內部,開啟一個搜集容器的進程。缺點:繁瑣,不利於管理,同時也違背了one-container-one-process的原則。
- 在啟動容器的時候,將host上的某個路徑mount上去。容器生成的日誌放在該路徑裡面,然後在host,啟用一個日誌搜集程序。
- 和上面一條類似,只不過不是將host上的某個路徑進行掛載,而是建立一個數據卷容器,然後使用--volumes-from選項,將其映射到任務容器中。
Docker 1.6開始支持log driver,支持下面幾種類型:
- json-file:該類型就是上面提到的,將標準輸出重定向到/var/lib/docker/containers/$CID/$CID-json.log的方式。
- syslog:將日誌輸出到syslog
- none:禁用日誌搜集功能。注意:此時,docker logs命令也被禁用了。
在啟動容器的時候,可以通過--log-driver選項來指定:
docker run -d --log-driver=syslog ubuntu echo "Hello"
使用digest來標識鏡像
Docker的鏡像是建立在Aufs基礎上的。通過Aufs,可以將不同的目錄mount在一個虛擬文件系統中,形成一種分層的模型。在建立鏡像時,每個寫操作,都被視為一種增量操作,即在原有的數據層上,添加一個新的層次,如下圖所示。
在以前的版本中,如果要pull一個鏡像,需要指定它的name和tag,比如:docker pull ubuntu:latest
考慮這樣一個鏡像:
$ docker history ubuntu:latest
IMAGE CREATED CREATED BY SIZE
d0955f21bf24 5 weeks ago /bin/sh -c #(nop) CMD [/bin/bash] 0 B
9fec74352904 5 weeks ago /bin/sh -c sed -i "s/^#s*(deb.*universe)$/ 1.895 kB
a1a958a24818 5 weeks ago /bin/sh -c echo "#!/bin/sh" &> /usr/sbin/polic 194.5 kB
f3c84ac3a053 5 weeks ago /bin/sh -c #(nop) ADD file:777fad733fc954c0c1 192.5 MB
511136ea3c5a 22 months ago 0 B
可以看見,上述鏡像的歷史,是由若干layer組成的(如d0955f21bf24, 9fec74352904,a1a958a24818等)。然而,在1.6版本之前,只能對ubuntu:latest進行pull操作,而無法實現pull任意一個layer。這一限制,在Docker 1.6里被打破了。我們現在可以在pull時,使用相應的digest:
docker pull ubuntu@sha256:9fec74352904baf5ab5237caa39a84b0af5c593dc7cc08839e2ba65193024507
Ulimits
在1.6之前,Docker容器的ulimit設置,繼承自docker daemon。在很多時候,對於單個容器來說,這樣的ulimit實在是太高了。在Docker 1.6里,可以設置全局默認的ulimit:
docker -d --default-ulimit nproc=1024:2048
或者在啟動容器時,單獨對其ulimit進行設置:
docker run -d --ulimit nproc=2048:4096 httpd
Dockerfile指令
最後,讓我們再來看一個望眼欲穿的功能:在commit和import的時候,使用Dockerfile指令。假設現在我們有一個容器c3f279d17e0a。在將其commit成新的鏡像時,可以執行一段Dockerfile指令:
docker commit --change "ENV DEBUG true" c3f279d17e0a foo/bar:v2
在以前,為了做到這一點,我們需要先commit成鏡像ImageA,然後寫一個Dockerfile:FROM ImageA,再build成鏡像ImageB,很繁瑣。
Cool~
參考
- Boot2Docker for Windows
- Docker Windows Client是在微軟的幫助下開發的。Ahmet Alp Balkan (@ahmetalpbalkan)是主要貢獻者。
- 參考了Markus Eisele的blog(可能需要翻牆)
推薦閱讀: