docker 是一套 Linux 的 LXC 管理工具.
LXC (Linux Containers) 的概念類似于虛擬機, 但是形式上有區(qū)別. 虛擬機更像是提供"機器環(huán)境", 而 LXC 則是提供"運行環(huán)境". 單看概念它們的區(qū)別有些微妙, 但是 LXC 的特點就是, 同樣是提供一套完全隔離的操作系統(tǒng)環(huán)境, 它很快, 超級快.
在使用上, 概念上的區(qū)別就是, 用虛擬機, 可能更多是想, 做一個電腦, 讓它跑起來, 然后再說讓這臺電腦干什么事.
而 docker 的使用, 則是做一個環(huán)境(一組進(jìn)程, 還有虛擬的設(shè)備等), 用環(huán)境來運行一個命令. 環(huán)境-命令 是一體的(一個容器), 命令一旦執(zhí)行完成, 那么一個容器實例的任務(wù)就結(jié)束了. 所以如果我們想讓一個容器像一臺電腦那樣, 通常我們給它一個像 /usr/bin/sshd -D
這樣的命令, 這個容器像一臺電腦, 是因為這個命令一直"沒有執(zhí)行完成"的效果.
虛擬機的使用, 一個鏡像就是一個安裝好的系統(tǒng). 而 docker 中, 鏡像更像是一張安裝光盤(刻盤后不能更改), 容器才是安裝好的系統(tǒng). 這種兩層式結(jié)構(gòu)相較于傳統(tǒng)的"快照"機制, 要好用得多. (如何從真正的系統(tǒng)安裝 ISO 鏡像得到 docker 鏡像, 我現(xiàn)在也不清楚怎么做)
更具體一些, 使用 docker , 就是在指定的環(huán)境中執(zhí)行一條命令, 比如:
docker run ubuntu:14.04 /bin/bash
意思就是, 在 ubuntu:14.04 這個環(huán)境中, 執(zhí)行 /bin/bash 這條命令. 當(dāng)然, 這條命令顯然是瞬間就執(zhí)行完了的. 如果和這個命令立即有交互, 那么需要一些參數(shù):
docker run -t -i ubuntu:14.04 /bin/bash
-t
是分配一個虛擬終端, -i
是獲取當(dāng)前的輸入. 這樣你可以立即使用一個終端來和這個環(huán)境交互了.
雖然終端是正常使用電腦最常用的交互方式, 不過真實使用 docker 的場景中, 會這樣用的機會不會很多的. 通常是直接執(zhí)行我們要做的事, 比如運行一個服務(wù), 或者執(zhí)行一系列的計算.
使用 nc
來作一個例子:
docker run -t ubuntu:14.04 nc -l 8000
加上 -t
是因為需要一個終端來顯示輸出, 否則 nc
的標(biāo)準(zhǔn)輸出就沒地方去了.
docker 安裝之后, 會自動在系統(tǒng)中作一個網(wǎng)橋配置, run
出來的每個容器實例, 都會分配一個橋接的 IP 地址. 上面的命令執(zhí)行之后, 已經(jīng)有容器在運行了, 并且在其中, nc
正監(jiān)聽著 8000
端口. 我們要接上去試試, 首先需要找到這個容器實例的 IP 地址.
先看當(dāng)前運行著的實例列表:
docker ps
你先看到下面的信息:
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES e1d0c9193025 ubuntu:14.04 nc -l 8000 5 seconds ago Up 4 seconds silly_curie
記下 ID , 不需要全部, 前面幾位就可以了, 然后查看指定容器實例的細(xì)節(jié):
docker inspect e1d0
會輸出一串 json 字符串, 里面會有這樣一節(jié):
"NetworkSettings": { "Bridge": "docker0", "Gateway": "172.17.42.1", "IPAddress": "172.17.0.82", "IPPrefixLen": 16, "PortMapping": null, "Ports": {} },
可以看到, 容器的 IP 是 172.17.0.82
, 上面的網(wǎng)關(guān) IP 172.17.42.1
就是你"實體機"的.
在實體機使用 telnet
連上去:
telnet 172.17.0.82 8000
現(xiàn)在能看到效果了.
^]
然后 quit
退出, nc
那邊結(jié)束執(zhí)行, 命令執(zhí)行完, 之前的那個容器實例也就關(guān)閉了. 你使用 docker ps
看不到. 但是使用:
docker ps -a
就能看到所有的容器實例. 在這里列出的實例是真實存在的, 只是當(dāng)前并沒有運行起來而已. 你可以隨時讓其中的實例再運行起來:
docker start e1d0c9193025
這樣你又可以 telnet
, 只是沒地方看輸出.
回顧上面的過程, 提出兩個概念, 鏡像 和 容器 .
鏡像 指上面的 ubuntu:14.04
這種, 嗯, 這種環(huán)境, 這種系統(tǒng). 后面會講如何做一個自己的 鏡像 .
容器 是在具體的 鏡像 上 run
具體的命令, 得到的一個"綁定狀態(tài)". run
命令執(zhí)行時的一些參數(shù)(比如和實體機的端口映射), 也是"狀態(tài)"的一部分, run
過之后就不能更改了.
它們的關(guān)系, 有些像編程語言中的 類 和 實例 . run
時的命令就像是類實例化時的參數(shù). 后面會提到, 你可以刪除 容器 , 也可以刪除 鏡像 . 當(dāng)你想刪除 鏡像 , 但是使用它的 容器 還存在時, 你會得到操作失敗的提示.
類 有繼承關(guān)系, 得利于 AUFS 這些的層級文件系統(tǒng), 鏡像 的構(gòu)建也是這種層層封裝的結(jié)果.
更多建議: