Docker 实战教程之从入门到提高(二)
本系列第一篇文章,Docker 實戰(zhàn)教程之從入門到提高 (一),我們已經(jīng)介紹了如何在 Ubuntu 操作系統(tǒng)中安裝 Docker,以及 Proxy 和 Insecure Registry 的配置。
本文繼續(xù) Docker 的實戰(zhàn)學習。
練習1:通過一個簡單例子學習 Docker 和宿主機操作系統(tǒng)文件目錄互相隔離的實現(xiàn)原理
我們知道在 Docker 容器里是無法訪問到宿主操作系統(tǒng)的文件目錄的,但這種隔離是怎么實現(xiàn)的呢?
其實一點也不神奇——利用了 Linux 系統(tǒng)的內(nèi)部命令 chroot.
chroot 能將進程的根目錄設置成任意指定的目錄。
使用 chroot 我們能創(chuàng)建一個新的進程,并且以 chroot 執(zhí)行時傳入的參數(shù)作為新進程的根目錄。
因為新進程創(chuàng)建之后就無法訪問除了新進程創(chuàng)建時傳入 chroot 參數(shù)之外的其他文件目錄,為了確保這個新進程能夠正常工作,我們必須手動拷貝一些文件到新進程的根目錄映射的舊目錄下。
做一個如下測試:
新建一個文件夾,執(zhí)行 chroot . 意思是把文件夾 $HOME/container 當作新建進程的根目錄。但是沒有成功,報錯誤消息:
chroot: failed to run command ‘/bin/bash’: No such file or directory
執(zhí)行下面兩條命令:
執(zhí)行命令 ldd $HOME/container/bin/bash:
該命令為了查看需要有哪些庫文件得手動拷貝到文件夾 $/HOME/container/bin/bash下面:
根據(jù) ldd 的輸出,再次執(zhí)行下圖的八條命令:
再次執(zhí)行 chroot . ,發(fā)現(xiàn)這次成功了:
pwd 發(fā)現(xiàn)是在根目錄下,ls 也只能發(fā)現(xiàn)執(zhí)行 chroot 時指定的 container 目錄下的子目錄:
這就是 docker 文件目錄隔離的實現(xiàn)原理。
練習2:用一個實際例子理解 Docker volume 工作原理
要了解 Docker Volume,首先我們需要理解 Docker 文件系統(tǒng)的工作原理。Docker 鏡像是由多個文件系統(tǒng)的只讀層疊加而成。當一個容器通過命令 docker run 啟動時,Docker 會加載只讀鏡像層并在鏡像棧頂部添加一個讀寫層。如果運行中的容器修改了現(xiàn)有的一個已經(jīng)存在的文件,那該文件將會從讀寫層下面的只讀層復制到讀寫層,但是該文件的只讀版本依然存在,只不過已經(jīng)被讀寫層中該文件的副本所隱藏。
當刪除Docker容器,并通過該鏡像重新啟動時,之前在讀寫層的更改將會丟失。在 Docker中,只讀層及在頂部的讀寫層的組合被稱為 Union File System(聯(lián)合文件系統(tǒng)),簡稱UnionFS,它用到了一個重要的資源管理技術,叫寫時復制。
寫時復制(copy-on-write), 也叫隱式共享,是一種對可修改資源實現(xiàn)高效復制的資源管理技術。對于一個重復資源,若不修改,則無需立刻創(chuàng)建一個新的資源,該資源可以被共享使用。當發(fā)生修改的時候,才會創(chuàng)建新資源。這會大大減少對于未修改資源復制的消耗。其實COW 這個概念對編程人員來說一點也不陌生,廣泛用在各種領域,比如 ABAP 里對于內(nèi)表(Internal table) 的拷貝動作,Java 字符串的拷貝實現(xiàn)等等。Docker 基于 UnionFS 去創(chuàng)建containers.
我們下面看一個實際例子。
使用命令行 docker run --help 查看這個命令的幫助文檔。 -h 的作用是指定容器的主機名。
使用命令行創(chuàng)建一個新的容器:
docker run -it --name jerry-container-test -h CONTAINER -v /data busybox /bin/sh
名稱為 jerry-container-test, 用 -v 創(chuàng)建了一個 volume /data
創(chuàng)建完畢之后,在容器里執(zhí)行cd /data進入這個目錄,這個時候還是空的。
docker ps 查看容器狀態(tài):
現(xiàn)在我想知道主機上為了實現(xiàn)這個 volume,使用了哪個 internal 目錄。
用命令 docker inspect jerry-container-test 查看關鍵字"volumes":
得到了容器里 /data 在主機上實現(xiàn)的目錄:
/var/lib/docker/volumes/96aa969033ee7e6d7ff607a0a47de5a5866613a422518ed3f86fee6240bae8cc/_data
現(xiàn)在我在主機上使用 touch 命令在這個目錄下直接創(chuàng)建一個文件:
sudo touch /var/lib/docker/volumes/96aa969033ee7e6d7ff607a0a47de5a5866613a422518ed3f86fee6240bae8cc/_data/test.s
現(xiàn)在切換到容器里,用ls也能看到直接在主機上用 touch 命令在 internal folder 里創(chuàng)建的文件了。
練習3:利用 Docker volume 修改 Nginx Docker 鏡像里的 index.html
通過這個小例子我們可以進一步加深對 Docker volume概念的理解和使用方法。
我們都知道運行基于 Docker 的 Nginx 鏡像后,訪問 localhost 能看到 Nginx 默認的首頁,這個首頁的位置是 Nginx 鏡像內(nèi)的 /usr/share/nginx/html 目錄下面。
假設我們有個需求,修改 Nginx 默認的首頁成下面的內(nèi)容:
<html> <head> <title>Custom Website from my container</title> </head> <body> <h1>This is Jerry's custom website.</h1> <p>This website is served from my <a href="http://www.docker.com" target="_blank">SAP Docker</a> container.</p> </body> </html>下面是詳細方法。
命令行 -v 將主機目錄 nginx-html 掛載到 Nginx 容器內(nèi)的 /usr/share/nginx/html 目錄內(nèi)。
docker run -d -p 1081:80 -v pwd/nginx-html:/usr/share/nginx/html --name jerry-custom nginx
使用 vi 將主機目錄 nginx-html 下面的 index.html 修改成自定義內(nèi)容:
通過交互式的方式進入到docker容器內(nèi)部:
docker exec -it jerry-custom /bin/sh
發(fā)現(xiàn) Docker 容器里的 index.html 也自動被修改了,內(nèi)容和主機目錄 nginx-html 下面的一致。
localhost:1081 即可看到修改過后的自定義 Nginx 首頁:
總結(jié)
本文首先通過一個簡單的例子,介紹了 Docker 和宿主機操作系統(tǒng)文件目錄互相隔離,是如何通過 Linux 命令 chroot 的實現(xiàn)原理,接著用修改 Nginx Docker 鏡像 index.html 的實際例子,闡述了 Docker Volume 的實現(xiàn)原理和使用方法。
總結(jié)
以上是生活随笔為你收集整理的Docker 实战教程之从入门到提高(二)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 亚马逊云科技公益计划首个人工智能体验中心
- 下一篇: Map-Reduce 思想在 ABAP