在掌握 Docker 基礎指令後,將動態運行的容器轉化為可重複部署的資產,是進階應用的核心。本文闡述此流程的理論脈絡,從端口映射開始,這是容器內服務與外部網路整合的關鍵。接著,在容器中部署自定義專案,是將應用程式及其依賴環境封裝的實踐過程。此過程產生的變更,可透過檔案系統差異比較進行檢視,確保狀態的可追溯性。最終,將此特定狀態的容器提交為新的映像檔,本質上是將一個經過配置的運行環境固化為不可變的靜態版本。這個從「動態容器」到「靜態映像檔」的轉換,是實現環境一致性與高效 CI/CD 流程的基石。
Docker容器進階操作:端口映射、自定義專案部署與映像檔管理
端口查詢與應用程式部署
docker port指令:查詢容器的端口映射
docker port指令用於查詢容器的特定內部端口被映射到主機的哪個端口。這在您啟動容器時沒有明確指定主機端口,或需要確認映射關係時非常有用。
語法:
$ docker port CONTAINER PRIVATE_PORT
範例:查詢Ghost部落格容器的2368端口映射
$ docker port OD-ghost 2368
4000
這表示OD-ghost容器內部的2368端口(Ghost部落格服務的預設端口)被映射到了主機的4000端口。
在Docker中部署自定義專案
將自定義專案部署到Docker容器中,是Docker的核心應用場景之一。玄貓將以一個Node.js專案為例,展示如何準備容器環境、拉取程式碼並運行。
部署步驟:
- 選擇基礎映像檔並啟動容器: 選擇一個維護良好且包含所需運行時的基礎映像檔(例如
dockerfile/nodejs)。在啟動容器時,我們需要考慮以下幾點:
- 端口映射: 應用程式將綁定到8000端口,因此需要將其映射到主機的8000端口。
- 容器命名: 為容器指定一個描述性的名稱,以便於後續引用。
$ docker run -it -p 8000:8000 --name code.it dockerfile/nodejs /bin/bash
準備容器內環境: 進入容器後,需要確認應用程式的依賴是否已安裝。對於Node.js專案,通常需要Git來拉取程式碼,以及npm來安裝Node.js模組。
dockerfile/nodejs映像檔通常已預裝Git和Node.js。獲取程式碼並安裝依賴:
- 進入容器後,切換到合適的目錄。
- 拉取專案程式碼(例如透過
git clone或git submodule update)。 - 安裝Node.js模組依賴。
[ root@3b0d5a04cdcd:/data ]$ cd /home
[ root@3b0d5a04cdcd:/home ]$ # 假設專案會被放置在 /home/code.it
[ root@3b0d5a04cdcd:/home ]$ git clone <your_project_repo> code.it # 範例,實際可能已透過卷掛載
[ root@3b0d5a04cdcd:/home ]$ cd code.it && git submodule update --init --recursive
[ root@3b0d5a04cdcd:/home/code.it ]$ npm install
- 運行應用程式:
[ root@3b0d5a04cdcd:/home/code.it ]$ node app.js
現在,您就可以透過localhost:8000訪問部署在容器中的應用程式了。
容器與映像檔的差異與版本控制
docker diff指令:查看容器與其基礎映像檔的差異
docker diff指令用於顯示容器檔案系統與其基礎映像檔之間的所有變更。這包括新增(A)、修改(C)和刪除(D)的檔案或目錄。
範例:查看code.it容器的差異
$ docker diff code.it
C /home
A /home/code.it
...
這表示/home目錄被修改了(C),並且新增了一個/home/code.it目錄(A),這通常是我們在容器內拉取程式碼和安裝依賴所導致的變更。
docker commit指令:從容器創建新映像檔
docker commit指令允許您將一個運行中或已停止的容器的當前狀態,保存為一個新的映像檔。這類似於Git的提交操作,您可以為新的映像檔添加提交訊息和作者資訊。
語法:
$ docker commit [選項] 容器名稱或ID [儲存庫名稱[:標籤]]
常用選項:
-p, --pause: 在提交過程中暫停容器(自v1.1.1起可用)。-m, --message="": 提交訊息,描述映像檔的變更內容。-a, --author="": 指定映像檔的作者。
範例:將code.it容器提交為新映像檔
$ docker commit -m "Code.it – A browser based text editor and IDE, with all dependencies installed" -a "玄貓" code.it shrikrishna/code.it:v1
這裡,我們將code.it容器的狀態提交為一個名為shrikrishna/code.it,標籤為v1的新映像檔,並添加了提交訊息和作者資訊。
映像檔命名慣例:
Docker映像檔的命名通常遵循[Docker Hub用戶名]/[應用程式或映像檔名稱]:[標籤]的慣例。例如,shrikrishna/code.it:v1中:
shrikrishna是Docker Hub的用戶名。code.it是應用程式或映像檔的名稱。v1是標籤,通常用於表示版本。
Docker容器與映像檔版本控制流程圖
此圖示展示了從運行容器到創建新映像檔的過程,以及期間的差異檢視。
@startuml
!define DISABLE_LINK
!define PLANTUML_FORMAT svg
!theme _none_
skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100
actor "使用者 (User)" as User
participant "Docker 客戶端 (Docker Client)" as Client
participant "Docker 守護進程 (Docker Daemon)" as Daemon
database "Docker 映像檔儲存 (Image Store)" as ImageStore
box "Docker 容器 (Docker Container)" #LightBlue
participant "運行中容器 (Running Container)" as Container
end box
User -> Client : `docker run <基礎映像檔>`
Client -> Daemon : 請求啟動容器
Daemon -> ImageStore : 獲取基礎映像檔
Daemon -> Container : 創建並啟動容器
User <-> Container : 在容器內進行操作 (安裝依賴, 部署程式碼)
User -> Client : `docker diff <容器>`
Client -> Daemon : 請求容器與基礎映像檔差異
Daemon -> Container : 檢測檔案系統變更
Container -> Daemon : 返回差異列表
Daemon -> Client : 返回差異列表
Client -> User : 顯示差異 (A/C/D)
User -> Client : `docker commit -m "訊息" -a "作者" <容器> <新映像檔名稱:標籤>`
Client -> Daemon : 請求提交容器為新映像檔
Daemon -> Container : 獲取容器當前狀態
Daemon -> ImageStore : 將容器狀態保存為新映像檔
ImageStore -> Daemon : 返回新映像檔ID
Daemon -> Client : 返回新映像檔ID
Client -> User : 顯示新映像檔ID
@enduml看圖說話:
此圖示描繪了從使用者啟動一個基於基礎映像檔的運行中容器,到最終將其狀態提交為一個新映像檔的完整流程。首先,使用者透過Docker客戶端執行docker run命令,守護進程從映像檔儲存中獲取基礎映像檔並啟動容器。使用者隨後在容器內部進行各種操作,例如安裝依賴和部署程式碼。在這些操作之後,使用者可以使用docker diff命令,讓客戶端請求守護進程檢測容器檔案系統與其基礎映像檔之間的差異,並將結果顯示給使用者。最後,當容器達到預期狀態時,使用者可以執行docker commit命令,客戶端將請求守護進程將容器的當前狀態保存為一個新的映像檔,並將其存儲在映像檔儲存中。這個過程有效地實現了容器狀態的版本控制,使得開發者可以根據需要創建自定義的、包含特定配置和應用程式的映像檔。
結語
玄貓認為,理解並善用docker port來管理容器的網路暴露、掌握在容器內部署自定義專案的流程,以及透過docker diff和docker commit進行容器狀態的版本控制,是Docker進階應用的核心。這些指令不僅提升了開發效率,也使得應用程式的部署和管理更加模組化和可重複。特別是docker commit,它提供了一種將容器的動態狀態固化為靜態映像檔的機制,為後續的部署和分發奠定了基礎。
從創新與突破的視角審視,Docker的進階操作不僅是技術能力的延伸,更是開發流程現代化的關鍵轉捩點。
docker commit將動態容器固化為靜態映像檔,完成了從「環境」到「可部署資產」的價值轉換。然而,這種手動操作的便利性,與Dockerfile所代表的自動化、可追溯建構形成了策略權衡。前者雖能快速驗證,卻容易累積「黑箱」技術債,導致維運困境;後者雖需前期投入,卻是確保品質與規模化部署的工程紀律基石。理解這兩者間的取捨,是技術領導者必須建立的核心認知。
隨著不可變基礎設施(Immutable Infrastructure)理念普及,未來純熟運用Dockerfile整合CI/CD管線,將成為衡量團隊DevOps成熟度的核心指標。手動提交映像檔的場景將大幅限縮於開發與除錯階段。
玄貓認為,高階管理者應將commit的學習定位為通往自動化的橋樑,而非終點。策略性地引導團隊建立標準化的Dockerfile建構實踐,才能將技術優勢真正轉化為穩固、可規模化的組織競爭力。