文章目錄
- Docker簡介
- Docker和虛擬機的聯系和區別
- 基本原理和概念
- 鏡像
- 容器
- 倉庫
- Docker安裝配置
- 容器化和Dockerfile
- 實踐環節
- Docker Compose
Docker簡介
- Docker是一個用于構建build、運行run、傳送share應用程序的平臺,可以把應用程序打包成一個個的集裝箱,然后小鯨魚就可以把它們運送到任何所需要的地方。
- Docker 是利用 Linux 內核的 Namespace + Cgroups 實現進程級隔離和資源限制,提供輕量級、快速可移植的容器技術,是現代云原生架構的基石之一。
- Docker 是一個開源的容器化平臺,可以把應用程序和它的依賴打包在一個輕量級、可移植、自包含的容器中,保證跨環境一致運行。
- 一句話:“一次構建,到處運行”。
- Docker 解決了什么問題?
- 在傳統部署中,常常遇到:
- 依賴沖突:不同應用需要不同版本的庫,部署在同一機器容易打架。
- 環境不一致:開發、測試、生產環境配置不一致,導致“在我機器上能跑”。
- 復雜部署流程:要手動配置各種環境,效率低、容易出錯。
- Docker 通過容器機制解決這些問題:
- 應用 + 環境打包成鏡像 → 一次構建,任意運行
- 鏡像不可變,版本可控,回滾方便
- 容器輕量、秒級啟動、資源隔離
-
以一個前后端分離的網站,如果沒有docker,那么我們要在本地先安裝以下內容,才可以運行:
- 安裝前端Node.js環境
- 安裝各種npm依賴
- 安裝Java運行時環境
- 安裝SpringBoot微服務的各種第三方依賴包
- 安裝MySQL數據庫
- 安裝配置Redis緩存
- 安裝配置Nginx負載均衡
- 配置各種環境變量并啟動腳本
-
而且這還只是開發環境,如果是要在測試環境也配一邊就要再來一次,耗時耗力而且容易出錯。
- 但是有了Docker我們就可以把他們打包成一個一個的集裝箱,只要在開發環境中運行成功了,那么在測試環境中運行也是沒有問題的。
- 核心概念
# Docker常用命令# 查看本地鏡像
docker images# 拉取鏡像
docker pull nginx# 啟動容器
docker run -d -p 8080:80 nginx# 查看運行中的容器
docker ps# 停止容器
docker stop <container_id># 進入容器
docker exec -it <container_id> /bin/bash
Docker和虛擬機的聯系和區別
- 聯系
- 目的相同:容器和虛擬機都是用來實現隔離,讓應用運行在相互隔離的環境中:
- 避免依賴沖突
- 保證環境一致性
- 提高資源利用率
- 都支持跨平臺部署:容器鏡像、虛擬機鏡像都能實現 “一次打包,到處運行”。
- 都能通過編排工具管理(如 K8s 支持容器,VM 支持 OpenStack、vSphere 等)
- 目的相同:容器和虛擬機都是用來實現隔離,讓應用運行在相互隔離的環境中:
- Docker 容器 ≠ 虛擬機,不需要 Hypervisor(虛擬化技術:將物理資源虛擬為多個邏輯資源的技術),不是完全模擬一個硬件環境
- Docker 容器 = 基于宿主機 Linux 內核的隔離進程,啟動快,資源開銷小
- 虛擬機一定程度上實現了資源的整合,可以將一臺服務器的計算能力、存儲能力、網絡資源分配給多個邏輯服務器,實現多臺服務器的功能
- 但是每臺虛擬機都需要占用大量的資源,如CPU、內存、硬盤、網絡等,而且啟動速度很慢
- 最主要的是,大部份情況下,我們一臺服務器上只需要運行一個主要對外提供服務的應用程序就行了,并不需要用到一個完整的操作系統所提供的所有功能,如下圖所示
- 上面的例子來說其實我們所需要的只是一個web服務器,但是虛擬機卻要啟動一個完整的操作系統,包括操作系統內核,各種系統服務,各種工具,甚至圖形界面等等,這些我們并不需要的服務會占用大量的資源,導致了資源的浪費和啟動速度慢的問題
- 于是容器技術應運而生,但是要注意,Docker并不是容器!
- Docker只是容器的一種實現,是一個容器化的解決方案和平臺;而容器是一種虛擬化技術,和虛擬機類似,也是一個獨立的環境,可以在這個環境中運行應用程序,但是和虛擬機不同的是它并不需要運行一個完整的操作系統,而是使用宿主機的操作系統,所以啟動速度非常快,通常只需要幾秒鐘,同時因為所需要的資源更少,所以可以在一臺物理服務器上運行更多的容器,這樣就可以更加充分地利用服務器的資源,減少資源的閑置和浪費。
# 虛擬機架構硬件
│
└── Hypervisor (KVM / VMware / Hyper-V)│├── Guest OS (Linux / Windows)│ └── App A├── Guest OS (Linux / Windows)│ └── App B
# 容器架構硬件
│
└── 宿主機 OS (Linux內核)│└── Docker Engine / containerd├── Container A (App + libs)├── Container B (App + libs)
- 容器不需要 Guest OS,進程直接運行在宿主機內核之上。
- 虛擬機需要完整 Guest OS,有更高隔離,但更重。
- 容器和虛擬機的主要聯系是都實現了應用隔離,方便跨平臺部署。區別在于虛擬機是通過 Hypervisor 提供系統級虛擬化,每個VM都有完整的操作系統,啟動慢、資源占用大,隔離性強;而容器是基于宿主機內核,通過 Linux 的 Namespace 和 Cgroups 技術提供進程級隔離,啟動快、資源占用小,非常適合微服務和大規模部署。容器與虛擬機是互補關系,通常混合使用,比如在公有云上用VM作為物理隔離基礎,容器作為上層彈性計算單位。
- 虛擬機提供系統級隔離,容器提供進程級隔離;VM 啟動慢資源重隔離強,容器啟動快資源輕靈活高效,兩者可以結合使用,滿足不同場景需求。
基本原理和概念
- Docker 鏡像是應用程序和依賴的靜態打包模板,容器是鏡像運行時的隔離進程,倉庫用于存儲和分發鏡像。三者配合實現了應用的一鍵打包、快速部署和跨環境一致運行,是現代 DevOps 流水線的核心組件。
Dockerfile → docker build → 鏡像 (Image) → docker push → 倉庫 (Registry)↓docker run↓容器 (Container)
鏡像
- 鏡像是一個只讀的模版,可以用來創建容器。
- 鏡像和容器的關系,就好比Java中類和實例的關系一樣,我們可以定義一個類中有哪些屬性和方法,這個定義好的類就是模版,然后我們可以根據這個模版來創建多個實例,這些實例就是這個類的對象,對應到Docker中,鏡像就是一個模版,容器就是這個模版的一個實例,可以有一個也可以有多個。
- 鏡像是一個靜態的模板,包含了應用程序和所有依賴、庫、工具、配置等。
- 容器運行時會在鏡像上加一個可寫層(Writable Layer)
- 可以理解成容器的快照,容器運行時是基于鏡像啟動出來的。
- 特點:
- 分層結構,每一層是只讀的
- 可復用,相同基礎層不會重復存儲
- 版本可控,便于回滾和管理
docker images # 查看本地鏡像
docker pull nginx # 拉取遠程鏡像
docker build -t myapp:v1 . # 構建鏡像
docker rmi <image_id> # 刪除鏡像
容器
- 容器是Docker的運行實例,提供了一個獨立的可移植的環境。
- 鏡像和容器的關系,就好比Java中類和實例的關系一樣,我們可以定義一個類中有哪些屬性和方法,這個定義好的類就是模版,然后我們可以根據這個模版來創建多個實例,這些實例就是這個類的對象,對應到Docker中,鏡像就是一個模版,容器就是這個模版的一個實例,可以有一個也可以有多個。
- 容器是鏡像的運行時實例,本質上是一個受限隔離的進程,它運行在宿主機內核之上。
- 容器 = 運行中受限隔離的進程 + 分層文件系統。
- 特點:
- 容器之間互相隔離,與宿主機隔離
- 輕量,共享宿主機內核(不像 VM 需要 Guest OS)
- 可以隨時創建 / 啟動 / 停止 / 刪除
- 容器是臨時的,可以隨時銷毀,也可以通過數據卷持久化數據
docker run -d -p 8080:80 nginx # 啟動容器
docker ps # 查看運行中的容器
docker stop <container_id> # 停止容器
docker rm <container_id> # 刪除容器
docker exec -it <container_id> /bin/bash # 進入容器
倉庫
- 鏡像如何分享給別人呢?這就涉及到Docker倉庫的概念了。
- Docker倉庫是用來存儲Docker鏡像的地方,最流行和最常用的倉庫就是DockerHub,這是一個公共的Docker倉庫,用來集中存儲和管理Docker鏡像,可以在這里下載各種鏡像,也可以將鏡像上傳到倉庫實現鏡像的共享和復用。
- 倉庫(Registry)是用來存放和分發鏡像的服務器。1、公共倉庫(Public):如 Docker Hub。2、私有倉庫(Private):企業內部自建 Registry,保障鏡像安全、加快拉取速度。
- 倉庫(Registry)里可以有很多 倉庫名(Repository),一個 Repository 中可以有多個 標簽(Tag),每個標簽對應一個鏡像版本。
nginx:1.25.2
nginx:latest
mycompany/myapp:v1.0.0docker.io/nginx:latest # Docker Hub
registry.example.com/myapp:v1.0 # 私有倉庫
docker login registry.example.com # 登錄私有倉庫
docker push myapp:v1 # 推送鏡像
docker pull myapp:v1 # 拉取鏡像
Docker安裝配置
- 官網:https://www.docker.com/
- 安裝完成之后記得啟動Docker,Windows系統記得開啟Hyper-V功能
- Docker使用Client-Server架構模式,Docker Client和Docker Daemon之間使用socket或者RESTful API進行通信,Docker Daemon就是服務端的守護進程,負責管理Docker的各種資源,Docker Client負責向Docker Daemon發送請求,Docker Daemon接收到請求之后進行處理,然后將結果返回給Docker Client,Docker Daemon是一個后臺進程,用來接收并處理來自Docker客戶端度請求,然后將結果返回給Docker客戶端,所以我們在終端中輸入各種Docker命令,實際上都是通過Docker客戶端發送給Docker Daemon的,然后Docker Daemon進行處理再將結果返回給客戶端,就可以在終端中看到執行結果了。
容器化和Dockerfile
- 容器化Containerization,顧名思義就是將應用程序打包成容器,然后在容器中執行應用程序的過程,主要有三步
- 創建一個Dockerfile,告訴Docker創建應用程序鏡像所需要的步驟和配置
- 使用Dockerfile構建鏡像
- 使用鏡像創建和運行容器
- Dockerfile是一個文本文件,里面包含了一條一條的指令,用來告訴Docker如何來構建鏡像,這個鏡像包括了我們應用程序執行的所有命令,也就是剛剛提到的各種依賴,配置環境和運行應用程序所需要的所有內容:
- 精簡版操作系統
- 應用程序的運行時環境
- 應用程序
- 第三方依賴庫或者包
- 應用程序的配置文件和環境變量等
實踐環節
-
寫一個js腳本文件,輸出"Hello World!"
-
沒有Docker之前,我們在其他機器要運行代碼,只能通過以下步驟:
- Step1: 安裝操作系統
- Step2: 安裝JavaScript運行環境(NodeJS)
- Step3: 復制應用程序、依賴包、配置文件
- Step4: 執行啟動命令運行程序
-
有了Docker后我們可以把下面的步驟給寫入Dockerfile里面,剩下的工作就交給Docker來自動完成
- 需要先指定一個基礎鏡像,鏡像是按層次結構來構建的,每一層都是基于上一層的,所以要先指定一個基礎鏡像然后在這個鏡像的基礎上再添加我們的應用程序
- 比如可以在一個基礎的linux鏡像開始然后安裝nodejs,也可以直接使用nodejs的鏡像,
FROM node:14-alpine
- 然后需要把我們的應用程序復制到鏡像中,可以使用copy命令來復制文件,
COPY source dest
,比如COPY index.js /index.js
- 接下來需要在鏡像中運行應用程序,可以使用
CMD
命令來運行應用程序,CMD是個方括號,里面第一個參數表示可執行程序的名字,第二個參數表示可執行程序接收到的參數CMD [ "node", "/index,js" ]
,也可以不用方括號,如CMD node /index.js
- 回到終端使用
docker build -t 鏡像名字 .
來構建鏡像,后面加的一個點表示的是當前目錄,也就是Dockerfile所在的目錄 docker image ls
或者是docker images
,查看所有的鏡像,latest表示最新版本docker run 鏡像名字
,即可執行當前鏡像文件
Docker Compose
- 用于定義和運行多容器Docker應用程序的工具
- 使用YAML文件來配置應用程序的服務
- 一條命令即可創建并啟動所有服務
- 實際開發環境中這些服務是需要相互關聯著才能工作的,Docker Compose解決的就是這個問題,通過一個單獨的docker-compose.yaml的配置文件來將這一組互相關聯的容器組合在一起,形成一個項目,然后使用一條命令就可以啟動、停止或者重建這些服務,
docker compose up