圖文詳細教程
1 Docker原理
-
對 Docker 最簡單並且帶有一定錯誤的認知就是 “Docker 是一種性能非常好的虛擬機”。
- 正如上面所說,這是有一定錯誤的說法。Docker 相比於傳統虛擬機的技術來說先進了不少,
- 具體表現在 Docker 不是在宿主機上虛擬出一套硬件(VMare VBox虛擬機都是需要虛擬硬件,需要佔用內存和硬盤)後再虛擬出一個操作系統,
- 而是讓 Docker 容器裏面的進程直接運行在宿主機上(Docker 會做文件、網絡等的隔離),
- 這樣一來 Docker 會 “體積更輕、跑的更快、同宿主機下可創建的個數更多”。
-
Docker 中有三個核心概念:Image、Container、Repository。
-
Image 鏡像:
- 有領“好人卡”傾向的廣大程序猿一定對 鏡像 的概念不會陌生。
- 但和 windows 的那種 iso 鏡像相比,Docker 中的鏡像是分層的,可複用的,
- 而非簡單的一堆文件迭在一起(類似於一個壓縮包的源碼和一個 git 倉庫的區別)。
-
Container 容器:
- 容器的存在離不開鏡像的支持,他是鏡像運行時的一個載體(類似於實例和類的關係)。
- 依託 Docker 的虛擬化技術,給容器創建了獨立的端口、進程、文件等“空間”,
- Container 就是一個與宿機隔離 “容器”。容器可宿主機之間可以進行 port、volumes、network 等的通信。
- 容器存儲層的生存週期和容器一樣,容器消亡時,容器存儲層也隨之消亡。因此,任何保存於容器存儲層的信息都會隨容器刪除而丟失。
- 數據卷的生存週期獨立於容器,容器消亡,數據卷不會消亡。因此,使用數據卷後,容器刪除或者重新運行之後,數據卻不會丟失。
-
Repository 倉庫:
- Docker 的倉庫和 git 的倉庫比較相似,擁有倉庫名、tag。
- 在本地構建完鏡像之後,即可通過倉庫進行鏡像的分發。
- 常用的 Docker hub 有 https://hub.docker.com/ 、 https://cr.console.aliyun.com/ 等。
- 以 Ubuntu 鏡像 爲例,ubuntu 是倉庫的名字,其內包含有不同的版本標籤,如,16.04, 18.04。
- 我們可以通過 ubuntu:16.04,或者 ubuntu:18.04 來具體指定所需哪個版本的鏡像。如果忽略了標籤,比如 ubuntu,那將視爲 ubuntu:latest。
- 倉庫名經常以 兩段式路徑 形式出現,比如 jwilder/nginx-proxy,前者往往意味着 Docker Registry 多用戶環境下的用戶名,後者則往往是對應的軟件名。
-
鏡像(Image)和容器(Container)的關係,就像是面向對象程序設計中的 類 和 實例 一樣,
-
鏡像是靜態的定義,容器是鏡像運行時的實體。容器可以被創建、啓動、停止、刪除、暫停等。
-
2 Docker安裝
-
Ubuntu虛擬機中安裝docker:docker-ce docker-ce-cli docker-compose
-
docker全部安裝完成後,鏡像源修改中國的加速源地址,終端執行命令創建 sudo vi /etc/docker/daemon.json 文件,在其中輸入如下內容。
{ "registry-mirrors": ["https://registry.docker-cn.com"] }
- 然後輸入:符號,輸入wq保存退出
-
Ubuntu安裝使用Docker注意:
- Docker安裝完成後,如果不修改源,網速不好,有時候啓動或者執行命令會出現失敗或者超時提示
- 安裝博文中提到卸載後重新安裝,後面發現是網速問題,只需要新建daemon.json文件,添加中國源即可
- 注意,有些命令需要使用sudo docker xxx xxx … 執行,直接docker執行會報錯
- 也可以將終端使用 su 回車 輸入超級用戶密碼 回車 進入超級用戶 顯示符號位#
-
Docker拖取鏡像速度慢的終極解決辦法:
- 上面daemon.json雖然添加了官方的加速源地址,電信速度還可以(有時也很慢),但是移動速度很慢,有時候超時或者失敗
- 推薦使用阿里雲鏡像,具體方法參考博文,docker下載鏡像使用阿里雲加速器:
- 具體步驟:
- 1.註冊阿里雲賬號,搜索容器鏡像服務,然後進入
- 2.鏡像倉庫裏面新建一個鏡像倉庫
- 3.左側菜單欄有個鏡像加速器,點開
- 4.複製裏面加速器地址,到daemon.json文件替換https://registry.docker-cn.com,保存退出
- 5.依次執行命令:
- sudo systemctl daemon-reload 重載daemon.json配置文件
- sudo systemctl restart docker 重啓docker服務
- 此時下載速度已經可以達到你的寬帶速度正常值,可以刪除一個鏡像,然後重新下載對比速度。
-
Docker安裝注意事項:
- Docker桌面版,WIN10系統只能專業版和企業版可以安裝
- 家庭版安裝比較麻煩,需要視同toolbox工具或者修改註冊表僞裝爲專業版騙過軟件安裝時候的檢測
- Docker安裝在WIN10下面需要開啓HyperV虛擬功能,該功能開啓後會導致VMware和VirtualBox出錯
- 鑑於以上原因,不推薦在WIN10安裝Docker,建議Ubuntu虛擬機服務器中安裝
- Win10安裝可以具體參考我的QQ瀏覽器收藏夾中,python相關軟件安裝/docker安裝,裏面有家庭版和專業版安裝收藏
3 鏡像(Image)
3.1 獲取鏡像
-
Docker Hub 上有大量的高質量的鏡像可以用,這裏我們就說一下怎麼獲取這些鏡像。
-
從 Docker 鏡像倉庫獲取鏡像的命令是 docker pull。其命令格式爲:
- docker pull [選項] [Docker Registry 地址[:端口號]/]倉庫名[:標籤]
-
具體的選項可以通過 docker pull --help 命令看到,這裏我們說一下鏡像名稱的格式。
-
Docker 鏡像倉庫地址:地址的格式一般是 <域名/IP>[:端口號]。默認地址是 Docker Hub。
-
倉庫名:如之前所說,這裏的倉庫名是兩段式名稱,即 <用戶名>/<軟件名>。
-
對於 Docker Hub,如果不給出用戶名,則默認爲 library,也就是官方鏡像。
-
比如:
- docker pull ubuntu:18.04
- 上面的命令中沒有給出 Docker 鏡像倉庫地址,因此將會從 Docker Hub 獲取鏡像,省略了官方用戶名 library
- 而鏡像名稱是 ubuntu:18.04 實際將會獲取官方鏡像 library/ubuntu 倉庫源中獲取標籤爲 18.04 的鏡像
- docker pull httpd 不指定版本,默認獲取latest
- docker pull tikazyq/crawlab:latest
- 從DockerHub官方中的tikazyq用戶獲取crawlab鏡像,版本爲最新的latest
- docker pull registry.cn-hangzhou.aliyuncs.com/crawlab-team/crawlab:latest
- 鏡像地址:registry.cn-hangzhou.aliyuncs.com
- 倉庫名:用戶名/軟件名
- 用戶名:crawlab-team
- 軟件名:crawlab
- 標籤:latest
- 從下載過程中可以看到我們之前提及的分層存儲的概念,鏡像是由多層存儲所構成。
- 下載也是一層層的去下載,並非單一文件。下載過程中給出了每一層的 ID 的前 12 位。
- 並且下載結束後,給出該鏡像完整的 sha256 的摘要,以確保下載一致性。
- docker pull ubuntu:18.04
-
鏡像獲取完成後,執行 docker images 即可看到本地所有的鏡像
-
-
運行一個簡單的容器,以ubuntu:18.04爲基礎鏡像
- docker run -it --rm ubuntu:18.04 /bin/bash
- docker run 就是運行容器的命令,具體格式我們會在 容器 一節進行詳細講解,我們這裏簡要的說明一下上面用到的參數。
- 參數 -it 實際是兩個參數,一個是 -i:交互式操作,一個是 -t 終端。我們這裏打算進入 bash 執行一些命令並查看返回結果,因此我們需要交互式終端。
- 參數 --rm 這個參數是說容器退出後隨之將其刪除。默認情況下,爲了排障需求,退出的容器並不會立即刪除,除非手動 docker rm。
- 我們這裏只是隨便執行個命令,看看結果,不需要排障和保留結果,因此使用 --rm 可以避免浪費空間。
- 參數 ubuntu:18.04 這是指用 ubuntu:18.04 鏡像爲基礎來啓動容器。
- 參數 /bin/bash 放在鏡像名後的是 命令,這裏我們希望有個交互式 Shell 終端,因此用的是 bash
- 改命令執行以後,就啓動了一個ubuntu系統下的shell終端,然後我們可以終端操作
- cat /etc/os-release 查看當前容器鏡像系統版本信息,cat命令就是打開查看文件信息
- ls 查看當前根目錄下有哪些文件夾及文件
- 最後我們通過 exit 命令退出了這個容器
3.2 查找拖取鏡像
- 查找鏡像
- Docker Hub 網站來搜索鏡像,Docker Hub 網址爲: https://hub.docker.com/ 直接訪問網速不好
- docker search 命令來搜索鏡像。比如我們需要一個 httpd 的鏡像來作爲我們的 web 服務
- 比如我們需要一個 httpd 的鏡像來作爲我們的 web 服務。我們可以通過 docker search 命令搜索 httpd 來尋找適合我們的鏡像。
- docker search httpd
- 拖去鏡像(參考上面3.1)
- docker pull httpd
3.3 列出鏡像
-
列出鏡像
- 以下兩個命令都可以
- docker image ls
- docker images
- 鏡像按CREATED,即創建時間排列,最近創建的在最上面
- 列表包含了 倉庫名、標籤、鏡像 ID、創建時間 以及 所佔用的空間
- 鏡像 ID 則是鏡像的唯一標識,一個鏡像可以對應多個 標籤, 因爲標籤相當於版本號,一個Ubuntu就有多個版本
- 以下兩個命令都可以
-
列出鏡像各個選項說明:
- REPOSITORY:表示鏡像的倉庫源(類似軟件名稱)
- TAG:鏡像的標籤 (類似軟件版本號)
- IMAGE ID:鏡像ID
- CREATED:鏡像創建時間
- SIZE:鏡像大小
-
同一倉庫源可以有多個 TAG,代表這個倉庫源的不同個版本,如 ubuntu 倉庫源裏,有 15.10、14.04 等多個不同的版本,
- 我們使用 REPOSITORY:TAG 來定義同一個倉庫源中不同的鏡像。
-
鏡像體積
- docker image ls 顯示的是鏡像下載到本地後,展開的大小,準確說,是展開後的各層所佔空間的總和,
- 因爲鏡像到本地後,查看空間的時候,更關心的是本地磁盤空間佔用的大小,在Docker Hub上是壓縮後的體積
- 另外一個需要注意的問題是,docker image ls 列表中的鏡像體積總和並非是所有鏡像實際硬盤消耗。
- 由於 Docker 鏡像是多層存儲結構,並且可以繼承、複用,因此不同鏡像可能會因爲使用相同的基礎鏡像,
- 從而擁有共同的層。由於 Docker 使用 Union FS,相同的層只需要保存一份即可,
- 因此實際鏡像硬盤佔用空間很可能要比這個列表鏡像大小的總和要小的多。
- 以下命令來便捷的查看鏡像、容器、數據卷所佔用的空間
- docker system df
- docker system df
-
虛懸鏡像
- 一個特殊的鏡像,這個鏡像既沒有倉庫名,也沒有標籤,均爲
- docker pull 可能導致這種情況,docker build 也同樣可以導致這種現象。
- 由於新舊鏡像同名,舊鏡像名稱被取消,從而出現倉庫名、標籤均爲 的鏡像。
- 這類無標籤鏡像也被稱爲 虛懸鏡像(dangling image)
- 使用以下命令可以查看:
- docker image ls -f dangling=true
- 虛懸鏡像已經失去了存在的價值,是可以隨意刪除的,可以用下面的命令刪除虛懸鏡像。
- docker image prune
-
中間層鏡像
- 爲了加速鏡像構建、重複利用資源,Docker 會利用 中間層鏡像。
- 所以在使用一段時間後,可能會看到一些依賴的中間層鏡像。
- 默認的 docker image ls 列表中只會顯示頂層鏡像,如果希望顯示包括中間層鏡像在內的所有鏡像的話,需要加 -a 參數。
- docker image ls -a
-
列出部分鏡像
- docker image ls ubuntu 列出標籤名爲ubuntu的所有鏡像
- docker image ls ubuntu:18.04 列表指定的鏡像,指定倉庫名和標籤
- docker image ls -f since=mongo:3.2 -f 就是filter過濾參數,列出mongo:3.2之後的鏡像
- docker image ls -f before=mongo:3.2 列出mongo:3.2之前的鏡像
-
特定格式顯示鏡像列表
-
只包含鏡像ID和倉庫名
-
docker image ls --format “{{.ID}}: {{.Repository}}”
5f515359c7f8: redis 05a60462f8ba: nginx fe9198c04d62: mongo 00285df0df87: <none> 1e0c3dd64ccd: ubuntu
-
以表格等距顯示,並且有標題行,和默認一樣,不過自己定義列
-
docker image ls --format “table {{.ID}}\t{{.Repository}}\t{{.Tag}}”
IMAGE ID REPOSITORY TAG 5f515359c7f8 redis latest 05a60462f8ba nginx latest
-
3.4 刪除鏡像
-
刪除本地的鏡像,可以使用 docker image rm 命令,其格式爲:
- docker image rm [選項] <鏡像1> [<鏡像2> …]
- <鏡像> 可以是 鏡像短 ID、鏡像長 ID、鏡像名 或者 鏡像摘要
- 鏡像的完整 ID,也稱爲 長 ID,來刪除鏡像。
- 使用腳本的時候可能會用長 ID,但是人工輸入就太累了,所以更多的時候是用 短 ID 來刪除鏡像。
- docker image ls 默認列出的就已經是短 ID 了,一般取前3個字符以上,只要足夠區分於別的鏡像就可以了
- 刪除示例:
- docker image rm da3fadgad34l 以完整IMAGE ID刪除,推薦使用
- docker image rm 501 短ID,IMAGE ID 前三位
- docker image rm centos 鏡像REPOSITORY倉庫名稱
- docker image rm centos:latest 鏡像REPOSITORY倉庫名和標籤名
- 也可以使用以下命令刪除
- docker rmi hello-world 刪除hello-world鏡像
- 精確的是使用 鏡像摘要 刪除鏡像。
- 查看摘要命令:docker image ls --digests
- 以摘要刪除鏡像,@後面就是摘要:
- docker image rm node@sha256:b4f0e0bdeb578043c1ea6862f0d40cc4afe32a4a582f3be235a3b164422be228
-
刪除ID相同的鏡像,直接使用ID刪除,系統不知道刪除那個,需要使用倉庫名和標籤名刪除
-
批量刪除鏡像
- 刪除所有倉庫名爲 redis 的鏡像:
- docker image rm $(docker image ls -q redis)
- 刪除所有在 mongo:3.2 之前的鏡像:
- docker image rm $(docker image ls -q -f before=mongo:3.2)
- 刪除所有倉庫名爲 redis 的鏡像:
-
刪除命令執行後會出現 Untagged 和 Deleted
-
如果觀察上面這幾個命令的運行輸出信息的話,你會注意到刪除行爲分爲兩類,一類是 Untagged,另一類是 Deleted。
-
我們之前介紹過,鏡像的唯一標識是其 ID 和摘要,而一個鏡像可以有多個標籤。
-
因此當我們使用上面命令刪除鏡像的時候,實際上是在要求刪除某個標籤的鏡像。
-
所以首先需要做的是將滿足我們要求的所有鏡像標籤都取消,這就是我們看到的 Untagged 的信息。
-
因爲一個鏡像可以對應多個標籤,因此當我們刪除了所指定的標籤後,可能還有別的標籤指向了這個鏡像,
-
如果是這種情況,那麼 Delete 行爲就不會發生。
-
所以並非所有的 docker image rm 都會產生刪除鏡像的行爲,有可能僅僅是取消了某個標籤而已。
-
當該鏡像所有的標籤都被取消了,該鏡像很可能會失去了存在的意義,因此會觸發刪除行爲。
-
鏡像是多層存儲結構,因此在刪除的時候也是從上層向基礎層方向依次進行判斷刪除。
-
鏡像的多層結構讓鏡像複用變得非常容易,因此很有可能某個其它鏡像正依賴於當前鏡像的某一層。
-
這種情況,依舊不會觸發刪除該層的行爲。直到沒有任何層依賴當前層時,纔會真實的刪除當前層。
-
這就是爲什麼,有時候會奇怪,爲什麼明明沒有別的標籤指向這個鏡像,但是它還是存在的原因,
-
也是爲什麼有時候會發現所刪除的層數和自己 docker pull 看到的層數不一樣的原因。
-
除了鏡像依賴以外,還需要注意的是容器對鏡像的依賴。
-
如果有用這個鏡像啓動的容器存在(即使容器沒有運行),那麼同樣不可以刪除這個鏡像。
-
之前講過,容器是以鏡像爲基礎,再加一層容器存儲層,組成這樣的多層存儲結構去運行的。
-
因此該鏡像如果被這個容器所依賴的,那麼刪除必然會導致故障。如果這些容器是不需要的,應該先將它們刪除,然後再來刪除鏡像。
-
3.5 創建的鏡像
-
創建鏡像的兩種方式:
- 更新鏡像:從已經創建的容器中更新鏡像,並且提交這個鏡像
- 構建鏡像:使用 Dockerfile 指令來創建一個全新的鏡像
-
更新鏡像:
- 更新鏡像之前,我們需要使用鏡像來創建一個容器。比如:
- runoob@runoob:~$ docker run -t -i ubuntu:15.10 /bin/bash
- root@e218edb10161:/#
- 在運行的容器內使用 apt-get update 命令進行更新。
- 在完成操作(比如在容器下安裝一些包之類)之後,輸入 exit 命令來退出這個容器。
- 此時 ID 爲 e218edb10161 的容器,是按我們的需求更改的容器。我們可以通過命令 docker commit 來提交容器副本。
- 提交鏡像就相當於添加了標籤
- runoob@runoob:~$ docker commit -m=“has update” -a=“runoob” e218edb10161 runoob/ubuntu:v2
- sha256:70bf1840fd7c0d2d8ef0a42a817eb29f854c1af8f7c59fc03ac7bdee9545aff8
- 各個參數說明:
- -m: 提交的描述信息
- -a: 指定鏡像作者
- e218edb10161:容器 ID
- runoob/ubuntu:v2: 指定要創建的目標鏡像名稱,我們創建鏡像時候要使用自己的賬戶名,felixzfb/ubuntu:v2
- ubuntu鏡像通過tag進行區別,上面tag就是v2
- 一個鏡像,不做修改,直接tag添加標籤,新的鏡像和原始鏡像的ID是一樣的
- 特別注意:
- commit 提交時候,軟件名稱斜線前面的用戶名要寫自己dockerhub的賬戶名,不然push到個人倉庫會找不到用戶名,會被denied
- tag 標籤時候,用戶名也是自己的賬戶名,後面是倉庫名稱和tag標籤
- tag 標籤命令可以用來修改鏡像的 REPOSITORY 名稱,也可以同時修改名稱和tag
- 詳細細節參考5.2節更新鏡像實例
- 更新鏡像之前,我們需要使用鏡像來創建一個容器。比如:
-
構建鏡像:
- 首先需要創建一個 Dockerfile 文件,其中包含一組指令來告訴 Docker 如何構建我們的鏡像。
- 比如構建一個
- cat Dockerfile
- docker build -t runoob/centos:6.7 .
- 參數說明:
- -t :指定要創建的目標鏡像名
- . :Dockerfile 文件所在目錄,可以指定Dockerfile 的絕對路徑
- 設置鏡像標籤
- 我們可以使用 docker tag 命令,爲鏡像(可用鏡像ID或者REPOSITORY名稱)添加一個新的標籤(REPOSITORY名稱和TAG)。
- runoob@runoob:~$ docker tag 860c279d2fec runoob/centos:dev
4 容器(Container)
- 容器是獨立運行的一個或一組應用,以及它們的運行態環境,類似一個虛擬機。
- 對應的,虛擬機可以理解爲模擬運行的一整套操作系統(提供了運行態環境和其他系統環境)和跑在上面的應用。
4.1 創建啓動容器
-
啓動容器有兩種方式,一種是基於鏡像新建一個容器並啓動,另外一個是將在終止狀態(stopped)的容器重新啓動。
-
因爲 Docker 的容器實在太輕量級了,很多時候用戶都是隨時刪除和新創建容器。
-
新建容器時候一般不指定容器名稱,名稱都是自動創建的,容器互聯時候指定名稱,參考5.2節
-
方式1:新建並啓動進入容器
-
所需要的命令主要爲 docker run
-
下面的命令輸出一個 “Hello World”,之後就自動終止容器。
- docker run ubuntu:18.04 /bin/echo ‘Hello world’
- Hello world
-
這跟在本地直接執行 /bin/echo ‘hello world’ 幾乎感覺不出任何區別。
-
下面的命令則啓動一個 bash 終端,允許用戶進行交互。
-
docker run -t -i ubuntu:18.04 /bin/bash
-
docker run -it ubuntu:18.04 /bin/bash 該方式推薦使用
-
docker run -it ubuntu /bin/bash 如果ubuntu不指定版本號,會默認實用latest
-
docker run -itd ubuntu:18.04 /bin/bash 容器後臺運行,新建容器時候不進入容器
-
root@af8bae53bdd3:/#
-
參數說明:
- -t 選項讓Docker分配一個僞終端(pseudo-tty)並綁定到容器的標準輸入上,
- -i 則讓容器的標準輸入保持打開
- -d 容器後臺運行,不進入容器(不直接調出終端,要進入容器使用docker exec -it 243c32535da7 /bin/bash)
-
在交互模式下,用戶可以通過所創建的終端來輸入命令,例如
- root@af8bae53bdd3:/# pwd
- /
- root@af8bae53bdd3:/# ls
- bin boot dev etc home lib lib64 media mnt opt proc root run sbin srv sys tmp usr var
-
exit 命令退出容器
-
docker container ls 查看容器信息,裏面是空的
-
-
當利用 docker run 來創建容器時,Docker 在後臺運行的標準操作包括:
- 檢查本地是否存在指定的鏡像,不存在就從公有倉庫下載
- 利用鏡像創建並啓動一個容器
- 分配一個文件系統,並在只讀的鏡像層外面掛載一層可讀寫層
- 從宿主主機配置的網橋接口中橋接一個虛擬接口到容器中去
- 從地址池配置一個 ip 地址給容器
- 執行用戶指定的應用程序
- 執行完畢後容器被終止
-
-
方式2:新建啓動容器(容器後臺運行)
- docker run -itd --name ubuntu-test ubuntu /bin/bash
- 加了 -d 參數默認不會進入容器,想要進入容器需要使用指令 docker exec 命令,參考後面
- docker ps 查看當前運行的容器所有信息
- docker ps -a 查看已經終止的容器所有信息
- 第一列是ID,最後一列是名稱NAMES
-
方式3:啓動已終止容器
- 可以利用 docker start container_id 命令,直接將一個已經終止的容器啓動運行。
- 容器的核心爲所執行的應用程序,所需要的資源都是應用程序運行所必需的。
- 除此之外,並沒有其它的資源。可以在僞終端中利用 ps 或 top 來查看進程信息。
- root@ba267838cc1b:/# ps
- PID TTY TIME CMD
- 1 ? 00:00:00 bash
- 11 ? 00:00:00 ps
- 可見,容器中僅運行了指定的 bash 應用。這種特點使得 Docker 對資源的利用率極高,是貨真價實的輕量級虛擬化
- root@ba267838cc1b:/# ps
- 再次啓動已經終止的容器,啓動後是在後臺運行的
- docker start container_id
- 是在後臺運行的,可以使用命令查看:docker container ls
- docker stop container_id 終止容器
- 再次docker container ls查看已經沒有容器了
4.2 終止、重啓容器
- docker stop container 來終止一個運行中的容器。
- 此外,當 Docker 容器中指定的應用終結時,容器也自動終止。
- 例如對於上一章節中只啓動了一個終端的容器,用戶通過 exit 命令或 Ctrl+d 來退出終端時,所創建的容器立刻終止。
- 終止狀態的容器可以用以下兩個命令查看,結果相同:
- docker container ls -a
- docker ps -a
- docker restart container_id 重新啓動當前的容器
4.3 進入後臺容器
- 進入容器使用 -d 參數時,容器啓動後會進入後臺。此時想要進入容器,可以通過以下指令進入:
- docker attach:不推薦使用,使用 exit 退出容器時,容器會自動終止
- docker attach 243c32535da7
- docker exec:推薦大家使用 docker exec 命令,因爲此方法退出容器終端,不會導致容器的停止
- docker exec -it 243c32535da7 /bin/bash
- docker attach:不推薦使用,使用 exit 退出容器時,容器會自動終止
4.4 導出和導入容器
- docker export命令
- docker export 7691a814370e > ubuntu.tar
- 導出容器到本地文件
- docker import 從容器快照文件中再導入爲鏡像
- cat ubuntu.tar | docker import - test/ubuntu:v1.0
- test/ubuntu軟件名稱,v1.0爲版本號
- 也可以通過指定 URL 或者某個目錄來導入,例如
- docker import http://example.com/exampleimage.tgz example/imagerepo
4.5 刪除容器
- 刪除容器使用 docker rm 命令,刪除容器是刪除後臺運行或者已終止的容器,因爲容器id是唯一的
- docker rm 容器名稱或ID
- docker rm -f 容器名稱或ID
- docker ps -a 查看已終止的容器
- docker ps -l 查看最後一次創建的容器
- 注意:刪除容器時,容器必須是停止狀態,否則會報如下錯誤
- 刪除所有已終止的容器
- docker container prune
- docker container prune
4.5 容器運行一個簡單Web應用實例
-
docker容器中運行一個 Python Flask 應用來運行一個web應用
-
1.新建容器
-
docker pull training/webapp # 載入鏡像
-
docker run -d -P training/webapp python app.py
-
參數說明:
- -d:讓容器在後臺運行。
- -P:將容器內部使用的網絡端口映射到我們使用的主機上。
- Docker 開放了 5000 端口(默認 Python Flask 端口)映射到主機端口 32768 上。
-
通過主機的瀏覽器訪問容器內部WEB應用:192.168.0.21:5000
-
-p 指定映射端口
- docker run -d -p 5000:5000 training/webapp python app.py
- docker ps 查看容器列表信息,裏面有端口PORTS的詳細映射信息
-
-
2.查看容器映射網絡端口
- docker port container_name or container_id 可以查看容器端口的映射情況
- 5000/tcp -> 0.0.0.0:5000 前面是容器端口,後面是映射的主機(0.0.0.0就是當前電腦主機)和端口
- docker port container_name or container_id 可以查看容器端口的映射情況
-
3.查看Web應用程序日誌
- docker logs -f 容器名稱或者ID
- -f: 讓 docker logs 像使用 tail -f 一樣來輸出容器內部的標準輸出。
- 退出使用ctrl + z 或者 ctrl + d
-
4.查看web應用程序的進程
- docker top 容器名稱或者ID
-
- 檢查 WEB 應用程序
- docker inspect 容器名稱或者ID
- 查看 Docker 的底層信息。它會返回一個 JSON 文件記錄着 Docker 容器的配置和狀態信息。
-
6.停止 WEB 應用容器
- docker stop 容器名稱或者ID
-
7.重啓WEB應用容器
- 已經停止的容器,我們可以使用命令 docker start 來啓動。
- docker start 容器名稱或者ID
5 Docker 容器連接
5.1 網絡端口映射
-
上面的4.5節中我們實現了通過網絡端口來訪問運行在 docker 容器內的服務。
-
容器中可以運行一些網絡應用,要讓外部也可以訪問這些應用,可以通過 -P 或 -p 參數來指定端口映射。
- -P : 是容器內部端口隨機映射到主機的高端口。
- -p : 是容器內部端口綁定到指定的主機端口。
- 比如以下實例:
- docker run -d -P training/webapp python app.py
- PORTS: 0.0.0.0:32768->5000/tcp 容器應用的5000端口映射到主機上的32768端口
- docker run -d -p 5000:5000 training/webapp python app.py
- PORTS: 0.0.0.0:5000->5000/tcp 容器應用的5000端口映射到主機上指定的5000端口
- 我們可以通過瀏覽器 192.168.0.21:5000 來訪問容器的 5000 端口,即容器內部的web應用
-
可以指定容器綁定的網絡地址,比如綁定 127.0.0.1
- docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py
- PORTS:127.0.0.1:5001->5000/tcp 容器應用的5000端口映射到網絡IP地址127.0.0.1指定的5000端口
- 我們可以通過瀏覽器 127.0.0.1:5001 來訪問容器的 5000 端口,即容器內部的web應用
- docker run -d -p 127.0.0.1:5001:5000 training/webapp python app.py
-
上述方法,默認綁定都是tcp端口
- 如果要綁定udp端口,端口號後面加上/udp即可
- docker run -d -p 127.0.0.1:5000:5000/udp training/webapp python app.py
- PORTS:127.0.0.1:5000->5000/udp
-
查看容器映射網絡端口
- docker port container_name or container_id 可以查看容器端口的映射情況
5.2 Docker容器互聯
-
端口映射並不是唯一把 docker 連接到另一個容器的方法。
- docker 有一個連接系統允許將多個容器連接在一起,共享連接信息。
- docker 連接會創建一個父子關係,其中父容器可以看到子容器的信息。
-
容器命名
- 當我們創建一個容器的時候,docker 會自動對它進行命名。另外,我們也可以使用 --name 標識來命名容器,例如:
- runoob@runoob:~$ docker run -d -P --name runoob training/webapp python app.py
- 指定容器的名稱爲 runoob
-
新建網絡
- 下面先創建一個新的 Docker 網絡。
- docker network create -d bridge test-net
- 參數說明:
- -d:參數後面指定 Docker 網絡類型,有 bridge、overlay。
- 其中 overlay 網絡類型用於 Swarm mode,在本小節中你可以忽略它。
- test-net:網絡的名稱,後面容器連接該網絡時候使用該名稱
- -d: 在前面創建容器時候,用途是新建容器後,容器後臺運行,不進入容器
-
連接容器
-
該終端運行一個容器並連接到上面新建的 test-net 網絡:
- docker run -itd --name test1 --network test-net ubuntu /bin/bash
-
打開新的終端,再運行一個容器並加入到 test-net 網絡:
- docker run -itd --name test2 --network test-net ubuntu /bin/bash
-
安裝 ping 工具(網絡連通測試)
- 如果 test1、test2 容器內中無 ping 命令,則在容器內執行以下命令安裝 ping
- apt-get update 先更新以下源地址列表
- apt install iputils-ping 下載安裝 ping 工具
- 如果 test1、test2 容器內中無 ping 命令,則在容器內執行以下命令安裝 ping
-
具體步驟:
- 進入test1的容器終端:docker exec -it test1 /bin/bash
- 然後執行上面兩個命令:
- apt-get update
- apt install iputils-ping
-
安裝完成後,然後分別進行ping測試:
- test1容器:ping test2
- test2容器:ping test1
- 連接成功,相互就有數據傳輸
-
-
更新鏡像實例:
- 上面我們已經在一個容器裏面,更新了源地址列表,同時又安裝了ping工具
- 此時鏡像和創建容器時候的鏡像已經發生了改變,我們可以提交爲自己的鏡像
- 下次創建容器時候就可以用我們自己的鏡像,裏面的包就不用重新安裝了
- 上面已經更新了Ubuntu的源列表,並安裝了ping工具,先 exit 命令退出容器,我們提交容器副本:
- docker commit -m=“has update” -a=“felix” e218edb10161 felix/ubuntu:v2
- 各個參數說明:
- -m: 提交的描述信息
- -a: 指定鏡像作者,即用戶名
- e218edb10161:容器 ID
- felixzfb/ubuntu:v2: 指定要創建的目標鏡像名稱 (REPOSITORY倉庫名)和版本號(TAG)
- ubuntu不同的鏡像通過tag的v2進行區分
- 提交的鏡像就已經有了新的tag標籤
- 提交後本地鏡像庫就有了剛剛提交的鏡像,提交成功如下圖:
5.3 Docker Hub 個人倉庫管理
-
在 https://hub.docker.com 免費註冊一個 Docker 賬號
- 網速很慢,需要掛代理,註冊後選擇免費community版
- 本地登錄和退出用戶
- docker login
- docker logout
- 登錄需要輸入用戶名和密碼,登錄成功後,我們就可以從 docker hub 上拉取自己賬號下的全部鏡像
- 登陸用戶時候不用掛代理,因爲daemon.json已經設置了阿里雲加速地址,但是有時網速不好會登陸不上
- 推送鏡像
- 用戶登錄後,可以通過 docker push 命令將自己的鏡像推送到 Docker Hub。
- docker tag ubuntu:18.04 felixzfb/ubuntu:18.04 將本地的ubuntu:18.04鏡像直接使用添加tag標籤變成自己鏡像
REPOSITORY TAG IMAGE ID CREATED ... ubuntu 18.04 275d79972a86 6 days ago ... felixzfb/ubuntu 18.04 275d79972a86 6 days ago
- 上述添加標籤的鏡像ID相同,因爲直接用的本地鏡像添加標籤,未做任何改動,ID一模一樣
- 參考015圖片,本地鏡像進行更新提交後的鏡像,是一個全新的鏡像ID已經發生了變化
- docker push felixzfb/ubuntu:18.04 將添加標籤的鏡像推送到Docker Hub自己的賬戶中,即felixzfb中
- docker search felixzfb/ubuntu 搜索自己倉庫的鏡像
- 特別注意:
- commit 提交時候,軟件名稱斜線前面的用戶名要寫自己dockerhub的賬戶名,不然push到個人倉庫會找不到用戶名,會被denied
- tag 標籤時候,用戶名也是自己的賬戶名,後面是倉庫名稱和tag標籤
- tag 標籤命令可以用來修改鏡像的 REPOSITORY 名稱,也可以同時修改名稱和tag
- [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-OegTOV0H-1585754846179)(008_Docker容器/016_登陸個人倉庫_上傳本地鏡像到個人倉庫.png)]
- [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-gDGJ6YGZ-1585754846180)(008_Docker容器/017_登陸個人倉庫_上傳本地自己的鏡像到個人倉庫.png)]
- [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-vzloim3i-1585754846181)(008_Docker容器/018_登陸個人網站_查看已上傳的鏡像.png)]
- 上述圖片可以發現:
- docker push felix/ubuntu 失敗,因爲它去查找的是felix賬戶,不是自己的賬戶,沒有權限
- 然後將felix/ubuntu 鏡像直接使用 tag 命令修改,相當於修改 REPOSITORY 名稱得到的鏡像和原始鏡像的ID是一模一樣的
-
刪除ID相同的鏡像,直接使用ID刪除,系統不知道刪除那個,需要使用倉庫名和標籤名刪除
- [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-mZ54k03s-1585754846181)(008_Docker容器/019_刪除ID相同的鏡像使用倉庫名和標籤名.png)]
5.4 配置全部容器的DNS
-
我們可以在宿主機的 /etc/docker/daemon.json 文件中增加以下內容來設置全部容器的 DNS:
``` { "dns" : [ "114.114.114.114", "8.8.8.8" ] } ```
-
設置後,啓動容器的 DNS 會自動配置爲 114.114.114.114 和 8.8.8.8。
- 配置完,需要重啓 docker 才能生效:
- /etc/init.d/docker restart
- 查看容器的 DNS 是否生效可以使用以下命令:
- docker run -it --rm ubuntu cat etc/resolv.conf
- 它會輸出容器的 DNS 信息:
- nameserver 114.114.114.114
- nameserver 8.8.8.8
- 配置完,需要重啓 docker 才能生效:
-
手動指定單個容器的配置
- 如果只想在指定的容器設置 DNS,則可以使用以下命令:
- docker run -it --rm -h host_ubuntu --dns=114.114.114.114 --dns-search=test.com ubuntu
- 參數說明:
- -h HOSTNAME 或者 --hostname=HOSTNAME: 設定容器的主機名,它會被寫到容器內的 /etc/hostname 和 /etc/hosts。可以通過,cat /etc/hostname 查看文件內容
- –dns=IP_ADDRESS: 添加 DNS 服務器到容器的 /etc/resolv.conf 中,讓容器用這個服務器來解析所有不在 /etc/hosts 中的主機名。
- –dns-search=DOMAIN: 設定容器的搜索域,當設定搜索域爲 .example.com 時,在搜索一個名爲 host 的主機時,DNS 不僅搜索 host,還會搜索 host.example.com。
- 如果在容器啓動時沒有指定 --dns 和 --dns-search,Docker 會默認用宿主主機上的 /etc/resolv.conf 來配置容器的 DNS
6 Docker Compose
6.1 Compose 簡介
-
Compose 是用於定義和運行多容器 Docker 應用程序的工具。
-
通過 Compose,您可以使用 YML 文件來配置應用程序需要的所有服務。
-
然後,使用一個命令,就可以從 YML 文件配置中創建並啓動所有服務。
-
Compose 使用的三個步驟:
- 使用 Dockerfile 定義應用程序的環境。
- 使用 docker-compose.yml 定義構成應用程序的服務,這樣它們可以在隔離環境中一起運行。
- 最後,執行 docker-compose up 命令來啓動並運行整個應用程序
-
docker-compose安裝 第 2 章裏面的博文,安裝完成後輸入:
- docker-compose --version 顯示版本就是安裝成功
-
docker-compose使用需要配置 yml 文件,yml 文件配置說明參考以下文章
6.2 docker-compose 使用案例
-
配置文件儘量粘貼複製,以防出錯
-
由於我的Ubuntu和Win之間出現相互之間不能粘貼複製,但是共享文件夾可以訪問
-
折中辦法:共享文件夾中新建打開一個txt文件,WIN10下面複製粘貼,Ubuntu每次重新載入,相當於一個實時剪貼板
-
標準案例步驟:
-
- 準備
-
創建一個測試目錄:
- mkdir composetest
- cd composetest
- touch app.py 測試目錄中創建一個名爲 app.py 的文件
- 具體步驟如下圖,具體文件內部內容都是WIN10直接複製到txt剪貼板,然後粘貼進去
-示例中,redis 是應用程序網絡上的 redis 容器的主機名,該主機使用的端口爲 6379。
- 然後繼續在 composetest 目錄中創建另一個名爲 requirements.txt 的文件,內容參考截圖
-
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-rddImX10-1585754846183)(008_Docker容器/020_docker-compose使用準備.png)]
-
- 創建 Dockerfile 文件
- 在 composetest 目錄中,創建一個名爲的文件 Dockerfile
- 具體內容如下截圖
- Dockerfile 內容解釋:
-
FROM python:3.7-alpine: 從 Python 3.7 映像開始構建鏡像。
-
WORKDIR /code: 將工作目錄設置爲 /code。
-
ENV FLASK_APP app.py
-
ENV FLASK_RUN_HOST 0.0.0.0
-
設置 flask 命令使用的環境變量。
-
RUN apk add --no-cache gcc musl-dev linux-headers
-
安裝 gcc,以便諸如 MarkupSafe 和 SQLAlchemy 之類的 Python 包可以編譯加速。
-
COPY requirements.txt requirements.txt
-
RUN pip install -r requirements.txt
-
複製 requirements.txt 並安裝 Python 依賴項。
-
COPY . .: 將 . 項目中的當前目錄複製到 . 鏡像中的工作目錄。
-
CMD [“flask”, “run”]: 容器提供默認的執行命令爲:flask run。
-
- [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-7og7yq6r-1585754846190)(008_Docker容器/021_docker-compose使用_創建Dockerfile文件1.png)]
- [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-cyvpc8eX-1585754846190)(008_Docker容器/022_docker-compose使用_創建Dockerfile文件2.png)]
-
- 創建 docker-compose.yml
- 在測試目錄中創建一個名爲 docker-compose.yml 的文件
- 該 yml 文件定義了兩個服務:web 和 redis。
- web:該 web 服務使用從 Dockerfile 當前目錄中構建的鏡像。然後,它將容器和主機綁定到暴露的端口 5000。此示例服務使用 Flask Web 服務器的默認端口 5000 。
- redis:該 redis 服務使用 Docker Hub 的公共 Redis 映像。
- [外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-haOvuukp-1585754846192)(008_Docker容器/023_docker-compose使用_創建docker-compose.yml配置文件.png)]
-
- 使用 Compose 命令構建和運行您的應用
-
在測試目錄中,執行以下命令來啓動應用程序:
- docker-compose up
-
如果你想在後臺執行該服務可以加上 -d 參數:
- docker-compose up -d
-
ctrl + d 退出容器
-
docker exec -it xxxxxxxxxx /bin/sh 進入容器終端
-
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-1Q8D7PYF-1585754846193)(008_Docker容器/024_docker-compose使用_啓動docker-compose服務1.png)]
-
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片保存下來直接上傳(img-sOZTh6Ql-1585754846193)(008_Docker容器/025_docker-compose使用_啓動docker-compose服務2.png)]
-
該實例及 yml 配置詳細配置參考:菜鳥教程-Docker Compose
-
補充1:
- docker-compose 啓動多容器 Docker 應用程序 實際最核心就是 yml 文件
- 我們只需要新建一個文件夾,文件夾下面創建 yml 配置文件
- 當前文件夾執行 docker-compose up 就可以啓動一個 docker-compose 容器
- 上面案例是 1 2 步並非一定操作,可以參考 007_Crawlab爬蟲管理平臺中 4.1.3 節啓動crawlab管理平臺容器
6.3 docker-compose 常用命令
- 由於docker-compose 啓動的是多容器 Docker 應用程序
- 啓動停止都是依賴的 docker-compose.yml 配置文件
- 並且都是在項目文件夾啓動的,所有服務都是相互依賴的
- 使用 docker-compose ps 查看服務運行狀態,是沒有ID的
- 命令和docker一樣,但是執行命令不需要指定名稱和ID
- 所有命令都是在項目文件夾下執行:
- docker-compose up 啓動多容器應用,進入
- docker-compose up -d 啓動多容器應用,後臺運行
- ctrl + d 退出應用終端,回到用戶終端
- docker-compose ps 查看後臺容器信息或者已停止容器信息
- docker-compose ps -a 查看已停止容器信息
- docker-compose stop 停止容器
- docker-compose start 重啓已停止的容器
- docker-compose rm 刪除已停止的容器
- docker-compose down 停止並刪除所有的容器