在前文,我們介紹了Docker學習的基本方法和原理,以及基礎三大件:鏡像、容器、倉庫,還有Dockerfile和資料卷,
回顧:
Docker小白入門建議及基本原理介紹
Docker速學(一) 鏡像和容器
Docker速學(二) Dockerfile和資料卷
今天,小九給大家介紹的內容是用戶、網路和行程,在學習中深刻理解 Docker 網路的概念和原理是非常重要的,接下來,讓我們一起學習吧~
網路
由于容器是用于部署應用的,因此它需要頻繁的被其他服務所訪問,深刻理解 Docker 網路的概念和原理就顯得至關重要,
組網
對于Docker系統來說,默認有一個容器路由功能,簡單的說,Docker會給每個部署好的Container生成一個內網IP地址,例如,Docker下運行了容器,Docker就自動分配了3個內網地址:
容器1 172.18.0.1
容器2 172.18.0.2
容器3 172.18.0.23
對于其中任何Container來說,都可以通過IP地址作為訪問通道
埠
每個Container,都可以映射到服務器的一個埠上,以便于外部訪問這個Container, 例如:172.18.0.1 上運行了MySQL,且MySQL本身開啟了外部訪問,這個時候,如何通過服務器的IP地址來訪問這個MySQL呢?
- 首先,將容器1的做一個埠映射,加入映射到都服務器的3306埠
- 然后,通過 服務器IP:3306 就可以訪問MySQL
問題:Container中的應用為什么有埠號?Container是帶最簡的作業系統的,有作業系統就一定會通過埠訪問程式
用戶
一般來說 Docker 不建議以 root 用戶運行容器行程,因此 Dockerfile 的撰寫者都會在代碼中創建普通用戶,然后以普通用戶運行行程,
如果沒有創建普通用戶,容器就會默認以 root 用戶權限運行
容器的 root 與宿主機的 root 是同一個用戶,但容器 root 的權限是有限的,如果加上 --privileged=true,那么它就等同于宿主機 root 權限

UID
雖然有用戶名的概念,但由于 Linux 內核最終管理的用戶物件是以 uid 為標識,所以本節均以 uid 來替代用戶名,
容器由于是基于虛擬隔離技術的并共享作業系統內核的獨立行程,而內核只管理一套 uid 和 gid,所以容器中的 uid 和 gid 實際上與宿主機內核是一套體系,
理解容器中用戶權限、uid、gid 等本質,重點在于理解 《Linux User Namespace》
當容器行程嘗試寫檔案時,內核會檢查此容器的 uid 和 gid,以確定其是否具有足夠的特權來修改檔案,
提權
我們在 Dockerfile 會發現,當需要對用戶提權的時候,采用的不是 su,而是下面兩個命令的組合
- gosu
- exec
行程
有人說,容器的本質就是行程,不管這句話是否絕對,但可見行程對于容器的重要性不言而喻,
查詢行程
通過運行 docker top containerid 查詢行程,
為了便于理解,我們先運行一個Docker應用:docker-wordpress(opens new window)
然以后分別查詢各個容器的行程,
[root@test ~]# docker top wordpress-mysql
UID PID PPID C STIME TTY TIME CMD
polkitd 22107 22080 0 Aug01 ? 00:01:52 mysqld
[root@test ~]# docker top wordpress
UID PID PPID C STIME TTY TIME CMD
33 807 22090 0 Aug01 ? 00:00:00 apache2 -DFOREGROUND
33 1675 22090 0 Aug01 ? 00:00:01 apache2 -DFOREGROUND
33 2935 22090 0 Aug01 ? 00:00:00 apache2 -DFOREGROUND
33 21955 22090 0 Aug01 ? 00:00:00 apache2 -DFOREGROUND
root 22090 22054 0 Aug01 ? 00:00:06 apache2 -DFOREGROUND
33 26327 22090 0 Aug01 ? 00:00:00 apache2 -DFOREGROUND
33 28793 22090 0 Aug01 ? 00:00:01 apache2 -DFOREGROUND
33 30253 22090 0 Aug01 ? 00:00:00 apache2 -DFOREGROUND
33 31445 22090 0 Aug01 ? 00:00:01 apache2 -DFOREGROUND
33 31955 22090 0 Aug01 ? 00:00:01 apache2 -DFOREGROUND
33 32734 22090 0 Aug01 ? 00:00:01 apache2 -DFOREGROUND
可見有的容器只運行了一個行程,而有的容器運行了多個行程(Apache 作為HTTP服務器,其天生是多行程設計),
也可以進入其中一個容器,再運行 ps -ef 命令查看行程:
UID PID PPID C STIME TTY TIME CMD
root 1 0 0 Aug01 ? 00:00:06 apache2 -DFOREGROUND
www-data 153 1 0 Aug01 ? 00:00:01 apache2 -DFOREGROUND
www-data 181 1 0 Aug01 ? 00:00:00 apache2 -DFOREGROUND
www-data 193 1 0 Aug01 ? 00:00:01 apache2 -DFOREGROUND
www-data 209 1 0 Aug01 ? 00:00:01 apache2 -DFOREGROUND
www-data 214 1 0 Aug01 ? 00:00:01 apache2 -DFOREGROUND
www-data 215 1 0 Aug01 ? 00:00:00 apache2 -DFOREGROUND
www-data 218 1 0 Aug01 ? 00:00:01 apache2 -DFOREGROUND
www-data 219 1 0 Aug01 ? 00:00:00 apache2 -DFOREGROUND
www-data 224 1 0 Aug01 ? 00:00:00 apache2 -DFOREGROUND
www-data 225 1 0 Aug01 ? 00:00:00 apache2 -DFOREGROUND
root 253 0 0 06:17 pts/0 00:00:00 bash
root 261 253 0 06:18 pts/0 00:00:00 ps -ef
可見,兩者的效果是一樣的,
新開一個 Shell 視窗,再運行 pstree -a 命令,回看到如下的行程樹
├─containerd-shim -namespace moby -id 8a7712fe435afaa79c08e7281de7e1a658cd00261fecc7ba02da1847d47d1715 -address /run/containerd/containerd.sock
│ ├─apache2 -DFOREGROUND
│ │ ├─apache2 -DFOREGROUND
│ │ ├─apache2 -DFOREGROUND
│ │ ├─apache2 -DFOREGROUND
│ │ ├─apache2 -DFOREGROUND
│ │ ├─apache2 -DFOREGROUND
│ │ ├─apache2 -DFOREGROUND
│ │ ├─apache2 -DFOREGROUND
│ │ ├─apache2 -DFOREGROUND
│ │ ├─apache2 -DFOREGROUND
│ │ └─apache2 -DFOREGROUND
│ ├─bash
│ └─12*[{containerd-shim}]
├─containerd-shim -namespace moby -id d287c79eaced1fcdde94b2b6d45781937cb17a0ddf4848d26907dee40602e80f -address /run/containerd/containerd.sock
│ ├─mysqld
│ │ └─30*[{mysqld}]
│ └─13*[{containerd-shim}]
你會發現,這個查詢結果也基本類同,
創建行程
通過上面的說明,我們已經有了非常具體的行程印象,那么現在我們再深入一些:容器的行程是如何創建的呢?
我們先回顧 Dockerfile 中的 CMD 和 ENTRYPOINT,其他它就是容器的運行時,鏡像提供了容器運行所需的軟體包和軟體環境,但如果不通過 CMD 和 ENTRYPOINT 來啟動各種應用,容器就不會產生行程,
非服務行程
容器一般的用于承載服務,但在開發中,容器鏡像也可以用作短暫的行程:在我們計算機上運行的、容器化的可執行命令,這些容器執行單一的任務,生命周期短暫,而且通常可以在使用后被洗掉,我們稱之為可執行鏡像,這樣的鏡像創建的容器的行程可以稱之為非服務行程,
主行程
在Docker中有一個很特殊的行程(PID=1 的行程),這也是Docker的主行程,通過 Dockerfile 中的 ENTRYPOINT 和/或 CMD指令指定,當主行程退出的時候,容器所擁有的 PIG 命名空間就會被銷毀,容器的生命周期也會結束 Docker 最佳實踐建議的是一個 container 一個 service,并不強制要你一個container一個執行緒,有的服務,會催生更多的子行程,比如 Apache 和 uwsgi,這是完全可以的,
PID1行程需要對自己創建的子行程負責,當主行程沒有設計好,不能優雅地讓子行程退出,就會照成很多問題,比如資料庫 container,如果處理資料的行程沒有優雅地退出,可能會照成資料丟失,如果很不幸,你的主行程就是這種管理不了子行程的那種,Docker 提供了一個小工具,幫助你來完成這部分內容,你只需要在 run 創建 container 的時候提供一個 —init flag 就行,Docker 就會手動為你處理好這些問題,
Docker 的主行程由于是一個很特殊的存在,它的生命周期就是 docker container 的生命周期,它得對產生的子行程負責,在寫 Dockerfile 的時候,務必明確 PID1 行程是什么,
下篇內容:
Docker速學(四) 編排、集群和常見命令總結
本文由Websoft9原創發布,轉載請注明出處,
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/296268.html
標籤:其他
