最全 Docker 介紹與教程,一文全掌握

最全 Docker 介紹與教程,一文全掌握

2013年發佈至今, Docker 一直廣受矚目,被認為可能會改變軟件行業。

但是,許多人並不清楚 Docker 到底是什麼,要解決什麼問題,好處又在哪裡?本文就來詳細解釋,幫助大家理解它,還帶有簡單易懂的實例,教你如何將它用於日常開發。

最全 Docker 介紹與教程,一文全掌握

一、環境配置的難題

最全 Docker 介紹與教程,一文全掌握

軟件開發最大的麻煩事之一,就是環境配置。用戶計算機的環境都不相同,你怎麼知道自家的軟件,能在那些機器跑起來?

用戶必須保證兩件事:操作系統的設置,各種庫和組件的安裝。只有它們都正確,軟件才能運行。舉例來說,安裝一個 Python 應用,計算機必須有 Python 引擎,還必須有各種依賴,可能還要配置環境變量。

如果某些老舊的模塊與當前環境不兼容,那就麻煩了。開發者常常會說:"它在我的機器可以跑了"(It works on my machine),言下之意就是,其他機器很可能跑不了。

環境配置如此麻煩,換一臺機器,就要重來一次,曠日費時。很多人想到,能不能從根本上解決問題,軟件可以帶環境安裝?也就是說,安裝的時候,把原始環境一模一樣地複製過來。

最全 Docker 介紹與教程,一文全掌握

二、虛擬機

最全 Docker 介紹與教程,一文全掌握

虛擬機(virtual machine)就是帶環境安裝的一種解決方案。它可以在一種操作系統裡面運行另一種操作系統,比如在 Windows 系統裡面運行 Linux 系統。應用程序對此毫無感知,因為虛擬機看上去跟真實系統一模一樣,而對於底層系統來說,虛擬機就是一個普通文件,不需要了就刪掉,對其他部分毫無影響。

雖然用戶可以通過虛擬機還原軟件的原始環境。但是,這個方案有幾個缺點。

(1)資源佔用多

虛擬機會獨佔一部分內存和硬盤空間。它運行的時候,其他程序就不能使用這些資源了。哪怕虛擬機裡面的應用程序,真正使用的內存只有 1MB,虛擬機依然需要幾百 MB 的內存才能運行。

(2)冗餘步驟多

虛擬機是完整的操作系統,一些系統級別的操作步驟,往往無法跳過,比如用戶登錄。

(3)啟動慢

啟動操作系統需要多久,啟動虛擬機就需要多久。可能要等幾分鐘,應用程序才能真正運行。

最全 Docker 介紹與教程,一文全掌握

三、Linux 容器

最全 Docker 介紹與教程,一文全掌握

由於虛擬機存在這些缺點,Linux 發展出了另一種虛擬化技術:Linux 容器(Linux Containers,縮寫為 LXC)。

Linux 容器不是模擬一個完整的操作系統,而是對進程進行隔離。或者說,在正常進程的外面套了一個保護層。對於容器裡面的進程來說,它接觸到的各種資源都是虛擬的,從而實現與底層系統的隔離。

由於容器是進程級別的,相比虛擬機有很多優勢。

(1)啟動快

容器裡面的應用,直接就是底層系統的一個進程,而不是虛擬機內部的進程。所以,啟動容器相當於啟動本機的一個進程,而不是啟動一個操作系統,速度就快很多。

(2)資源佔用少

容器只佔用需要的資源,不佔用那些沒有用到的資源;虛擬機由於是完整的操作系統,不可避免要佔用所有資源。另外,多個容器可以共享資源,虛擬機都是獨享資源。

(3)體積小

容器只要包含用到的組件即可,而虛擬機是整個操作系統的打包,所以容器文件比虛擬機文件要小很多。

總之,容器有點像輕量級的虛擬機,能夠提供虛擬化的環境,但是成本開銷小得多。

最全 Docker 介紹與教程,一文全掌握

四、Docker 是什麼?

最全 Docker 介紹與教程,一文全掌握

Docker 屬於 Linux 容器的一種封裝,提供簡單易用的容器使用接口。它是目前最流行的 Linux 容器解決方案。

Docker 將應用程序與該程序的依賴,打包在一個文件裡面。運行這個文件,就會生成一個虛擬容器。程序在這個虛擬容器裡運行,就好像在真實的物理機上運行一樣。有了 Docker,就不用擔心環境問題。

總體來說,Docker 的接口相當簡單,用戶可以方便地創建和使用容器,把自己的應用放入容器。容器還可以進行版本管理、複製、分享、修改,就像管理普通的代碼一樣。

最全 Docker 介紹與教程,一文全掌握

五、Docker 的用途

最全 Docker 介紹與教程,一文全掌握

Docker 的主要用途,目前有三大類。

(1)提供一次性的環境。比如,本地測試他人的軟件、持續集成的時候提供單元測試和構建的環境。

(2)提供彈性的雲服務。因為 Docker 容器可以隨開隨關,很適合動態擴容和縮容。

(3)組建微服務架構。通過多個容器,一臺機器可以跑多個服務,因此在本機就可以模擬出微服務架構。

最全 Docker 介紹與教程,一文全掌握

六、Docker 的安裝

最全 Docker 介紹與教程,一文全掌握

Docker 是一個開源的商業產品,有兩個版本:社區版(Community Edition,縮寫為 CE)和企業版(Enterprise Edition,縮寫為 EE)。企業版包含了一些收費服務,個人開發者一般用不到。下面的介紹都針對社區版。

Docker CE 的安裝請參考官方文檔。

安裝完成後,運行下面的命令,驗證是否安裝成功。

$ docker version$ docker info

Docker 需要用戶具有 sudo 權限,為了避免每次命令都輸入sudo,可以把用戶加入 Docker 用戶組(官方文檔)。

$ sudo usermod -aG docker $USER

Docker 是服務器----客戶端架構。命令行運行docker命令的時候,需要本機有 Docker 服務。如果這項服務沒有啟動,可以用下面的命令啟動(官方文檔)。

$ sudo service docker start$ sudo systemctl start docker
最全 Docker 介紹與教程,一文全掌握

七、image 文件

最全 Docker 介紹與教程,一文全掌握

Docker 把應用程序及其依賴,打包在 image 文件裡面。只有通過這個文件,才能生成 Docker 容器。image 文件可以看作是容器的模板。Docker 根據 image 文件生成容器的實例。同一個 image 文件,可以生成多個同時運行的容器實例。

image 是二進制文件。實際開發中,一個 image 文件往往通過繼承另一個 image 文件,加上一些個性化設置而生成。舉例來說,你可以在 Ubuntu 的 image 基礎上,往裡面加入 Apache 服務器,形成你的 image。

$ docker image ls$ docker image rm [imageName]

image 文件是通用的,一臺機器的 image 文件拷貝到另一臺機器,照樣可以使用。一般來說,為了節省時間,我們應該儘量使用別人製作好的 image 文件,而不是自己製作。即使要定製,也應該基於別人的 image 文件進行加工,而不是從零開始製作。

為了方便共享,image 文件製作完成後,可以上傳到網上的倉庫。Docker 的官方倉庫 Docker Hub 是最重要、最常用的 image 倉庫。此外,出售自己製作的 image 文件也是可以的。

最全 Docker 介紹與教程,一文全掌握

八、實例:hello world

最全 Docker 介紹與教程,一文全掌握

下面,我們通過最簡單的 image 文件"hello world",感受一下 Docker。

需要說明的是,國內連接 Docker 的官方倉庫很慢,還會斷線,需要將默認倉庫改成國內的鏡像網站,具體的修改方法在下一篇文章的第一節。有需要的朋友,可以先看一下。

首先,運行下面的命令,將 image 文件從倉庫抓取到本地。

$ docker image pull library/hello-world

上面代碼中,docker image pull是抓取 image 文件的命令。library/hello-world是 image 文件在倉庫裡面的位置,其中library是 image 文件所在的組,hello-world是 image 文件的名字。

由於 Docker 官方提供的 image 文件,都放在library組裡面,所以它的是默認組,可以省略。因此,上面的命令可以寫成下面這樣。

$ docker image pull hello-world

抓取成功以後,就可以在本機看到這個 image 文件了。

$ docker image ls

現在,運行這個 image 文件。

docker container run命令會從 image 文件,生成一個正在運行的容器實例。

注意,docker container run命令具有自動抓取 image 文件的功能。如果發現本地沒有指定的 image 文件,就會從倉庫自動抓取。因此,前面的docker image pull命令並不是必需的步驟。

如果運行成功,你會在屏幕上讀到下面的輸出。

$ docker container run hello-worldHello from Docker!This message shows that your installation appears to be working correctly...

輸出這段提示以後,hello world就會停止運行,容器自動終止。

有些容器不會自動終止,因為提供的是服務。比如,安裝運行 Ubuntu 的 image,就可以在命令行體驗 Ubuntu 系統。

$ docker container run -it ubuntu bash

對於那些不會自動終止的容器,必須使用docker container kill 命令手動終止。

$ docker container kill [containID]
最全 Docker 介紹與教程,一文全掌握

九、容器文件

最全 Docker 介紹與教程,一文全掌握

image 文件生成的容器實例,本身也是一個文件,稱為容器文件。也就是說,一旦容器生成,就會同時存在兩個文件: image 文件和容器文件。而且關閉容器並不會刪除容器文件,只是容器停止運行而已。

$ docker container ls$ docker container ls --all

上面命令的輸出結果之中,包括容器的 ID。很多地方都需要提供這個 ID,比如上一節終止容器運行的docker container kill命令。

終止運行的容器文件,依然會佔據硬盤空間,可以使用docker container rm命令刪除。

$ docker container rm [containerID]

運行上面的命令之後,再使用docker container ls --all命令,就會發現被刪除的容器文件已經消失了。

最全 Docker 介紹與教程,一文全掌握

十、Dockerfile 文件

最全 Docker 介紹與教程,一文全掌握

學會使用 image 文件以後,接下來的問題就是,如何可以生成 image 文件?如果你要推廣自己的軟件,勢必要自己製作 image 文件。

這就需要用到 Dockerfile 文件。它是一個文本文件,用來配置 image。Docker 根據 該文件生成二進制的 image 文件。

下面通過一個實例,演示如何編寫 Dockerfile 文件。

十一、實例:製作自己的 Docker 容器

下面我以 koa-demos 項目為例,介紹怎麼寫 Dockerfile 文件,實現讓用戶在 Docker 容器裡面運行 Koa 框架。

作為準備工作,請先下載源碼。

$ git clone https://github.com/ruanyf/koa-demos.git$ cd koa-demos

11.1 編寫 Dockerfile 文件

首先,在項目的根目錄下,新建一個文本文件.dockerignore,寫入下面的內容。

.gitnode_modulesnpm-debug.log

上面代碼表示,這三個路徑要排除,不要打包進入 image 文件。如果你沒有路徑要排除,這個文件可以不新建。

然後,在項目的根目錄下,新建一個文本文件 Dockerfile,寫入下面的內容。

FROM node:8.4COPY . /appWORKDIR /appRUN npm install --registry=https://registry.npm.taobao.orgEXPOSE 3000

上面代碼一共五行,含義如下。

  • FROM node:8.4:該 image 文件繼承官方的 node image,冒號表示標籤,這裡標籤是8.4,即8.4版本的 node。
  • COPY . /app:將當前目錄下的所有文件(除了.dockerignore排除的路徑),都拷貝進入 image 文件的/app目錄。
  • WORKDIR /app:指定接下來的工作路徑為/app。
  • RUN npm install:在/app目錄下,運行npm install命令安裝依賴。注意,安裝後所有的依賴,都將打包進入 image 文件。
  • EXPOSE 3000:將容器 3000 端口暴露出來, 允許外部連接這個端口。

11.2 創建 image 文件

有了 Dockerfile 文件以後,就可以使用docker image build命令創建 image 文件了。

$ docker image build -t koa-demo .$ docker image build -t koa-demo:0.0.1 .

上面代碼中,-t參數用來指定 image 文件的名字,後面還可以用冒號指定標籤。如果不指定,默認的標籤就是latest。最後的那個點表示 Dockerfile 文件所在的路徑,上例是當前路徑,所以是一個點。

如果運行成功,就可以看到新生成的 image 文件koa-demo了。

$ docker image ls

11.3 生成容器

docker container run命令會從 image 文件生成容器。

$ docker container run -p 8000:3000 -it koa-demo /bin/bash$ docker container run -p 8000:3000 -it koa-demo:0.0.1 /bin/bash

上面命令的各個參數含義如下:

  • -p參數:容器的 3000 端口映射到本機的 8000 端口。
  • -it參數:容器的 Shell 映射到當前的 Shell,然後你在本機窗口輸入的命令,就會傳入容器。
  • koa-demo:0.0.1:image 文件的名字(如果有標籤,還需要提供標籤,默認是 latest 標籤)。
  • /bin/bash:容器啟動以後,內部第一個執行的命令。這裡是啟動 Bash,保證用戶可以使用 Shell。

如果一切正常,運行上面的命令以後,就會返回一個命令行提示符。

root@66d80f4aaf1e:/app

這表示你已經在容器裡面了,返回的提示符就是容器內部的 Shell 提示符。執行下面的命令。

root@66d80f4aaf1e:/app

這時,Koa 框架已經運行起來了。打開本機的瀏覽器,訪問 http://127.0.0.1:8000,網頁顯示"Not Found",這是因為這個 demo 沒有寫路由。

這個例子中,Node 進程運行在 Docker 容器的虛擬環境裡面,進程接觸到的文件系統和網絡接口都是虛擬的,與本機的文件系統和網絡接口是隔離的,因此需要定義容器與物理機的端口映射(map)。

現在,在容器的命令行,按下 Ctrl + c 停止 Node 進程,然後按下 Ctrl + d (或者輸入 exit)退出容器。此外,也可以用docker container kill終止容器運行。

$ docker container ls$ docker container kill [containerID]

容器停止運行之後,並不會消失,用下面的命令刪除容器文件。

$ docker container ls --all$ docker container rm [containerID]

也可以使用docker container run命令的--rm參數,在容器終止運行後自動刪除容器文件。

$ docker container run --rm -p 8000:3000 -it koa-demo /bin/bash

10.4 CMD 命令

上一節的例子裡面,容器啟動以後,需要手動輸入命令node demos/01.js。我們可以把這個命令寫在 Dockerfile 裡面,這樣容器啟動以後,這個命令就已經執行了,不用再手動輸入了。

FROM node:8.4COPY . /appWORKDIR /appRUN npm install --registry=https://registry.npm.taobao.orgEXPOSE 3000CMD node demos/01.js

上面的 Dockerfile 裡面,多了最後一行CMD node demos/01.js,它表示容器啟動後自動執行node demos/01.js。

你可能會問,RUN命令與CMD命令的區別在哪裡?簡單說,RUN命令在 image 文件的構建階段執行,執行結果都會打包進入 image 文件;CMD命令則是在容器啟動後執行。另外,一個 Dockerfile 可以包含多個RUN命令,但是隻能有一個CMD命令。

注意,指定了CMD命令以後,docker container run命令就不能附加命令了(比如前面的/bin/bash),否則它會覆蓋CMD命令。現在,啟動容器可以使用下面的命令。

$ docker container run --rm -p 8000:3000 -it koa-demo:0.0.1

10.5 發佈 image 文件

容器運行成功後,就確認了 image 文件的有效性。這時,我們就可以考慮把 image 文件分享到網上,讓其他人使用。

首先,去 hub.docker.com 或 cloud.docker.com 註冊一個賬戶。然後,用下面的命令登錄。

接著,為本地的 image 標註用戶名和版本。

$ docker image tag [imageName] [username]/[repository]:[tag]$ docker image tag koa-demos:0.0.1 ruanyf/koa-demos:0.0.1

也可以不標註用戶名,重新構建一下 image 文件。

$ docker image build -t [username]/[repository]:[tag] .

最後,發佈 image 文件。

$ docker image push [username]/[repository]:[tag]

發佈成功以後,登錄 hub.docker.com,就可以看到已經發布的 image 文件。

十二、其他有用的命令

docker 的主要用法就是上面這些,此外還有幾個命令,也非常有用。

(1)docker container start

前面的docker container run命令是新建容器,每運行一次,就會新建一個容器。同樣的命令運行兩次,就會生成兩個一模一樣的容器文件。如果希望重複使用容器,就要使用docker container start命令,它用來啟動已經生成、已經停止運行的容器文件。

$ docker container start [containerID]

(2)docker container stop

前面的docker container kill命令終止容器運行,相當於向容器裡面的主進程發出 SIGKILL 信號。而docker container stop命令也是用來終止容器運行,相當於向容器裡面的主進程發出 SIGTERM 信號,然後過一段時間再發出 SIGKILL 信號。

$ bash container stop [containerID]

這兩個信號的差別是,應用程序收到 SIGTERM 信號以後,可以自行進行收尾清理工作,但也可以不理會這個信號。如果收到 SIGKILL 信號,就會強行立即終止,那些正在進行中的操作會全部丟失。

(3)docker container logs

docker container logs命令用來查看 docker 容器的輸出,即容器裡面 Shell 的標準輸出。如果docker run命令運行容器的時候,沒有使用-it參數,就要用這個命令查看輸出。

$ docker container logs [containerID]

(4)docker container exec

docker container exec命令用於進入一個正在運行的 docker 容器。如果docker run命令運行容器的時候,沒有使用-it參數,就要用這個命令進入容器。一旦進入了容器,就可以在容器的 Shell 執行命令了。

$ docker container exec -it [containerID] /bin/bash

(5)docker container cp

docker container cp命令用於從正在運行的 Docker 容器裡面,將文件拷貝到本機。下面是拷貝到當前目錄的寫法。

$ docker container cp [containID]:[/path/to/file] .

非常感謝你一直讀到了這裡,這個系列還有下一篇,介紹如何使用 Docker 搭建真正的網站,歡迎繼續閱讀。


分享到:


相關文章: