DOCKER概覽

      網友投稿 833 2025-03-31

      docker服務端是個daemon進程,管理docker容器并與客戶端交互。服務端監聽/var/run/docker.sock這個套接字,提供命令行交互和RESTful API兩種方式。

      Docker的daemon進程需要用root運行,docker用戶組有root用戶相同的權限,所以是種安全隱患。另外,默認通信方式是非認證的模式,所以也是不安全的,但是可以設置TLS認證。

      鏡像的概念不是Docker發明的,甚至可以參照理解windows系統的ghost盜版方式。

      Docker鏡像是基于Union文件系統的一種分層結構,可以由一步一步的構建出來。可以參照理解純凈版的ghost windows(基礎鏡像),和安裝了office等軟件的ghost windows(FROM基礎鏡像)

      鏡像也可以理解為容器的“源代碼”,后面會稍微展開一些。

      上面說了鏡像是容器的源代碼,那么Registry就可以理解為代碼庫。

      Registry官方提供一個公共庫,是收費的。企業也可以搭建自己的私有Registry。

      容器就涉及Docker大名鼎鼎的集裝箱概念了,容器就是集裝箱,鏡像是貨物。容器不關心具體鏡像是什么,容器會按照相同的方式去管理鏡像,如創建、啟動、關閉、重啟、銷毀。

      容器可以包含一個或多個進程,但是當前的主流做法(微服務)是單容器單進程。

      Docker并不是憑空冒出來的,依賴于原來OS的一些功能。但是Docker也希望反向作用于容器標準化,于是有了libcontainer作為容器管理的抽象,后續好真正實現跨平臺。

      Docker底層依賴linux內核的namespace、cgroups、Union File System(可選:Device Manager、AUFS、vfs、btrfs),主要用于資源的隔離和控制,如文件系統、進程、網絡等。所以Docker需要較新的內核版本,推薦是3.8以上。

      Docker采用寫時復制(https://en.wikipedia.org/wiki/Copy-on-write)技術,通過分層的文件系統保證高效率和很少占用空間。

      Docker可以日志化容器中的標準輸入輸出,STDOUT/STDERR/STDIN,也支持偽tty終端,提供一個交互shell,可以用來定位和調試。

      Docker底層依賴的設計思路可以參考公司內李國柱的博客:

      http://3ms.huawei.com/hi/blog/11100_1899017.html?h=h

      細節可參照陳皓的系列博客:

      http://coolshell.cn/articles/17010.html

      http://coolshell.cn/articles/17029.html

      http://coolshell.cn/articles/17049.html

      http://coolshell.cn/articles/17061.html

      http://coolshell.cn/articles/17200.html

      Docker命令大概分四類,參考:

      http://www.infoq.com/cn/articles/docker-command-line-quest

      其中大部分和LINUX命令相同的名字的命令,基本也是相似的語義。

      info命令用于查看docker基本信息,會返回所有容器的鏡像、執行和存儲驅動、基本配置。容器保存在/var/lib/docker/containers 。

      inspect命令可以查看容器的最詳細信息。

      images命令查看所有的鏡像。鏡像保存在宿主機的/var/lib/docker目錄。

      run命令是運行容器,-i參數保證STDIN開啟,-t命令啟動偽tty,兩個參數可以保證啟動容器后的交互。run指定的鏡像,會先找本地,找不到會找倉庫,找到一次就緩存到本地,整個過程類似maven的管理。

      --name會給容器指定一個名字,這個很有用,會被很多地方引用,所以必須是唯一的,如果有重名,必須先rm掉舊的容器。-d表示daemon,創建一個長期運行的容器。-- rm表示一次性運行的容器,運行完容器的進程會自動刪除容器。-h會指定容器的主機名,不指定的話默認是容器ID。--volumes-from指定從某個容器掛載所有的卷。

      attach可以重新附著一個run的容器會話。

      logs命令查看容器日志,-f參數使用和linux的tail –f類似。-t為日志加時間戳。

      build構建鏡像、history可以查看這個構建的過程。

      exec命令在容器內啟動新的進程,-d可以設置為daemon進程。

      Docker鏡像就是文件系統一層一層疊加出來的。

      最底層是一個引導文件系統bootfs,類似linux的引導文件系統。docker用戶不會和引導文件系統有交互,因為在容器啟動后,就會被移到內存中,引導文件系統會被unmount,以便留出更多內存供initrd(boot loader initialized RAM disk)磁盤鏡像使用。

      引導文件系統上層是rootfs,rootfs是基于內存的文件系統,所有操作都在內存中完成;也沒有實際的存儲設備,所以不需要設備驅動程序的參與。基于以上原因,linux在啟動階段使用rootfs文件系統,當磁盤驅動程序和磁盤文件系統成功加載后,linux系統會將系統根目錄從rootfs切換到磁盤文件系統。

      linux引導過程中,root文件系統先按只讀方式加載,引導完成,包括校驗完成,會被切換為讀寫模式。但是Docker中,root文件系統永遠都是只讀模式,Docker用union mount技術又會在root文件系統之上加載其他的文件系統,這些也是只讀的。

      union mount會一次同時加載多個文件系統,但是從外看,只有一個文件系統。union mount把各層文件疊加到一起,這個看起來的最終的文件系統會包含所有底層的文件和目錄。這個外觀型的文件系統,就是鏡像。

      所以,容易理解,鏡像也是可以一層一層疊加的,下層的鏡像就是上層的parent image,最底層的鏡像是base image。

      當容器啟動時,Docker在鏡像的最頂層加載一個讀寫文件系統,在Docker中運行的程序就是在這個讀寫層執行的。剛啟動時,這個讀寫層是空的,發生變化時,變化的部分會體現在這一層,這就是所謂的寫時復制。

      實際上,容器就是這個讀寫層+下面的鏡像層+配置。

      鏡像的版本管理貌似是參考了git的思路。

      Docker Registry管理鏡像,包含了鏡像、層、和一些關于鏡像的元數據。

      Docker默認用的是官方的Registry,也就是Docker Hub,這個部分也是開源的,所以企業也可以搭建自己的私有Registry。Registry也可以運行在Docker中~

      Docker Hub中有兩種類型的倉庫,user repository和top-level repository。用戶倉庫的鏡像是Docker用戶創建。頂級倉庫是Docker內部人員管理,一般是由Docker合作廠家提供,如操作系統發行商。用戶基于頂層的這些基礎鏡像來構建自己的鏡像。

      用戶倉庫的命名由用戶名和倉庫名兩部分組成,如user/repo,頂層倉庫只包含倉庫名。

      同一倉庫中的鏡像,可以通過加tag區分。相同鏡像ID可以有多個TAG。

      docker run命令從鏡像啟動一個容器時,如果鏡像不在本地,docker默認會從Docker Hub下載鏡像,如果沒有顯示指定tag,會默認下載latest標簽的鏡像。也可以通過docker pull命令,預先加載到本地。

      docker search命令,查找所有Docker Hub上公共的可用鏡像。docker push命令將鏡像推送到docker hub。

      Docker Hub還有個比較有意思的功能是“Trusted Build”,將Docker Hub關聯GitHub上的Dockerfile文件,每次提交代碼,都會觸發一次構建,并創建新鏡像。

      https://docs.docker.com/engine/reference/builder/

      這里邊講的“構建”,并不是說從零構建,這會復雜的多。一般說的構建鏡像就是基于基礎鏡像去構建新鏡像。從零構建可以參考.

      https://docs.docker.com/engine/userguide/eng-image/baseimages/

      構建鏡像有兩種方式:

      1. 單步命令:docker commit

      2. 批量方式:Dockerfile文件 + docker build命令

      可以類比于java中的單個編譯和ant腳本批量編譯。commit命令一般不推薦使用,因為Dockerfile功能更強,也更靈活。

      上面說Registry類似git倉庫,其實commit命令其實類似git提交代碼。下載鏡像、基于它構建、構建鏡像的過程,其實可以類比于下載代碼,基于代碼修改,提交代碼的過程。

      commit命令需要指定docker容器的ID(通過docker ps –l –q命令看剛創建的容器ID),一個目標倉庫和鏡像名。commit命令提交的只是差異部分,并不是全量提交,這也是分層的好處。

      Dockerfile實際上是定義了一種DSL,提供了一種批量構建鏡像的方式。參考

      Dockerfile所在的目錄就是構建環境,被成文build context。Docker會在構建鏡像時將這個目錄和目錄中的文件和子目錄上傳到Docker守護進程。Docker守護進程可以直接訪問構建所需的任何代碼、文件或其他的數據。

      Dockerfile由一系列的指令和參數組成,每條指令,如FROM,都是大寫字母。指令后面要加一個參數。Dockerfile中的指令從上到下按順序執行。

      每條指令都會創建一個新的鏡像,并自動提交。相當于基于父鏡像,每執行一條指令,就docker commit一次,然后新構建的鏡像作為下一條指令的父鏡像。直到所有指令執行完。

      官方給了幾個dockerfile的實例,舉一個如下:

      EXPOSE指定對外暴漏的接口,在實際宿主機上,還要做端口映射。方法是使用docker run命令的-p參數,可以隨機分配,或指定端口映射,設置可以指定某個特定的宿主機的映射方式。也可以使用-P參數,直接暴露所有EXPOSE指令指定的端口。

      RUN是最基本的運行指令,會在當前鏡像中運行指定的指令。每條RUN都會創建一個新的鏡像層,如果成功,就會提交鏡像,然后繼續執行下一條。

      FROM會引入基礎鏡像,所有命令基于此開始構建。

      # 開頭是注釋。

      docker build命令,會執行dockerfile,并返回最后一個成功的鏡像。

      build命令推薦指定鏡像名和標簽,沒指定tag會默認打上latest標簽。也可以打多個標簽:

      $ docker build -t shykes/myapp:1.0.2 -t shykes/myapp:latest .

      build命令執行過程中,如上面所說,每一步都是獨立的構建,每一步都會有一個鏡像ID:

      所以,在執行某一個指令失敗時,會返回最后一個成功的鏡像。可以在這個鏡像的基礎上,手工執行出錯的指令,進行調試。而之前構建出來的鏡像也會被作為緩存,再次構建不是從頭開始,而是從失敗的位置開始構建。如果需要關閉緩存,在build命令后加—no-cache參數。

      構建的過程,也可以通過docker history命令回溯。

      CMD命令指定容器啟動時要運行的命令;對應的,上面說的RUN是鏡像構建時要運行的命令。參數格式和RUN命令相同,都支持數組形式參數:

      CMD ["executable","param1","param2"] (exec form, this is the preferred form)

      CMD ["param1","param2"] (as default parameters to ENTRYPOINT)

      CMD command param1 param2 (shell form)

      CMD在一個dockerfile中只有一條,即使配置了多條,也只有最后一條生效。

      要注意的是,啟動命令可以被docker run命令指定的啟動命令覆蓋。

      ENTRYPOINT和CMD非常類似,區別在于不能被覆蓋。docker run命令指定的任何參數都會被當作參數再次船體給ENTRYPOINT指令中指定的命令。

      ENV命令,顧名思義,設置構建鏡像的環境變量。從構建的鏡像啟動容器,環境變量就會生效,且持久生效。對應的docker run命令-e指定的環境變量,只會在運行時有效。

      容器啟動的工作目錄。CMD和ENTRYPOINT都會從這個目錄下執行。可以設置多次,運行不同指令,如:

      WORKDIR /a RUN xxx WORKDIR b CMD xxx run命令的-w可以覆蓋工作目錄

      指定鏡像以什么用戶運行。run命令的-u選項可以覆蓋

      向容器添加卷。卷是docker設計的一種共享方式,可以繞過unionfs,在不同容器間持久化共享數據。可以用來存放調試代碼、日志管理、數據共享等用途。

      卷有幾個特性:

      1.卷在容器間共享和重用

      2.對卷的修改是即時生效的

      3.卷的修改不會對更新鏡像產生影響

      4.直到所有引用的容器都被刪除,卷才會被刪除(要注意刪除容器,卷被誤刪)

      5.卷這個參數不是必須的,容器可以選擇不共享

      可以通過數組參數,指定多個卷。

      提交或創建鏡像時,鏡像中不包含卷。

      ADD把構建目錄下的文件和目錄復制到鏡像中。文件源支持正常路徑和URL模式。目的路徑如果不存在,會創建全路徑。

      ADD有個奇葩的隱藏功能,會根據地址參數末尾的字符來判斷是文件還是目錄,比如以/結尾,就認為是目錄。

      另一個奇葩的隱藏功能,如果將gzip等標準壓縮格式作為源,ADD會自動解壓。

      COPY和ADD基本一樣,只是不會自動解壓。個人認為docker這種ADD/COPY,CMD/ENTRYPOINT的設計非常奇葩。這個命令創建的文件和目錄的UID和GID都會設為0。拷貝的內容包含文件系統的元數據。

      這是個鉤子,當鏡像作為父鏡像構建時,鉤子會被調用。

      ONBUILD后面可以加任何構建指令,插入的指令可以認為是緊跟在FROM之后執行的。

      可以結合這個命令和構建緩存的功能,制作構建模板。

      docker支持兩種網絡驅動,bridge 和overlay ,默認是網橋模式。

      如果不特意指定,守護進程管理所有容器的網絡連接,都是通過docker0這個虛擬網橋:

      ubuntu@ip-172-31-36-118:~$ ifconfig

      docker0 Link encap:Ethernet HWaddr 02:42:47:bc:3a:eb

      inet addr:172.17.0.1 Bcast:0.0.0.0 Mask:255.255.0.0

      inet6 addr: fe80::42:47ff:febc:3aeb/64 Scope:Link

      UP BROADCAST RUNNING MULTICAST MTU:9001 Metric:1

      RX packets:17 errors:0 dropped:0 overruns:0 frame:0

      TX packets:8 errors:0 dropped:0 overruns:0 carrier:0

      collisions:0 txqueuelen:0

      RX bytes:1100 (1.1 KB) TX bytes:648 (648.0 B)

      docker0接口有符合RFC1918的私有IP地址,范圍是172.16~172.30,上例中的網關地址是172.17.0.1,也是所有docker容器的網關地址。

      docker創建一個容器就會創建一組互聯的網絡接口,一端是容器的eth0,一段是docker0,這樣Docker相當于管理了一個虛擬子網。

      默認容器和宿主機網絡是不通的,除非指定打開端口。

      docker容器重啟,就會改變IP地址。這對需要互聯的容器很不方便,所以docker提供了link功能。link可以把一個或多個docker容器連接起來,互相通信。

      https://docs.docker.com/engine/userguide/networking/work-with-networks/#linking-containers-in-user-defined-networks

      link需要引用容器的名字,所以上文也強調過名字的重要性。

      docker run –link選項,可以創建兩個容器間的父子連接,有兩個參數,一個是要連接的容器名,另一個參數是連接后容器的別名。別名可以讓使用者不關注底層容器的名字。

      因為是父子連接,所以不是雙向的,但是可以運行兩個命令來達到雙向的目的:

      $ docker run --net=isolated_nw -itd --name=container4 --link container5:c5 busybox

      01b5df970834b77a9eadbaff39051f237957bd35c4c56f11193e0594cfd5117c

      $ docker run --net=isolated_nw -itd --name=container5 --link container4:c4 busybox

      72eccf2208336f31e9e33ba327734125af00d1e1d2657878e2ee8154fbb23c7a

      $ docker attach container4

      / # ping -w 4 c5

      PING c5 (172.25.0.5): 56 data bytes

      64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms

      64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms

      64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms

      64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms

      DOCKER概覽

      --- c5 ping statistics ---

      4 packets transmitted, 4 packets received, 0% packet loss

      round-trip min/avg/max = 0.070/0.081/0.097 ms

      / # ping -w 4 container5

      PING container5 (172.25.0.5): 56 data bytes

      64 bytes from 172.25.0.5: seq=0 ttl=64 time=0.070 ms

      64 bytes from 172.25.0.5: seq=1 ttl=64 time=0.080 ms

      64 bytes from 172.25.0.5: seq=2 ttl=64 time=0.080 ms

      64 bytes from 172.25.0.5: seq=3 ttl=64 time=0.097 ms

      --- container5 ping statistics ---

      4 packets transmitted, 4 packets received, 0% packet loss

      round-trip min/avg/max = 0.070/0.081/0.097 ms

      $ docker attach container5

      / # ping -w 4 c4

      PING c4 (172.25.0.4): 56 data bytes

      64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms

      64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms

      64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms

      64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms

      --- c4 ping statistics ---

      4 packets transmitted, 4 packets received, 0% packet loss

      round-trip min/avg/max = 0.065/0.070/0.082 ms

      / # ping -w 4 container4

      PING container4 (172.25.0.4): 56 data bytes

      64 bytes from 172.25.0.4: seq=0 ttl=64 time=0.065 ms

      64 bytes from 172.25.0.4: seq=1 ttl=64 time=0.070 ms

      64 bytes from 172.25.0.4: seq=2 ttl=64 time=0.067 ms

      64 bytes from 172.25.0.4: seq=3 ttl=64 time=0.082 ms

      --- container4 ping statistics ---

      4 packets transmitted, 4 packets received, 0% packet loss

      round-trip min/avg/max = 0.065/0.070/0.082 ms

      父容器可以直接訪問自容器的任意公開端口,而且只有配置--link連接的容器才能訪問。容器端口甚至不需要對宿主機開放。

      連接只能運行在同個宿主機中,不能運行在不同宿主機。

      配置link,會在父容器的dns配置文件,如/etc/hosts里寫入IP,重啟后,這個IP也會隨著刷新。不過docker技術變化很快,這種底層的技術也可能變化很快。

      Docker生態有三種API:Registry API、Docker Hub API、Docker Remote API,前兩個是與倉庫交互,最后一個是與docker daemon進程交互。

      REST API支持證書認證。

      基本接口和docker命令都能一一對應,如/images/json返回結果和docker images命令非常類似。還可以控制容器,如/containers/start

      容器編排有兩大類,一種是簡單的把容器連起來,如Fig;一種是更強大的容器編排,包括服務發現,動態伸縮,調度等,如Consul(服務發現),kubernetes、mesos(集群調度和管理),swarm。

      每個話題都很大,這里不展開。

      描述問題一般有個約定,要給出背景信息:

      docker info和docker version的輸出

      uname –a命令的輸出

      要描述你想要什么,希望它如何工作,嘗試了什么。

      提問前可以先搜索,參考提問的藝術。

      轉載請注明出處:華為云博客 https://portal.hwclouds.com/blogs

      Docker

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      版權聲明:本文內容由網絡用戶投稿,版權歸原作者所有,本站不擁有其著作權,亦不承擔相應法律責任。如果您發現本站中有涉嫌抄襲或描述失實的內容,請聯系我們jiasou666@gmail.com 處理,核實后本網站將在24小時內刪除侵權內容。

      上一篇:如何在 Excel 中根據條件創建編號規則?
      下一篇:插入中找不到音頻(找不到相應的音頻是咋回事)
      相關文章
      国产AV无码专区亚洲AV琪琪| 亚洲一区精品视频在线| 亚洲人成无码网站在线观看| 亚洲国产精品lv| 国产v亚洲v天堂无码网站| 久久精品国产亚洲Aⅴ香蕉| 亚洲男人的天堂在线va拉文| 亚洲欧洲中文日韩av乱码| 亚洲国产成人影院播放| 亚洲片国产一区一级在线观看 | 久久99亚洲综合精品首页| 亚洲国产精品一区二区三区久久| 亚洲国模精品一区| 2048亚洲精品国产| 亚洲中文字幕在线第六区| 亚洲男人的天堂www| 亚洲国产精品无码av| 久久青青草原亚洲AV无码麻豆| 亚洲精品国产品国语在线| 亚洲色欲久久久综合网 | 亚洲熟妇无码八V在线播放| 亚洲日韩精品国产3区| 亚洲aⅴ无码专区在线观看| 亚洲电影日韩精品| 国产精品V亚洲精品V日韩精品 | 亚洲精品乱码久久久久久按摩 | 亚洲福利一区二区| 亚洲jizzjizz在线播放久| 亚洲一区二区无码偷拍| 亚洲精品永久在线观看| 国产成人亚洲午夜电影| 亚洲一级特黄大片无码毛片| 亚洲精品无码国产| 97久久精品亚洲中文字幕无码| 亚洲av专区无码观看精品天堂| 亚洲av永久中文无码精品综合 | 久久精品国产亚洲沈樵| 91天堂素人精品系列全集亚洲| 亚洲欧洲日韩极速播放 | 久久丫精品国产亚洲av不卡 | 亚洲处破女AV日韩精品|