上一篇文章,已經安裝好 Docker Desktop 了。接下來讓我們進入 Docker 的重點,即映像檔(image)與容器(container)的操作。
本文會陸續介紹相關的指令,讓讀者初步認識 Docker 的使用方式,並展示從下載軟體到運行起來的過程。算是 hello world 性質的範例。
此篇亦轉載到個人部落格。
本系列文章在示範方面,主要以在 command line(命令提示字元)輸入指令的方式來進行。而 Docker Desktop 可用來確認結果。若讀者熟悉了,亦可直接透過 GUI 進行如啟動、刪除等動作,較為便利。
Docker 指令的寫法,大致上可歸納成如下的格式。
docker 對象 動作 各種參數
雖然讀者可能看過如 docker ps
、docker run
之類的指令。但為了方便記憶,筆者在撰寫指令時,仍會以上述的格式為主。
讓我們下載第一個映像檔到本地,藉此初步認識 Docker 的操作。
docker image pull docker/getting-started:latest
此映像檔是 docker
的 getting-started
,其內容為官方提供的教學網站。下載後,可查看目前主機上已有的映像檔。
docker image ls
執行指令後,Docker 會以表格的形式列出來,示意結果如下。
REPOSITORY | TAG | IMAGE ID | CREATED | SIZE |
---|---|---|---|---|
docker/getting-started | latest | 3e4394f6b72f | 11 months ago | 47MB |
可以看到,映像檔會有自己的 id 和 tag(標籤)。
其中 id 是用來辨識映像檔,後續接觸到其他 Docker 指令時,會需要將它傳入。
至於 tag 則用來區別版本,讀者可想像成版本控制的「分支」。若下載映像檔時未提供 tag,則預設為「latest」。
若映像檔不再使用了,可將其刪除。指令寫法為 docker image rm {映像檔 id}
。
docker image rm 3e4394f6b72f
其實映像檔 id 不一定要完整寫出來,只要寫出的部份足以辨識,未與其它的重複即可。後續使用其他 Docker 指令也是如此。
docker image rm 3e43
如果主機上有多個想刪除的映像檔,也可傳入多個 id 或名稱。
docker image rm 3e43 a3b6
或是執行下列指令,一口氣刪除當下沒有容器的映像檔。
docker image prune
若讀者在前面剛好將「getting-started」這個映像檔給刪除了,請先下載回來。本節我們要用它來建立出容器。
準備好映像檔,便能建立出容器。指令寫法為:docker container create {各種參數} {映像檔 id | 映像檔名稱:標籤}
。
以上述的映像檔為例,範例寫法如下:
docker container create --name MyDockerTutorial -p 80:80 3e43
接著分別說明用到的幾個參數。
--name MyDockerTutorial
:將容器取名為「MyDockerTutorial」。-p 80:80
:將主機在 80 port 收到的請求,轉發給容器的 80 port。左邊是主機,右邊則是容器的 port。3e43
:用來辨認映像檔的 id。此處亦可寫成「getting-started:latest」。建立完畢後,可查看目前主機上已有的容器。
docker container ls -a
加上 -a
選項,代表列出所有的容器,否則只會列出運行中的容器。示意結果如下。
CONTAINER ID | IMAGE | CREATED | STATUS | NAMES |
---|---|---|---|---|
0a68392b0620 | 3e43 | 7 hours ago | Created | MyDockerTutorial |
可看到容器也有自己的 id。
如果容器有問題,例如不小心傳錯參數,或是壞掉了,這時只要刪除後重新建立即可,過程十分簡便。
刪除容器的指令寫法為 docker container rm {容器 id | 容器名稱}
。範例寫法如下:
docker container rm MyDockerTutorial
如果有多個想刪除的容器,也可傳入多個 id 或名稱。
docker container rm MyDockerTutorial MyRedis
或是執行下列指令,一口氣刪除停止中的容器。
docker image prune -f
加上 -f
選項,是為了讓 Docker 不必向我們再次確認,直接刪除即可。否則需輸入 y 來回答它的詢問。
本節就要將前面建立的容器「MyDockerTutorial」給運行起來。
啟動容器的指令寫法為 docker container start {容器 id | 容器名稱}
。範例寫法如下:
docker container start MyDockerTutorial
稍待一會兒,在瀏覽器前往 http://localhost
即可看到網站。代表我們成功啟動此容器了!
docker-getting-started-website.png
當容器不再使用了,可將其關閉。指令寫法為 docker container stop {容器 id | 容器名稱}
。範例寫法如下:
docker container stop MyDockerTutorial
此時執行 docker container ls -a
指令,可看到該容器的狀態(STATUS)變為「Exited」。
本文從下載映像檔、建立容器,到啟動容器,在範例中使用了以下指令。
docker image pull docker/getting-started:latest
docker container create --name MyDockerTutorial -p 80:80 3e4394f6b72f
docker container start MyDockerTutorial
為了方便,我們還可以將這三個步驟簡化為兩個,甚至一個指令。
比方說,我們已下載好映像檔,想直接運行容器,則指令寫法為:docker container run {各種參數} {映像檔 id | 映像檔名稱:標籤}
以下為範例指令。
docker container run -d --rm --name MyDockerTutorial -p 80:80 3e4394f6b72f
或
docker container run -d --rm --name MyDockerTutorial -p 80:80 docker/getting-started:latest
使用 run
,即可達到「建立容器後立即啟動」的效果。它還能搭配一些選項,讀者可自行嘗試。
-d
:讓該容器在背景運行。否則 command line 會被該容器給占用(需按 Ctrl + C
停止)。--rm
:讓容器停止後,自動刪除。接著再更進一步。如果在網路上找到了映像檔,但還沒下載就想直接運行,則指令寫法為:docker container run {各種參數} {映像檔名稱:標籤}
以下為範例指令。
docker container run -d --name MyDockerTutorial -p 80:80 docker/getting-started:latest
與前面相比,也就是映像檔的參數只能給予名稱。我們可視為:若本地沒有該映像檔,Docker 會先行下載,隨後再建立、啟動容器。
容器啟動後,我們可以進入容器中,看看裡面有什麼東西。指令寫法為:docker container exec -it {容器 id | 容器名稱} sh
以下為範例指令。
docker container exec -it MyDockerTutorial bash
此處使用了 -t
與 -i
兩個選項。前者會讓 Docker 建立一個虛擬終端機,讓我們能在主機 command line 上,對容器內部做事情。後者則是讓主機的指令能夠傳遞到容器中。
進入容器後,會看到一個類似 Linux 的 shell 環境。在裡面,包含「ls」、「cd」、「cat」等指令,甚至「vi」都能使用。
docker-exec-sh-demo.png
最後執行「exit」可以離開 shell 環境。
在 Docker 上,可以使用同一個映像檔建立出多個容器。那就意味著,在一臺主機上,能夠讓相同的服務,同時運行在多個 port。
如果讀者尚未關閉前面啟動的「MyDockerTutorial」容器,那麼不妨嘗試一下運行第二個。
docker container run -d --name MyDockerTutorial_2 -p 81:80 docker/getting-started:latest
上述指令在主機的 81 port 運行了名為「MyDockerTutorial_2」的容器。屆時可在瀏覽器前往 http://localhost:81
,同樣會見到該容器提供的的教學網站。
運行於多個 port 有什麼好處呢?例如 Node.js 是單執行緒的程式。那麼建立多個容器,再搭配負載平衡(load balance),可達到讓伺服器在相同時間,處理更多流量的效果。
本文算是 hello world 性質的範例,藉此認識 Docker 的使用方式,以及常用的指令。下一篇會示範透過 Docker 運行 MySQL 資料庫,加深讀者的感受。
今日文章到此結束!
最後推廣一下自己的部落格,我是「新手工程師的程式教室」的作者,請多指教