天天看點

docker專題(2):docker常用管理指令(上)

本文隻記錄docker指令在大部分情境下的使用,如果想了解每一個選項的細節,請參考官方文檔,這裡隻作為自己以後的備忘記錄下來。

根據自己的了解,總的來說分為以下幾種:

容器生命周期管理 — <code>docker [run|start|stop|restart|kill|rm|pause|unpause]</code>

容器操作運維 — <code>docker [ps|inspect|top|attach|events|logs|wait|export|port]</code>

容器rootfs指令 — <code>docker [commit|cp|diff]</code>

鏡像倉庫 — <code>docker [login|pull|push|search]</code>

本地鏡像管理 — <code>docker [images|rmi|tag|build|history|save|import]</code>

其他指令 — <code>docker [info|version]</code>

看一個變遷圖

docker專題(2):docker常用管理指令(上)

其中我們可以根據repository來判斷這個鏡像是來自哪個伺服器,如果沒有 / 則表示官方鏡像,類似于<code>username/repos_name</code>表示github的個人公共庫,類似于<code>regsistory.example.com:5000/repos_name</code>則表示的是私服。

image id列其實是縮寫,要顯示完整則帶上<code>--no-trunc</code>選項

<code>usage: docker search term</code>

搜尋的範圍是官方鏡像和所有個人公共鏡像。name列的 / 後面是倉庫的名字。

<code>usage: docker pull [options] name[:tag]</code>

上面的指令需要注意,在docker v1.2版本以前,會下載下傳官方鏡像的centos倉庫裡的所有鏡像,而從v.13開始官方文檔裡的說明變了:will pull the centos:latest image, its intermediate layers and any aliases of the same id,也就是隻會下載下傳tag為latest的鏡像(以及同一images id的其他tag)。

也可以明确指定具體的鏡像:

當然也可以從某個人的公共倉庫(包括自己是私人倉庫)拉取,形如<code>docker pull username/repository&lt;:tag_name&gt;</code> :

如果你沒有網絡,或者從其他私服擷取鏡像,形如<code>docker pull registry.domain.com:5000/repos:&lt;tag_name&gt;</code>

與上面的pull對應,可以推送到docker hub的public、private以及私服,但不能推送到top level repository。

registry.tp-link.net也可以寫成ip,172.29.88.222。

在repository不存在的情況下,指令行下push上去的會為我們建立為私有庫,然而通過浏覽器建立的預設為公共庫。

當利用 docker run 來建立容器時,docker 在背景運作的标準操作包括:

檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載下傳

利用鏡像建立并啟動一個容器

配置設定一個檔案系統,并在隻讀的鏡像層外面挂載一層可讀寫層

從宿主主機配置的網橋接口中橋接一個虛拟接口到容器中去

從位址池配置一個 ip 位址給容器

執行使用者指定的應用程式

執行完畢後容器被終止

<code>usage: docker run [options] image [command] [arg...]</code>

這是最簡單的方式,跟在本地直接執行<code>echo 'hello world'</code> 幾乎感覺不出任何差別,而實際上它會從本地ubuntu:latest鏡像啟動到一個容器,并執行列印指令後退出(<code>docker ps -l</code>可檢視)。需要注意的是,預設有一個<code>--rm=true</code>參數,即完成操作後停止容器并從檔案系統移除。因為docker的容器實在太輕量級了,很多時候使用者都是随時删除和新建立容器。

容器啟動後會自動随機生成一個<code>container id</code>,這個id在後面commit指令後可以變為<code>image id</code>

上面的<code>--name</code>參數可以指定啟動後的容器名字,如果不指定則docker會幫我們取一個名字。鏡像<code>centos:centos6</code>也可以用<code>image id</code> (68edf809afe7) 代替),并且會啟動一個僞終端,但通過ps或top指令我們卻隻能看到一兩個程序,因為容器的核心是所執行的應用程式,所需要的資源都是應用程式運作所必需的,除此之外,并沒有其它的資源,可見docker對資源的使用率極高。此時使用exit或ctrl+d退出後,這個容器也就消失了(消失後的容器并沒有完全删除?)

(那麼多個tag不同而image id相同的的鏡像究竟會運作以哪一個tag啟動呢

它将直接把啟動的container挂起放在背景運作(這才叫saas),并且會輸出一個<code>container id</code>,通過<code>docker ps</code>可以看到這個容器的資訊,可在container外面檢視它的輸出<code>docker logs ae60c4b64205</code>,也可以通過<code>docker attach ae60c4b64205</code>連接配接到這個正在運作的終端,此時在<code>ctrl+c</code>退出container就消失了,按ctrl-p ctrl-q可以退出到主控端,而保持container仍然在運作

另外,如果-d啟動但後面的指令執行完就結束了,如<code>/bin/bash</code>、<code>echo test</code>,則container做完該做的時候依然會終止。而且-d不能與--rm同時使用

可以通過這種方式來運作memcached、apache等。

映射主機到容器的端口是很有用的,比如在container中運作memcached,端口為11211,運作容器的host可以連接配接container的 internel_ip:11211 通路,如果有從其他主機通路memcached需求那就可以通過-p選項,形如<code>-p &lt;host_port:contain_port&gt;</code>,存在以下幾種寫法:

目錄映射其實是“綁定挂載”host的路徑到container的目錄,這對于内外傳送檔案比較友善,在搭建私服那一節,為了避免私服container停止以後儲存的images不被删除,就要把送出的images儲存到挂載的主機目錄下。使用比較簡單,<code>-v &lt;host_path:container_path&gt;</code>,綁定多個目錄時再加<code>-v</code>。

下面是一個例子:

在主機的/tmp/docker下建立index.html,就可以通過<code>http://localhost:80/</code>或<code>http://host-ip:80</code>通路了。

當我們在制作自己的鏡像的時候,會在container中安裝一些工具、修改配置,如果不做commit儲存起來,那麼container停止以後再啟動,這些更改就消失了。

<code>docker commit &lt;container&gt; [repo:tag]</code>

後面的repo:tag可選

隻能送出正在運作的container,即通過<code>docker ps</code>可以看見的容器,

-a "[email protected]"

請注意,當你反複去commit一個容器的時候,每次都會得到一個新的<code>image id</code>,假如後面的<code>repository:tag</code>沒有變,通過<code>docker images</code>可以看到,之前送出的那份鏡像的<code>repository:tag</code>就會變成<code>&lt;none&gt;:&lt;none&gt;</code>,是以盡量避免反複送出。

另外,觀察以下幾點:

commit container隻會pause住容器,這是為了保證容器檔案系統的一緻性,但不會stop。如果你要對這個容器繼續做其他修改:

你可以重新送出得到新image2,删除次新的image1

也可以關閉容器用新image1啟動,繼續修改,送出image2後删除image1

當然這樣會很痛苦,是以一般是采用<code>dockerfile</code>來<code>build</code>得到最終image,參考[]

雖然産生了一個新的image,并且你可以看到大小有100mb,但從commit過程很快就可以知道實際上它并沒有獨立占用100mb的硬碟空間,而隻是在舊鏡像的基礎上修改,它們共享大部分公共的“片”。