今天對docker做一個梳理触创。關于docker的安裝和初步使用衡奥,上周已經實踐過一次描融,今天就從安裝完成后開始逐步梳理睹晒。包括使用前的一些準備工作和單步跟蹤一個docker項目的全生命周期,從拉取鏡像显拳、運行容器棚愤、編輯容器到打包鏡像和部署生產。
首先說一下wsl環(huán)境下ubuntu操作docker的問題,本來以為有了wsl就方便多了宛畦,但微軟對wsl1的linxu子系統(tǒng)中做了很多折中瘸洛,導致docker無法運行容器。查看了類似問題次和,按照說明將wsl升級到wsl2反肋,但升級后出現(xiàn)子系統(tǒng)都無法啟動的問題,可能是家庭版的原因斯够,暫時只能先放一放囚玫,等以后有專業(yè)版windows再試就容易多了读规。既然wsl用不了docker,意義也不大了燃少,還是換回虛擬機上的ubuntu束亏。
1. 準備工作
相關指令
- 將當前用戶添加到docker用戶組:sudo adduser $USER docker
- 查看當前用戶所屬用戶組:id $USER
- 啟動|關停|重啟docker:sudo service docker start|stop|restart
- 查看docker服務的狀態(tài):sudo service docker status
- 查看docker狀態(tài):docker info
docker安裝好后,運行docker需要使用sudo提升權限阵具,如果想讓當前用戶直接就能使用docker碍遍,需要將當前用戶添加到docker用戶組⊙粢海可以cat /etc/group | grep docker查看一下怕敬,返回docker:x:999:的用戶組信息。其中第一個docker是組名帘皿,x是密碼的掩碼东跪,999是這個組創(chuàng)建時給的編號,后面跟的是用戶名鹰溜,因為現(xiàn)在還沒有為這個組添加任何用戶虽填,所以冒號后面是空的。輸入groupmod三連擊tab曹动,可以輸出系統(tǒng)里的所有組斋日,查看一下當前用戶所屬的組有哪些,輸入id $USER墓陈,($USER是環(huán)境變量恶守,你可以echo $USER看一下,就是你登錄的用戶名贡必,你也可以直接輸入用戶名取代這個環(huán)境變量)兔港。id指令輸出了所查詢用戶的所有組名,目前還沒加入docker組赊级。輸入sudo adduser $USER docker押框,再用id指令查看一下,當前用戶已經加入到docker組了理逊。以后再運行docker指令就無需使用sudo提權橡伞。
在進行下一步之前別忘了修改docker的hub源為國內源盒揉,具體方法在上周的日志中已經介紹,也可點此處溫故兑徘。修改源重啟docker后刚盈,使用docker info查看一下docker當前的狀態(tài),最后一段Registry Mirrors中是否列出了剛才修改的hub源挂脑?如果這條指令報如下錯誤“Cannot connect to the Docker daemon at unix:///var/run/docker.sock. Is the docker daemon running?”藕漱,這說明docker沒有啟動,可以使用sudo service docker start試一下崭闲,再用sudo service docker status看一下是否啟動成功肋联。
2. 拉取鏡像
相關指令
- 查看本地鏡像列表:docker image ls
- 搜索docker hub上的鏡像:docker search [--filter "xxx=xx"] XXX
- 拉取鏡像:docker image pull XXX:tag
- 刪除本地鏡像:docker rmi XXX:tag|IMAGE_ID
萬丈高樓平地起,首先要把地基選好刁俭,這個地基就是鏡像橄仍。在準備工作中,我們已經切換了docker hub為國內源牍戚,這個源就是提供地基的鏡像倉庫侮繁,得益于docker社區(qū)的人丁興旺,鏡像倉庫中已經儲備了非常豐富的鏡像如孝,能幾乎滿足各行業(yè)的地基需求宪哩。我們只需在倉庫中搜索自己需要的鏡像,再以此為基礎做進一步的修改和配置第晰。為何不從頭構建自己的鏡像呢锁孟?原因有二,一是效率不多說但荤,二是鏡像倉庫中提供的公共源是經過安全驗證和精簡化的罗岖,簡而言之就是如果我們自己動手構建出相同目的的鏡像,在體積和性能上往往都比不過鏡像倉庫中經過考驗的公共鏡像腹躁。
根據(jù)自己的需求桑包,首先到docker hub上搜索需要的鏡像,比如我們要搭建一個nginx反向代理服務纺非,輸入docker search nginx指令哑了,搜索公共鏡像庫,得到一堆返回信息烧颖。如果想增加一些過濾信息弱左,可以添加--filter參數(shù),如--filter "is-official=true"則僅僅返回官方版炕淮,--filter "stars=500"則返回獲星數(shù)大于500的鏡像拆火。有人要問,如果這個鏡像不錯,我是不是也可以去點個星们镜?當然可以了币叹,移步docker hub官網,如果要點星模狭,首先得注冊一個帳號颈抚,然后再在左上角的搜索框中搜索想要的鏡像,這個是可視化的搜索方式嚼鹉,可以查看鏡像的說明贩汉、查看鏡像各版本的tag號,可以給心怡的鏡像點★锚赤。如果僅僅是查看版本和tag匹舞,不注冊帳號也是可以的。
這里提到了tag宴树,tag是鏡像的版本標簽策菜,同一個鏡像會不停迭代版本,通過tag來標記版本酒贬,如果在拉取鏡像時不指定tag,則默認拉取tag為latest的版本翠霍,通過剛才的官網查詢锭吨,你也可以選擇自己需要的版本,比如stable也是不錯的選擇寒匙。拉取鏡像的指令是docker image pull nginx:stable零如,國內鏡像速度還是可以的,很快就拉取完畢锄弱,通過docker image ls再查看一下考蕾,本地的鏡像倉庫已經增加了一條nginx鏡像。
如果想刪除本地的鏡像会宪,可以通過docker rmi IMAGE_ID|REPOSITORY:TAG指令肖卧。rmi是移除鏡像的意思,后面跟的參數(shù)可以是鏡像的ID號掸鹅,也可以是鏡像的名稱:tag塞帐,但移除鏡像前先要確保基于該鏡像的容器已經全部關閉巍沙,否則會報錯葵姥。這里推薦通過鏡像名:tag的組合參數(shù)方式來移除鏡像,一是便于人類操作句携,二是存在兩個鏡像ID號重復的情況榔幸,比如有兩個nginx鏡像,一個tag為stable,一個tag為1.19削咆,這兩個鏡像其實是相同的牍疏,具有相同的IMAGE_ID,此時如果通過IMAGE_ID來刪除态辛,則會報錯麸澜。
3. 運行容器
利用本地鏡像庫中的鏡像啟動一個容器,docker run --name mynginx -d -p 81:80 nginx:stable奏黑,啟動成功后會返回一串ID號炊邦,這串號碼的前12位就是這個容器的ID號。這段命令中熟史,通過--name指定了容器別名馁害,通過-d指明屬于后臺進程,不會隨終端關閉而關閉蹂匹,-p 81:80指定了將本地81端口映射給容器的80端口碘菜,最后指明鏡像的名字和tag∠弈可以通過docker ps查看活動的容器忍啸,也可以再打開一個終端,輸入docker stats履植,結果將以列表形式不斷刷新當前所有活動容器的狀態(tài)计雌,類似于打開了一個實時監(jiān)控窗口。
通過docker stop mynginx可以關閉這個容器玫霎。通過docker rm mynginx可以刪除這個容器凿滤,刪除之前先要保證容器處于關閉狀態(tài)。只有與鏡像關聯(lián)的所有容器都被刪除后庶近,鏡像才能被刪除翁脆。
4. 編輯容器
獲取容器內系統(tǒng)的bash,可通過docker exec -it mynginx bash指令切換為容器內系統(tǒng)的bash鼻种。
在宿主機上通過docker cp指令反番,可以實現(xiàn)宿主機與docker容器的文件互傳,在宿主機桌面上打開終端普舆,輸入docker cp default.conf mynginx:/etc/nginx/conf.d/default.conf恬口,則實現(xiàn)了用宿主機桌面上的default.conf配置文件覆蓋容器中nginx配置文件的目的。當然這個桌面上的配置文件是提前準備好的沼侣,比如為了實現(xiàn)瀏覽器地址欄URL不改變的隱式跳轉祖能,可以這樣配置nginx:
server{
listen 80;
server_name 192.168.31.111;
location / {
proxy_pass https://www.baidu.com;
}
}
其中那串IP地址是我虛擬機上ubuntu的局域網地址,配置文件覆蓋后蛾洛,通過前文介紹的獲取容器bash的方法進入容器养铸,執(zhí)行nginx -s reload重啟nginx雁芙,到ubuntu或者windows上用瀏覽器訪問192.168.31.111:81,可以看到打開的內容是百度的首頁钞螟,這就實現(xiàn)了nginx的反向代理服務兔甘。為什么這里是81端口?還記得前面run這個容器時所做的端口映射嗎鳞滨。
5. 打包容器
相關指令
- 導出容器:docker export 容器名 > 本地路徑/xxx.tar
- 對應的導入鏡像: docker import 本地路徑/xxx.tar 鏡像名:tag
- 將容器保存到鏡像庫:docker commit -a 作者 -m 描述 鏡像名:tag
- 將鏡像保存到本地:docker save 鏡像名:tag > 本地路徑/xxx.tar
- 對應的導入鏡像:docker load < 本地路徑/xxx.tar
- 查看鏡像歷史信息:docker history 鏡像名:tag
- 查看鏡像層文件:docker inspect 鏡像名:tag
打包容器有兩種方法洞焙,一種是直接直接將容器導出到本地磁盤,一種是將容器提交到本地鏡像庫拯啦,然后再從鏡像庫中導出鏡像到本地磁盤澡匪。這兩者初看似乎結果一樣,都是實現(xiàn)了容器的本地持久化保存褒链,實際還是有區(qū)別的唁情。先來練手實踐,后面再來分析它們的區(qū)別甫匹。
先是第一種甸鸟,直接將容器導出到本地磁盤,docker export 容器名 > /home/xxx.tar兵迅,這里就將指定容器的快照持久化保存到本地/home/xxx1.tar文件中抢韭。從該文件還原鏡像的指令是docker import /home/xxx1.tar 鏡像名:tag。
第二種將容器持久化到本地鏡像庫恍箭,docker commit -a 作者 -m 描述 鏡像名:tag篮绰,再將鏡像庫中的這個鏡像導出到本地磁盤,docker save 鏡像名:tag > /home/xxx.tar季惯,這樣也同樣實現(xiàn)了容器轉鏡像再保存到本地的目的。從該文件還原鏡像就不能用import了臀突,import是與export對應的勉抓,與save對應的還原鏡像指令是docker load < /home/xxx2.tar,load時不用指定鏡像名和tag了候学,應為save保存時已經將原鏡像的相關信息保存到xxx2.tar中了藕筋。
在導入鏡像時可能會碰到錯誤,請查看一下是不是import和load用錯了梳码,不同的導出指令對應不同的導入指令隐圾。
這里再來細究一下兩種打包容器的方法的區(qū)別。首先可以去看看剛才導出的兩個壓縮文件xxx1.tar和xxx2.tar掰茶,它們的文件大小是不一樣的暇藏,export方式的xxx1.tar體積小于save方式的xxx2.tar,原因是export將當前容器的快照作為一層保存濒蒋,而通過commit再save的方式保存了鏡像的歷史層信息盐碱。你可以試著將xxx1.tar和xxx2.tar再導入到鏡像庫把兔,用指令docker history 鏡像名:tar來查看下它們各自的歷史信息,前者只有一條歷史信息瓮顽,后者保存有從基礎鏡像逐步構建的歷史信息县好。查看鏡像層信息的指令是docker inspect 鏡像名:tag,從輸出信息中RootFS:Layers屬性中可以看到暖混。鏡像分層相當于鏡像的開發(fā)里程碑缕贡,當從鏡像生成容器后,會增加一層容器層拣播,容器的所有操作都限制在這一層晾咪,下面各歷史鏡像層是不會被改動的,即使刪除下層的文件诫尽,也只是在容器層增加了一個刪除標記禀酱,所以越層刪除反而會增加鏡像的體積,而不會縮小體積牧嫉。
理解了這兩種打包方式的原理剂跟,就要審時度勢的使用。如果確認當前容器已經最優(yōu)酣藻,用于發(fā)布曹洽,則可以用export打包,所有層都將壓縮到一起辽剧,丟失分層信息送淆。如果使用敏捷開發(fā)和迭代部署,保留鏡像分層信息可用于回滾怕轿。
導出偷崩、導入也已經實現(xiàn)了,docker的基本使用和部署也就掌握了撞羽。
6. 部署生產
docker非常適合于分布式快速部署阐斜,與之配合的有Swarm,docker集群管理平臺诀紊。過去搭建大規(guī)模分布式系統(tǒng)谒出,需要考慮很多細節(jié)問題,部署復雜邻奠,對運維的要求也很高◇栽現(xiàn)在有了docker技術,配合Swarm碌宴,可以屏蔽很多分布式系統(tǒng)的底層細節(jié)問題杀狡,將重點集中到業(yè)務邏輯的拆分上,大大降低了運維的難度唧喉。這里有一篇文章秉氧,并發(fā)分布式架構演進之路,是淘寶從小規(guī)模發(fā)展到如今這樣規(guī)模的架構演進過程叉弦,寫得挺好惠勒,收藏于此。此生可能無緣部署如此規(guī)模的架構了,但其演進路上的某些里程碑是可以借鑒的,且如今有了docker這類容器化技術,比前人們的起點更高了祟绊。如何部署,需要的只是想象力和現(xiàn)實的業(yè)務需求量哥捕。當一切技術問題都不再是問題時牧抽,一張紙一支筆就能在架構設計的戰(zhàn)場上運籌帷幄。
7. 2021.1.6補充:docker容器開機自啟動
在使用docker run從鏡像啟動容器時遥赚,使用--restart參數(shù)來設置扬舒,--restart具體參數(shù)值詳細信息:
- no:
容器退出時,不重啟容器凫佛。 - on-failure:
只有在非0狀態(tài)退出時才從新啟動容器讲坎;在使用on - failure策略時,指定Docker將嘗試重新啟動容器的最大次數(shù)sudo docker run --restart=on-failure:10愧薛。默認情況下晨炕,Docker將嘗試永遠重新啟動容器。 - always:
無論退出狀態(tài)是如何毫炉,都重啟容器瓮栗。
如果創(chuàng)建容器時未指定 --restart=always ,可通過update命令更新容器:
docker update --restart=always 容器名