一杯茶的時間,上手 Docker

努力工做,而後進入夢鄉,「工做」和「作夢」之間好像沒有任何關聯;編寫代碼,而後部署應用,這二者彷佛也是天各一邊。然而果然如此嗎?這篇文章將經過《盜夢空間》的方式打開 Docker,讓你實現從「作夢」到「築夢」的實質性轉變。在原先的「作夢」階段(手動配置和部署),一切都充滿了隨機性和不可控性,你有時甚至都沒法回憶起具體作的每一步;而在「築夢」階段(藉助 Docker),你將經過自動化、高度可重複且可追蹤的方式輕鬆實現任何配置和部署任務。但願讀完這篇文章的你,也能成爲一個優秀的「築夢師」!html

準備工做

寫在前面的話

不少朋友跟咱們反饋說,「一杯茶」純粹就是忽悠人,寫那麼長,怎麼可能在一杯茶的時間內看完?實際上,「飲茶」的方式因人而異,不一樣的讀者自有不一樣的節奏。你徹底能夠選擇一目十行、甚至只瀏覽一下插圖,幾分鐘的時間便能看完;也能夠選擇跟着咱們一步一步動手實踐,甚至在有些地方停下來思考一番,雖然須要花更多的時間,可是咱們相信這份投入的時間必定是值得的。前端

其次,咱們想確認你是不是這篇文章的受衆:node

  1. 若是你已是天天操縱數以千計容器的 DevOps 大佬,那麼很抱歉打擾了,這篇文章對你來講可能過於簡單;
  2. 若是你已經比較熟悉 Docker 了,想要更多的實戰操做經驗,這篇文章可以較好地幫助你複習和鞏固關鍵的知識點;
  3. 若是你只據說過 Docker,可是基本上不會用,那麼這篇文章就是爲你準備的!只不過友情提醒:Docker 上手略有難度,想要真正掌握須要投入足夠的時間,認真讀完這篇文章必定能讓你有至關大的進步

最後,每一個小節的結構都是實戰演練 + 回憶與昇華。回憶與昇華部分是筆者花了很多時間對優質資源進行蒐集和整合而成,並結合了自身使用容器的經驗,相信可以進一步加深你的理解,若是你趕時間的話,也能夠略過哦。nginx

前提條件

在正式閱讀這篇文章以前,咱們但願你已經具有如下條件:git

  • 最基本的命令行操做經驗
  • 對計算機網絡有必定的瞭解,特別是應用層中的端口這一律念
  • 最好經歷過配環境、部署項目的痛苦掙扎😭

咱們將實現什麼

如今假定你手頭已經有了一個 React 編寫的「夢想清單」項目,以下面這個動圖所示:程序員

咱們將在這篇文章中教你一步步用 Docker 將這個應用容器化,用 Nginx 服務器提供構建好的靜態頁面。github

你將學會

這篇文章不會涉及 ...

固然咯,這篇文章做爲一篇入門性質的教程,如下進階內容不會涉及:docker

  • Docker 網絡機制
  • 數據卷和 Bind Mount 實現數據分享
  • Docker Compose
  • 多階段構建(Multi-stage Build)
  • Docker Machine 工具
  • 容器編排技術,例如 Kubernetes 以及 Docker Swarm

以上進階知識咱們會立刻推出相關教程,敬請期待。數據庫

安裝 Docker

咱們推薦各個平臺用如下方式安裝 Docker(通過咱們反覆測試哦)。npm

Windows

菜鳥教程中詳細介紹了 Win7/8 以及 Win10 的不一樣推薦安裝方法。注意 Win10 建議開啓 Hyper-V 虛擬化技術。

macOS

可經過點擊官方下載連接下載並安裝 DMG 文件(若是速度慢的話能夠把連接複製進迅雷哦)。安裝完畢以後,點擊 Docker 應用圖標便可打開。

Linux

對於各大 Linux 發行版(Ubuntu、CentOS 等等),咱們推薦用官方腳本進行安裝,方便快捷:

curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
複製代碼

而後推薦將 docker 的權限移交給非 root 用戶,這樣使用 docker 就不須要每次都 sudo 了:

sudo usermod -aG docker $USER
複製代碼

註銷用戶或者重啓以後就會生效。而後經過 systemd 服務配置 Docker 開機啓動:

sudo systemctl enable docker
複製代碼

配置鏡像倉庫

默認的鏡像倉庫 Docker Hub 在國外,國內拉取速度比較感人。建議參考這篇文章進行配置。

鏡像與容器:築夢師的圖紙和夢境

鏡像(Image)和容器(Container)是 Docker 中最爲基礎也是最爲關鍵的兩個概念,前者就是築夢師的圖紙,根據這張圖紙的內容,就可以生成徹底可預測的夢境(也就是後者)。

提示

若是你以爲這個比喻難以理解,那麼能夠經過面向對象編程中「類」(class)和「實例」(instance)這兩個概念進行類比,「類」就至關於「鏡像」,「實例」就至關於「容器」。

小試牛刀:夢開始的地方

在略微接觸了鏡像與容器這兩個基礎概念以後,咱們打算暫停理論的講解,而先來一波小實驗讓你快速感覺一下。

實驗一:Hello World!

按照歷史慣例,咱們運行一下來自 Docker 的 Hello World,命令以下:

docker run hello-world
複製代碼

輸出以下:

Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
1b930d010525: Pull complete
Digest: sha256:fb158b7ad66f4d58aa66c4455858230cd2eab4cdf29b13e5c3628a6bfc2e9f05
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
...
複製代碼

不就打印了一個字符串而後退出嗎,有這麼神奇?其實 Docker 爲咱們默默作了如下事情:

  1. 檢查本地是否有指定的 hello-world:latest 鏡像(latest 是鏡像標籤,後面會細講),若是沒有,執行第 2 步,不然直接執行第 3 步
  2. 本地沒有指定鏡像(Unable to find xxx locally),從 Docker Hub 下載到本地
  3. 根據本地的 hello-world:latest 鏡像建立一個新的容器並運行其中的程序
  4. 運行完畢後,容器退出,控制權返回給用戶

實驗二:運行一個 Nginx 服務器

感受太簡單?咱們來嘗試一個高級一點的:運行一個 Nginx 服務器。運行如下命令

docker run -p 8080:80 nginx
複製代碼

運行以後,你會發現一直卡住,也沒有任何輸出,但放心你的電腦並無死機。讓咱們打開瀏覽器訪問 localhost:8080

這時候熟悉 Nginx 的朋友可能就坐不住了:就一個簡簡單單的 docker run 命令,就搞定了 Nginx 服務器的安裝和部署??沒錯,你能夠繼續訪問一些不存在的路由,好比 localhost:8080/what,一樣會提示 404。這時候咱們再看 Docker 容器的輸出,就有內容(服務器日誌)了:

總結一下剛纔 Docker 作的事情:

  1. 檢查本地是否有指定的 nginx:latest 鏡像(關於 latest 標籤,後面會細講),若是沒有,執行第 2 步,不然直接執行第 3 步
  2. 本地沒有指定鏡像(Unable to find xxx locally),從 Docker Hub 下載到本地
  3. 根據本地的 nginx:latest 鏡像建立一個新的容器,並經過 -p--publish)參數創建本機的 8080 端口與容器的 80 端口之間的映射,而後運行其中的程序
  4. Nginx 服務器程序保持運行,容器也不會退出

提示

端口映射規則的格式爲 <本機端口>:<容器端口>。Nginx 容器默認開放了 80 端口,咱們經過設置 8080:80 的端口映射規則,就能夠在本機(容器以外)經過訪問 localhost:8080 訪問,甚至能夠在同一局域網內經過內網 IP 訪問,這篇文章的最後會演示哦。

實驗三:後臺運行 Nginx

看上去很酷,不過像 Nginx 服務器這樣的進程咱們更但願把它拋到後臺一直運行。按 Ctrl + C 退出當前的容器,而後再次運行如下命令:

docker run -p 8080:80 --name my-nginx -d nginx
複製代碼

注意到與以前不一樣的是,咱們:

  • 加了一個參數 --name,用於指定容器名稱爲 my-nginx
  • 加了一個選項 -d--detach),表示「後臺運行」

警告

容器的名稱必須是惟一的,若是已經存在同一名稱的容器(即便已經再也不運行)就會建立失敗。若是遇到這種狀況,能夠刪除以前不須要的容器(後面會講解怎麼刪除)。

Docker 會輸出一串長長的 64 位容器 ID,而後把終端的控制權返回給了咱們。咱們試着訪問 localhost:8080,還能看到那一串熟悉的 Welcome to nginx!,說明服務器真的在後臺運行起來了。

那咱們怎麼管理這個服務器呢?就像熟悉的 UNIX ps 命令同樣,docker ps 命令可讓咱們查看當前容器的狀態:

docker ps
複製代碼

輸出結果是這樣的:

提示

因爲 docker ps 的輸出比較寬,若是你以爲結果不直觀的話能夠把終端(命令行)拉長,以下圖所示:

從這張表中,就能夠清晰地看到了咱們在後臺運行的 Nginx 服務器容器的一些信息:

  • 容器 ID(Container ID)爲 0bddac16b8d8(你機器上的可能不同)
  • 所用鏡像(Image)爲 nginx
  • 運行命令/程序(Command)爲 nginx -g 'daemon of...,這個是 Nginx 鏡像自帶的運行命令,暫時不用關心
  • 建立時間(Created)爲 45 seconds ago(45 秒鐘以前)
  • 當前狀態(Status)爲 Up 44 seconds(已運行 44 秒鐘)
  • 端口(Ports)爲 0.0.0.0:8080->80/tcp,意思是訪問本機的 0.0.0.0:8080 的全部請求會被轉發到該容器的 TCP 80 端口
  • 名稱(Names)爲剛纔指定的 my-nginx

若是咱們要讓容器停下來,經過 docker stop 命令指定容器名稱或 ID 進行操做便可,命令以下:

docker stop my-nginx
# docker stop 0bddac16b8d8
複製代碼

注意

若是指定容器 ID 的話,記得要換成本身機器上真實的 ID 哦。此外,在沒有衝突的狀況下,ID 能夠只寫前幾位字符,例如寫 0bd 也是能夠的。

實驗四:交互式運行

在過了一把 Nginx 服務器的癮以後,咱們再來體驗一下 Docker 容器的另外一種打開方式:交互式運行。運行如下命令,讓咱們進入到一個 Ubuntu 鏡像中:

docker run -it --name dreamland ubuntu
複製代碼

能夠看到咱們加了 -it 選項,等因而同時指定 -i--interactive,交互式模式)和 -t--tty,分配一個模擬終端) 兩個選項。以上命令的輸出以下:

Unable to find image 'ubuntu:latest' locally
latest: Pulling from library/ubuntu
2746a4a261c9: Pull complete
4c1d20cdee96: Pull complete
0d3160e1d0de: Pull complete
c8e37668deea: Pull complete
Digest: sha256:9207fc49baba2e62841d610598cb2d3107ada610acd4f47252faf73ed4026480
Status: Downloaded newer image for ubuntu:latest
root@94279dbf5d93:/#
複製代碼

等下,咱們怎麼被拋在了一個新的命令行裏面?沒錯,你如今已經在這個 Ubuntu 鏡像構築的「夢境」之中,你能夠隨意地「遊走」,運行一些命令:

root@94279dbf5d93:/# whoami
root
root@94279dbf5d93:/# ls
bin   dev  home  lib64  mnt  proc  run   srv  tmp  var
boot  etc  lib   media  opt  root  sbin  sys  usr
複製代碼

例如咱們在上面運行了 whoamils 命令,你基本上能夠肯定如今已經在「夢境」(容器)之中了。這時候打開一個新的終端(命令行),運行 docker ps 命令,就能夠看到正在運行中的 Ubuntu 鏡像:

回到以前的容器中,按 Ctrl + D (或者輸入 exit 命令)便可退出。你能夠在以前查看 docker ps 的終端再次檢查容器是否已經被關閉了。

銷燬容器:聽夢碎的聲音

築夢師不免會有失敗的做品,而咱們剛纔建立的 Docker 容器也只是用於初步探索,後續不會再用到。因爲 Docker 容器是直接存儲在咱們本地硬盤上的,及時清理容器也可以讓咱們的硬盤壓力小一些。咱們能夠經過如下命令查看全部容器(包括已經中止的):

docker ps -a
複製代碼

-a--all)用於顯示全部容器,若是不加的話只會顯示運行中的容器。能夠看到輸出以下(這裏我把終端拉寬了,方便你看):

提示

你也許觀察到,以前的實驗一和實驗二中咱們沒有指定容器名稱,Docker 爲咱們取了頗爲有趣的默認容器名稱(好比 hardcore_nash),格式是一個隨機的形容詞加上一位著名科學家/程序員的姓氏(運氣好的話,你可能會看到 Linux 之父 torvalds 哦)。

相似 Shell 中的 rm 命令,咱們能夠經過 docker rm 命令銷燬容器,例如刪除咱們以前建立的 dreamland 容器:

docker rm dreamland
# 或者指定容器 ID,記得替換成本身機器上的
# docker rm 94279dbf5d93
複製代碼

但若是咱們想要銷燬全部容器怎麼辦?一次次輸入 docker rm 刪除顯然不方便,能夠經過如下命令輕鬆刪除全部容器

docker rm $(docker ps -aq)
複製代碼

docker ps -aq 會輸出全部容器的 ID,而後做爲參數傳給 docker rm 命令,就能夠根據 ID 刪除全部容器啦。

危險!

執行以前必定要仔細檢查是否還有有價值的容器(特別是業務數據),由於容器一旦刪除沒法再找回(這裏不討論硬盤恢復這種黑科技)!

回憶與昇華

關於端口映射

可能有些同窗仍是沒有徹底理解「端口映射」的概念,以 8080:80 這一條映射規則爲例,咱們能夠用「傳送門」的比喻來理解(下面的圖是《傳送門2》遊戲的封面):

仍是把容器比做「夢境」,把本機環境比做「現實」,經過創建端口映射,訪問本機的 8080 端口的請求就會被「傳送」到容器的 80 端口,是否是很神奇呢。

容器生命週期:夢境地圖

跟着作完上面四個小實驗以後,你或許已經對 Docker 容器有了很是直觀的感覺和理解了。是時候祭出這張十(sang)分(xin)經(bing)典(kuang)的 Docker 容器生命週期圖了(來源:docker-saigon.github.io/post/Docker…

這張圖乍一看頗具視覺衝擊力,甚至會讓你感受不知所措。沒事,咱們大體地解讀這張圖裏面的四類元素:

  1. 容器狀態(帶顏色的圓圈):包括已建立(Created)、運行中(Running)、已暫停(Paused)、已中止(Stopped)以及被刪除(Deleted)
  2. Docker 命令(箭頭上以 docker 開頭的文字):包括 docker rundocker createdocker stop 等等
  3. 事件(矩形框):包括 createstartdiestop 還有 OOM(內存耗盡)等等
  4. 還有一個條件判斷,根據重啓策略(Restart Policy)判斷是否須要從新啓動容器

OK,這張圖仍是很難一會兒理解,不過還記得剛纔咱們作的四個小實驗嗎?咱們實際上走了一共兩條路徑(也是平常使用中走的最多的路),接下來將一一進行分析。

第一條路徑(天然結束)

如上圖所示:

  • 咱們先經過 docker run 命令,直接建立(create)並啓動(start)一個容器,進入到運行狀態(Running)
  • 而後程序運行結束(例如輸出 Hello World 以後,或者經過 Ctrl + C 使得程序終止),容器死亡(die)
  • 因爲咱們沒有設置重啓策略,因此直接進入到中止狀態(Stopped)
  • 最後經過 docker rm 命令銷燬容器,進入到被刪除狀態(Deleted)

第二條路徑(強制結束)

  • 咱們仍是經過 docker run 命令,直接建立(create)並啓動(start)一個容器,進入到運行狀態(Running)
  • 而後經過 docker stop 命令殺死容器中的程序(die)並中止(stop)容器,最終進入到中止狀態(Stopped)
  • 最後經過 docker rm 命令銷燬容器,進入到被刪除狀態(Deleted)

提示

有些眼尖的讀者可能發現 docker killdocker stop 的功能很是類似,它們以前存在細微的區別: kill 命令向容器內運行的程序直接發出 SIGKILL 信號(或其餘指定信號),而 stop 則是先發出 SIGTERM 再發出 SIGKILL 信號,屬於優雅關閉(Graceful Shutdown)。

一條捷徑:刪除運行中的容器

生命週期圖其實有一條捷徑沒有畫出來:直接從運行中(或暫停中)到被刪除,經過給 docker rm 命令加上選項 -f--force,強制執行)就能夠實現:

# 假設 dreamland 還在運行中
docker rm -f dreamland
複製代碼

一樣地,咱們能夠刪除全部容器,不管處於什麼狀態:

docker rm -f $(docker ps -aq)
複製代碼

自由探索

你盡能夠自由探索其餘咱們沒走過的路線,例如嘗試再次啓動以前已經中止的容器(docker start),或者暫停正在運行的容器(docker pause)。幸運的是,docker help 命令能夠爲咱們提供探索的指南針,例如咱們想了解 start 命令的使用方法:

$ docker help start

Usage:	docker start [OPTIONS] CONTAINER [CONTAINER...]

Start one or more stopped containers

Options:
  -a, --attach                  Attach STDOUT/STDERR and forward signals
      --checkpoint string       Restore from this checkpoint
      --checkpoint-dir string   Use a custom checkpoint storage directory
      --detach-keys string      Override the key sequence for
                                detaching a container
  -i, --interactive             Attach container's STDIN 複製代碼

讀到這裏,相信你已經瞭解瞭如何利用現有的鏡像創造容器,並進行管理。在接下來,咱們將帶你建立本身的 Docker 鏡像,開始成爲一名標準的「築夢師」!

容器化第一個應用:開啓築夢之旅

在以前的步驟中,咱們體驗了別人爲咱們提早準備好的鏡像(例如 hello-worldnginxubuntu),這些鏡像均可以在 Docker Hub 鏡像倉庫中找到。在這一步,咱們將開始築夢之旅:學習如何容器化(Containerization)你的應用。

正如開頭所說,咱們將容器化一個全棧的」夢想清單「應用,運行如下命令來獲取代碼,而後進入項目:

git clone -b start-point https://github.com/tuture-dev/docker-dream.git
cd docker-dream
複製代碼

在這一步中,咱們將容器化這個用 React 編寫的前端應用,用 Nginx 來提供前端頁面的訪問。

什麼是容器化

容器化包括三個階段:

  • 編寫代碼:咱們已經提供了寫好的代碼
  • 構建鏡像:也就是這一節的核心內容,下面會詳細展開
  • 建立和運行容器:經過容器的方式運行咱們的應用

構建鏡像

構建 Docker 鏡像主要包括兩種方式:

  1. 手動:根據現有的鏡像建立並運行一個容器,進入其中進行修改,而後運行 docker commit 命令根據修改後的容器建立新的鏡像
  2. 自動:建立 Dockerfile 文件,指定構建鏡像的命令,而後經過 docker build 命令直接建立鏡像

因爲篇幅有限,這篇文章只會講解使用最爲普遍的第二種建立鏡像的方式。

一些準備工做

咱們先把前端項目 client 構建成一個靜態頁面。確保你的機器上已經安裝 Node 和 npm(點擊這裏下載,或使用 nvm),而後進入到 client 目錄下,安裝全部依賴,並構建項目:

cd client
npm install
npm run build
複製代碼

等待一陣子後,你應該能夠看到 client/build 目錄,存放了咱們要展現的前端靜態頁面。

建立 Nginx 配置文件 client/config/nginx.conf,代碼以下:

server {
    listen 80;
    root /www;
    index index.html;
    sendfile on;
    sendfile_max_chunk 1M;
    tcp_nopush on;
    gzip_static on;

    location / {
        try_files $uri $uri/ /index.html;
    }
}
複製代碼

不熟悉 Nginx 配置的同窗不用擔憂哦,直接複製粘貼就能夠了。上面的配置大體意思是:監聽 80 端口,網頁根目錄在 /www,首頁文件是 index.html,若是訪問 / 則提供文件 index.html

建立 Dockerfile

而後就是這一步驟中最重要的代碼:Dockerfile!建立 client/Dockerfile 文件,代碼以下:

FROM nginx:1.13

# 刪除 Nginx 的默認配置
RUN rm /etc/nginx/conf.d/default.conf 
# 添加自定義 Nginx 配置
COPY config/nginx.conf /etc/nginx/conf.d/ 
# 將前端靜態文件拷貝到容器的 /www 目錄下
COPY build /www 複製代碼

能夠看到咱們用了 Dockerfile 中的三個指令:

  • FROM 用於指定基礎鏡像,這裏咱們基於 nginx:1.13 鏡像做爲構建的起點
  • RUN 命令用於在容器內運行任何命令(固然前提是命令必須存在)
  • COPY 命令用於從 Dockerfile 所在的目錄拷貝文件到容器指定的路徑

是時候來構建咱們的鏡像了,運行如下命令:

# 若是你已經在 client 目錄中
#(注意最後面有個點,表明當前目錄)
docker build -t dream-client .

# 若是你回到了項目根目錄
docker build -t dream-client client
複製代碼

能夠看到咱們指定了 -t--tag,容器標籤)爲 dream-client,最後指定了構建容器的上下文目錄(也就是 當前目錄 .client)。

運行以上的命令以後,你會發現:

Sending build context to Docker daemon:66.6MB
複製代碼

並且這個數字還在不斷變大,就像黑客科幻電影中的場景同樣,最後應該停在了 290MB 左右。接着運行了一系列的 Step(4 個),而後提示鏡像構建成功。

爲啥這個構建上下文(Build Context)這麼大?由於咱們把比「黑洞」還「重」的 node_modules 也加進去了!(忍不住想起了下面這張圖)

使用 .dockerignore 忽略不須要的文件

Docker 提供了相似 .gitignore 的機制,讓咱們能夠在構建鏡像時忽略特定的文件或目錄。建立 client/.dockerignore 文件(注意 dockerignore 前面有一個點):

node_modules
複製代碼

很簡單,咱們只想忽略掉可怕的 node_modules。再次運行構建命令:

docker build -t dream-client .
複製代碼

太好了!此次只有 1.386MB,並且速度也明顯快了不少!

運行容器

終於到了容器化的最後一步——建立並運行咱們的容器!經過如下命令運行剛纔建立的 dream-client 鏡像:

docker run -p 8080:80 --name client -d dream-client
複製代碼

與以前相似,咱們仍是設定端口映射規則爲 8080:80,容器名稱爲 client,而且經過 -d 設置爲後臺運行。而後訪問 localhost:8080

成功了!一開始定下的三個夢想也都完成了!

提示

甚至,咱們已經能夠經過內網來訪問「夢想清單」了。Linux 或 macOS 的同窗能夠在終端輸入 ifconfig 命令查詢本機內網 IP,Windows 的同窗則是在 CMD 輸入 ipconfig 查詢本機內網 IP,通常是以 10172.16~172.31192.168 開頭。例如個人內網 IP 是 192.168.0.2,那麼在同一局域網下(通常是 WiFi),能夠用其餘設備(好比說你的手機)訪問 192.168.0.2:8080

回憶與昇華

關於鏡像標籤

在剛纔的實戰中,你也許已經注意到在拉取和構建鏡像時,Docker 老是會爲咱們加上一個 :latest 標籤,這個 :latest 的含義即是「最新」的意思。和軟件的版本機制同樣,鏡像也能夠經過標籤實現「版本化」。

注意

latest 字面上的意思的確是「最新的」,但也只是一個普通的標籤,並不能確保真的是「最新的」,更不會自動更新。更多討論請參考這篇文章

實際上,咱們徹底能夠在拉取或構建鏡像時指定標籤(一般被認爲是一種好的作法):

docker pull nginx:1.13
docker build -t dream-client:1.0.0
複製代碼

還能夠給現有的鏡像打上標籤:

# 把默認的 latest 鏡像打上一個 newest 標籤
docker tag dream-client dream-client:newest
# 甚至能夠同時修改鏡像的名稱和標籤
docker tag dream-client:1.0.0 dream-client2:latest
複製代碼

能夠看到,標籤未必必定是版本,還能夠是任何字符串(固然最好要有意義,不然過了一陣子你也不記得這個打了這個標籤的容器有什麼做用了)。

關於 Dockerfile

Dockerfile 其實是默認名稱,咱們固然能夠取一個別的名字,例如 myDockerfile,而後在構建鏡像時指定 -f--file)參數便可:

docker build -f myDockerfile -t dream-client .
複製代碼

這裏舉兩個經典的使用場景:

  1. 例如在 Web 開發時,分別建立 Dockerfile.dev 用於構建開發鏡像,建立 Dockerfile.prod 構建生產環境下的鏡像;
  2. 在訓練 AI 模型時,建立 Dockerfile.cpu 用於構建用 CPU 訓練的鏡像,建立 Dockerfile.gpu 構建用 GPU 訓練的鏡像。

再次思考鏡像和容器的關係

通過剛纔的容器化實戰,相信你對鏡像和容器的關係又有了新的理解。請看下面這張圖:

在以前的「小試牛刀」環節中(用綠色箭頭標出),咱們:

  1. 經過 docker pull 從 Docker 鏡像倉庫拉取鏡像到本地
  2. 經過 docker run 命令,根據鏡像建立並運行容器
  3. 經過 docker stop 等命令操做容器,使其發生各類狀態轉變

而在這一節的容器化實戰中(用紅色箭頭標出),咱們:

  1. 經過 docker build 命令,根據一個 Dockerfile 文件構建鏡像
  2. 經過 docker tag 命令,給鏡像打上標籤,獲得一個新鏡像
  3. (因爲篇幅有限沒有講)經過 docker commit 命令,將一個現有的容器轉化爲鏡像

至此,這篇 Docker 快速入門實戰教程也就結束啦,但願你已經對 Docker 的概念和使用有了初步的理解。後續咱們還會發表 Docker 進階的內容(例如 Network 網絡、Volume 數據卷、Docker Compose 等等),手把手帶你們部署一個全棧應用(先後端和數據庫)到雲主機(或任何你可以登陸的機器),敬請期待~

想要學習更多精彩的實戰技術教程?來圖雀社區逛逛吧。

相關文章
相關標籤/搜索