掌握一門語(yǔ)言,需要多寫代碼。掌握docker架構(gòu),可以多運(yùn)行docker命令。通過(guò)簡(jiǎn)單的命令就可以實(shí)現(xiàn)很多你千方百計(jì)都難以實(shí)現(xiàn)的功能。不信,咱走著瞧。
主機(jī)上的docker主要分為兩部分,一個(gè)是具有REST風(fēng)格的API守護(hù)進(jìn)程,一個(gè)是與守護(hù)進(jìn)程通信的客戶端。平常我們通過(guò)命令行運(yùn)行的docker run等命令中的docker就是客戶端,客戶端接收用戶指令后轉(zhuǎn)化為RESTAPI調(diào)用,通過(guò)http來(lái)與守護(hù)進(jìn)程通信。守護(hù)進(jìn)程則負(fù)責(zé)完成指令的最終實(shí)施,例如鏡像的管理和編譯,容器的運(yùn)行等等。由于客戶端和docker守護(hù)進(jìn)程之間是通過(guò)http通信的,兩者實(shí)際上可以位于不同的主機(jī)上。
從上圖中我們可以看出,除了docker hub之外,我們還可以搭建自己的docker注冊(cè)中心,從而實(shí)現(xiàn)私有化。(docker hub上面的鏡像是完全公開的)
既然說(shuō)到客戶端和守護(hù)進(jìn)程可以分開,那我們就嘗試把他們分開試試。
默認(rèn)的情況下,docker客戶端是通過(guò)/var/run/docker.sock域套接字來(lái)訪問(wèn)守護(hù)進(jìn)程的,而守護(hù)進(jìn)程也一直在這個(gè)socket上監(jiān)聽(tīng)來(lái)自客戶端的命令。要把他們分離,就首先要打破這個(gè)默認(rèn)的接口。因此首先需要停止docker守護(hù)進(jìn)程。例如:
sudo service docker stop
缺省的守護(hù)進(jìn)程停止之后,就可以按照我們的需求來(lái)啟動(dòng)守護(hù)進(jìn)程了:
docker daemon -H tcp://0.0.0.0:2375
如果另一臺(tái)主機(jī)要訪問(wèn)它,需要知道運(yùn)行著上述守護(hù)進(jìn)程的主機(jī)的IP地址:
docker -H tcp://<守護(hù)進(jìn)程所在主機(jī)ip>:2375
很多時(shí)候,容器也是一個(gè)服務(wù)器,它就需要以守護(hù)進(jìn)程方式運(yùn)行
docker run -d -i -p1234:123 --name daemon ubuntu nc -l 1234
解釋一下,-d標(biāo)志將以守護(hù)進(jìn)程方式運(yùn)行容器,-i標(biāo)志賦予容器域telnet繪畫交互能力, -p使得將主機(jī)的1234端口綁定到容器的123端口,如果有兩個(gè)容器,那么可以同時(shí)運(yùn)行起來(lái),只要主機(jī)端口不同即可。--name賦予容器一個(gè)名稱,以便后續(xù)引用。最后nc全稱為netcat,是在1234端口運(yùn)行一個(gè)簡(jiǎn)單的監(jiān)聽(tīng)?wèi)?yīng)答(echo)服務(wù)器,
例如telnet localhost 1234鏈接上一個(gè)運(yùn)行中的容器后,你給容器發(fā)送的命令,可以在結(jié)束telnet之后用docker logs daemon(容器名)查看到。
除此之外,還可以使用--restart=no 表明一旦發(fā)生守護(hù)進(jìn)程推出的情況,不需要重啟該容器。always則表示總是自動(dòng)重啟,on-failure[:max-retry]表示只有失敗時(shí)重啟。unless-stopped表示總是自動(dòng)重啟,除非用戶手動(dòng)停止。
對(duì)于想更多了解docker實(shí)際運(yùn)行狀況的人來(lái)說(shuō),這是一個(gè)很好的工具。它能將客戶端和docker守護(hù)進(jìn)程之間的通信過(guò)程輸出,以便我們了解某個(gè)docker命令到底時(shí)如何通過(guò)api實(shí)現(xiàn)的。
實(shí)現(xiàn)起來(lái)也很簡(jiǎn)單,一條命令即可:
socat -v UNIX-LISTEN:/tmp/dockerapi.sock,fork UNIX-CONNECT:/var/run/docker.sock &
-v用于提高輸出的可讀性,帶有數(shù)據(jù)流的指示。
UNIX-LISTEN部分是讓socat在一個(gè)unix socket上進(jìn)行監(jiān)聽(tīng)
UNIX-CONNECT部分是socat鏈接到docker的unix socket。這樣雙向流量都會(huì)被socket看到,并與docker客戶端所提供的任何輸出一起記錄到終端日志中。
socat不僅用于這里,對(duì)于其他網(wǎng)絡(luò)服務(wù)也可以使用。
一般來(lái)說(shuō),容器之間的通信時(shí)必須的。一個(gè)容器用于web服務(wù)器,一個(gè)容器用于數(shù)據(jù)庫(kù),那么他們之間就必須能進(jìn)行通信。使用docker的鏈接功能就可以讓容器彼此通信,
實(shí)現(xiàn)起來(lái)很簡(jiǎn)單:
$ docker run --name wp-mysql -e MYSQL_ROOT_PASSWORD=yoursecretpassword -d mysql
首先運(yùn)行數(shù)據(jù)庫(kù)容器,并命名為wp-mysql, -e提供一個(gè)環(huán)境變量以便mysql容器可以初始化數(shù)據(jù)庫(kù), -d表示以守護(hù)進(jìn)程方式運(yùn)行,最后的mysql表示使用官方的mysql鏡像
$ docker run --name wordpress --link wp-mysql:mysql -p 10003:80 -d wordpress
然后運(yùn)行web服務(wù)器,同樣命名為wordpress, 接下來(lái)--link把前面定義的wp-mysql容器鏈接到wordpress容器中,-p是wordpress的端口映射,最后也是使用官方的wordpress鏡像。
為了使用這種方式鏈接容器,構(gòu)建數(shù)據(jù)庫(kù)鏡像時(shí)必須指定暴露的容器端口。這可以通過(guò)在鏡像構(gòu)建的dockerfile中使用EXPOSE命令達(dá)成。
個(gè)人學(xué)習(xí)用的鏡像直接使用docker hub管理沒(méi)什么問(wèn)題,如果時(shí)企業(yè)的鏡像,可能就不想完全公開了,此時(shí)可以考慮建設(shè)企業(yè)私有的注冊(cè)中心。
要讓注冊(cè)中心運(yùn)行起來(lái),可在一臺(tái)具有大量磁盤空間的機(jī)器上發(fā)起以下命令:
$ docker run -d -p 5000:5000 -v $HOME/registry:/var/lib/registry registry:2
這條命令讓注冊(cè)中心運(yùn)行于主機(jī)的5000端口上,并使用主目錄下的registry作為容器的/var/lib/registry目錄。最后registry:2表示使用的鏡像。
然后在所有想訪問(wèn)這個(gè)注冊(cè)中心的機(jī)器上,將以下內(nèi)容添加到docker守護(hù)進(jìn)程的選項(xiàng)中 --insecure-registry HOSTNAME(這里HOSTNAME是新注冊(cè)中心的主機(jī)名或者IP地址),也就是說(shuō)需要停止docker服務(wù),然后重新運(yùn)行docker daemon命令,注意包含--insecure-registory選項(xiàng)。這個(gè)步驟完成后,就可以訪問(wèn)新的注冊(cè)中心了。例如:
docker push HOSTNAME:5000/image:tag
注冊(cè)中心可能被distribution的工具取代,詳見(jiàn)https://github.com/docker/distribution
守護(hù)進(jìn)程所在主機(jī)ip>聯(lián)系客服