docker小冊學習之二——使用容器

第6課 鏡像與容器

Docker鏡像

定義:docker鏡像是基於unionFS文件系統的一組鏡像層依次掛載而得,而每個鏡像層包含的其實是對上一層鏡像層的修改,這些修改是發生在容器運行過程中的。可以反過來理解,鏡像是對容器運行環境進行持久化存儲的結果。

docker images   //查看鏡像

第7課 從倉庫中獲取鏡像

docker pull ubuntu //獲取鏡像

docker search ubuntu  //查找鏡像

docker inspect redis:3.2  //獲得鏡像的詳細信息

docker rmi redis:3.2 redis:4.0 //刪除鏡像,支持同時刪除多個

第8課 運行和管理容器

容器的狀態

  1. Created:容器已經被創建,容器所需的相關資源已經準備就緒,但容器中的程序還未處於運行狀態。
  2. Running:容器正在運行,也就是容器中的應用正在運行。
  3. Paused:容器已經暫停,表示容器中的所有程序都處於暫停(不是停止)狀態。
  4. Delete:容器已經刪除,相關佔用的資源存儲在Docker中的管理信息也都已釋放和刪除。
docker create nginx:1.12 //創建容器
docker create --name nginx:1.12 //創建容器,配置容器名

docker start nginx //啓動容器

docker run --name nginx -d nginx:1.12  //docker run相當於docker create和docker start合成一步。 -d 或 --detach 進入後臺

docker ps // 列出所有容器(運行中)
docker ps -a //所有容器,或 --all
//所列出列中的 status,表示容器所處的狀態,     
//常見狀態三種:Created:此時容器已創建,但還沒被啓動過; Up[Time] 這時容器處於正在運行狀態,而這裏的Time表示容器從開始運行到查看時的時間; Exited([Code])[Time] 容器已經結束運行,這裏的code表示容器結束運行時,主程序返回的退出碼,而TIme則表示容器結束到查看時的時間。

docker stop nginx  // 停止正在運行的容器

docker rm nginx  // 刪除容器 -f 或 --force可以強制刪除正在運行的容器

docker exec nginx more /etc/hostname  //docker exec命令讓容器來運行我們所給出的命令

docker exec -it nginx bash //進入容器bash  -i:保持輸入流   -t:啓用一個僞終端  -it 一般連着用

docker attach nginx  //將當期那輸入輸出流連接到指定容器   限制較多,用的較少

第9課 爲容器配置網絡

容器網絡

  1. 沙盒(Sandbox):提供了容器的虛擬網絡棧,也就是之前所提到的端口套接子、IP路由表、防火牆等內容。其實現隔離了容器網絡與宿主機網絡,形成了完全獨立的容器網絡環境。
  2. 網絡可以理解爲docker內部的虛擬子網,網絡內的參與者相互可見並能夠進行通訊。Docker的這種虛擬網絡也是宿主機網絡存在隔離關係的,其目的主要是形成容器間的安全通訊環境。
  3. 端點是位於容器或網絡隔離牆上的洞,其主要目的是形成一個可以控制的突破封閉的網絡環境的出入口。當容器的端點與網絡的端點形成配對後,就如同在這兩者之間搭起了橋樑,便能夠進行數據傳輸了。

docker的網絡實現

目前docker官方爲我們提供了五種docker驅動,分別是:Bridge Driver,Host Driver,Overlay Driver,None Driver。

容器互聯

docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes mysql
docker run -f --name webapp --link mysql webapp:latest

jdbc: 
String url = "jdbc:mysql://mysql:3306/webapp";

暴露端口

docker run -d --name mysql -e MYSQL_RANDOM_ROOT_PASSWORD=yes --expose 13306 --expose 23306 mysql:5.7

//通過別名連接
docker run -d --name webapp --link mysql:database webapp:latest

java:
String url = "jdbc:mysql//database:3306/webapp";

管理網絡

docker inspect mysql  //查看容器,network中查看容器相關的網絡信息

創建網絡

docker CLI裏與網絡相關的命令都以docker network開頭,其中創建網絡的命令是 docker network create

docker network create -d bridge individual  //創建網絡
docker network ls // 查看docker中已經存在的網絡
docker network list // 同上

//創建容器時,通過--network來指定容器所加入的網絡,被指定後,容器不會默認加入到bridge網絡中
docker run -a --name mysql -e MYSQL_RANDOM_ROOT=yes --network individual mysql:5.7 
//此時,通過--link讓處於另外一個網絡的容器連接到這個容器上,報錯
docker run -d --name webapp --link mysql --network bridge webapp:latest
// 改變一下,讓運行web應用的容器加入到individual這個網絡,就成功建立容器間網路連接啦
docker run -d --name webapp --link mysql --network individual webapp:latest

端口映射

格式:-p ::,ip是宿主操作系統的監聽ip,可以用來控制監聽的網卡,默認是0.0.0.0,也就是監聽所用網卡。 host-port和container-port分別表示映射到宿主機的端口和容器的端口,這兩者可以不一樣。將容器的80端口映射到宿主機操作系統的8080端口,傳入 -p 8080:80即可

docker run -d --name nginx -p 80:80 -p 443:443 nginx:1.12

思考

通過docker網絡進行的容器互聯,與通過宿主機端口映射的容器互聯有怎樣的區別,又各有怎樣的優劣?

回答:
docker網絡進行的容器互聯是橫向的,各個容器是平等的。與宿主機進行端口映射的容器互聯是縱向的。容器互聯甚至不需要知道ip,只要知道需要連接容器的名稱和應用端口,把容器名映射爲ip。宿主機端口映射在網橋網絡中只需要把宿主的端口和容器端口進行映射即可,也不用管ip,是一種端口轉發,需要設定雙方的對應端口。
容器互聯講究的更多是容器內部的互相訪問,端口映射更講究的是通過宿主機外部訪問到容器。

第10節 管理和存儲數據

數據管理的實現方式

dcoker容器中的文件系統雖有很多優勢,但也有很多弊端,其中最顯著的是

  1. 沙盒文件系統是跟隨容器生命週期所創建和移除的,數據無法直接被持久化存儲。
  2. 由於容器隔離,我們很難從容器外部獲得操作容器內部文件中的數據。

掛載方式:

  1. Bind Mount:能夠直接將宿主操作系統中的目錄和文件掛載到容器內的文件系統中,通過指定容器外的路徑和容器內的路徑,就可以形成掛載映射關係,在容器內外對文件的讀寫,都是相互可見的。
  2. Voulume:也是從宿主操作系統中掛載目錄到容器內,只不過這個掛載目錄由Docker進行管理,我們只需要指定容器內的目錄,不需要關心具體掛載到了宿主操作系統的哪裏。
  3. Tmpfs Mount:支持掛載系統內存中一部分到容器的文件系統裏,不過由於內存和容器的特徵,它的存儲並不是持久的,其中的內容隨着容器的停止而消失。

掛載文件到容器

使用-v或者–volune來掛載, -v : ,需要注意,爲了避免混淆,docker這裏強制定義目錄時必須使用絕對路徑,不能使用相對路徑。

docker run -d --name nginx -v /webapp/html:/usr/share/nginx/html nginx:1.12

//掛載目錄的容器啓動後,宿主機操作系統中的文件已經出現在容器中
docker exec nginx ls /usr/share/nginx/html

//docker inspect查看容器詳情  
docker inspect nginx
    {
## ......
        "Mounts": [
            {
                "Type": "bind",
                "Source": "/webapp/html",
                "Destination": "/usr/share/nginx/html",
                "Mode": "",
                "RW": true,
                "Propagation": "rprivate"
            }
        ],
## ......
    }
//在“Mounts”中可以看到有關容器掛載的信息,其中“RW”表示讀寫性,如果希望容器只讀
docker run -d --name nginx -v /webapp/html:/usr/share/nginx/html:ro nginx:1.12

掛載臨時文件目錄

掛載臨時文件目錄需要通過–tmpfs來完成,由於內存的具體位置無需我們來指定,這個選項裏只需傳遞掛載到容器內的目錄即可。

docker run -d --name webapp --tmpfs /webapp/cache webapp:latest
docker inspect webapp
    {
## ......
         "Tmpfs": {
            "/webapp/cache": ""
        },
## ......
    }

使用數據卷

除了與其他虛擬機工具近似的宿主操作系統目錄掛載的功能意外,docker還創造了數據卷(Volume)這個概念。 數據卷的本質依然是宿主機操作系統上的一個目錄,只不過這個目錄存放在Dokcer內部,接受docker的管理。
使用數據卷掛載時,不需要知道數據具體存儲在了宿主操作系統的何處,只需要給定容器中哪個目錄會被掛載即可。

依舊使用 -v 或者 --volume 來實現

docker run -d --name webapp -v /webapp/storage webapp:latest

docker inspect webapp
    {
## ......
        "Mounts": [
            {
                "Type": "volume",
                //數據卷命名,也可以通過 -v <name>:<container-path>來進行命名。
                // 由於-v即可以用來bind Mount的定義,又參與volume,所以其參數方式需要特別留意。所以 -v定義掛載時,需要使用絕對路徑,目的就是避免與數數據卷掛載中命名這種形式的衝突
                "Name": "2bbd2719b81fbe030e6f446243386d763ef25879ec82bb60c9be7ef7f3a25336",
                // source 是docker爲我們分配用於掛載的宿主機目錄,位於docker的資源區域(默認是/var/lib/docker),我們無需關心這個目錄,對它的管理已經在docker中實現
                "Source": "/var/lib/docker/volumes/2bbd2719b81fbe030e6f446243386d763ef25879ec82bb60c9be7ef7f3a25336/_data",
                "Destination": "/webapp/storage",
                "Driver": "local",
                "Mode": "",
                "RW": true,
                "Propagation": ""
            }
        ],
## ......
    }

共用數據卷

數據卷的另一大作用是實現容器內的目錄共享,也就是通過掛載相同的數據卷,讓容器之間能夠同時看到並操作數據卷中的內容。雖也能通過綁定掛載來實現,但是數據卷操作更加舒適簡單。

// 數據卷名在docker中是惟一的,所以讓多個容器掛載同一個數據卷即可
docker run -d --name webapp -v html:/webapp/html webapp:latest
docker run -d --name nginx -v html:/usr/share/nginx/html:ro nginx:1.12

//專門用於操作數據卷的命令
docker volume create appdata  // 創建名稱爲appdata的數據卷
docker volume ls  //列出當前已創建的數據卷

刪除數據卷

docker volume rm appdata  // 刪除名爲 appdata的數據卷

//刪除容器的命令中 加 -v 可以刪除掉容器關聯的數據卷
docker rm -v webapp 

docker volume prune   //刪除沒有被容器引用的數據卷

數據卷容器

所謂數據卷容器,就是一個沒有具體指定的應用,甚至不需要運行的容器,我們使用它的目的,是爲了定義一個或多個數據卷並持有它們的引用。

創建數據卷容器方式很簡單,由於不需要容器本身運行,因而找個簡單的系統鏡像都可以完成創建。
使用數據卷容器時,不建議再定義數據卷的名稱,我們可以通過對數據卷容器的引用來完成數據卷的引用。

docker create --name appdata -v /webapp/storage ubuntu

之前提到,Docker的Network是容器間的網絡橋樑,如果類比,數據卷容器就可以算是容器間的文件系統橋樑。我們可以向加入網絡一樣引用數據卷容器, 只需要在創建新容器時使用專門的 --volumes-from選項即可。

docker run -d --name webapp --volumes-from appdata webapp:latest

引用數據卷容器時,不需要再定義數據卷掛載到容器中的位置,docker會以數據卷容器中的掛載定義將數據卷掛載到引用的容器中。

備份和遷移數據卷

利用數據卷容器,我們還可以能夠更方便的對數據卷中的數據進行遷移。
對數據的備份、遷移、恢復的過程我們可以理解爲對數據進行打包、移動到其他位置,在需要的地發進行解壓的過程。

docker run --rm --volumes-from appdata -v /backup:/backup ubuntu tar cvf /backup/backup.tar /webapp/storage
//命令解析 /backup 是我們用來存放打包文件的目錄
// --rm 我們可以讓容器停止後自動刪除,臨時容器中很有幫助
// tar cvf /backup/backup.tar /webapp/storage 在容器所定義的鏡像之後的命令。 在鏡像定義之後接上命令,可以直接替換掉所定義的主程序啓動命令,而去執行本條命令。

備份之後,我們可以在/backup下找到數據卷的備份文件,也就是backup.tar了。

如果恢復數據卷中的數據,我們也藉助臨時容器完成

docker run --rm --volumes-from appdata -v /backup:/backup ubuntu tar xvf /back/backup.tar -C /webapp/storage --strip
//恢復過程與備份類似,只不過把打包的命令轉換爲解包的命令

另一個掛載選項

-v選項來掛載存在容易混淆的問題,主要原因是掛載的方式和配置隨着docker的不斷髮展日漸豐富,而-v選項的傳參方式限制了它的使用場景。
Docker中爲我們提供了一個相對支持豐富的掛載方式,也就是通過–mount這個選項配置掛載

docker run -d --name webapp webapp:latest --mount 'type=volume,src=appdata,dst=/webapp/storage,volume-driver=local,volume-opt=type=nfs,volume-opt=device=<nfs-server>:<nfs-path> ' webapp:latest

//--mount 通過逗號分割這種CVS格式來定義多個參數,其中type是掛載類型,可以是: bind,volume,tmpfs。  

另外 --mount選項能夠幫助我們實現集羣掛載的定義,如本例,我們掛載的來源是一個NFS目錄。

實際開發中,-v基本滿足我們的需求,所以不常用相對複雜的–mount定義掛載。

留言互動

問題: 結合我們所提到的三種掛載方式各自適用的場景,分別嘗試使用它們進行數據掛載

答:

  1. 掛載文件方式,docker從本地讀取文件場景:把宿主機的文件掛載到docker,可以方便指定軟件的配置相關文件,比如 nginx.conf,mysqli.ini,tomcat的server.xml等。
  2. 掛載卷的方式,docker寫入本地的場景:文件服務器,ftp服務器,要把服務產生的數據寫入到宿主機,幾個容器之間還可共享。
  3. 掛載tmpfs:掛載內存文件到docker適合高速讀寫的問加,適合不需要持久化類似session性質問加,重點理解tmp臨時性,和內存高性能讀寫兩個點。

PS: 這是學習docker小冊的筆記,附上小冊地址:https://juejin.im/book/5b7ba116e51d4556f30b476c

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章