編譯整理|TesterHome社區
作者|Ishaan Gupta
以下為作者觀點:
Docker 徹底改變了我們開發、交付和運行應用程序的方式。它使開發人員能夠將應用程序打包到容器中 - 標準化的可執行組件,將應用程序源代碼與在任何環境中運行該代碼所需的操作系統 (OS) 庫和依賴項相結合。本文將介紹 docker 的關鍵概念、安裝、命令、構建映像、管理容器、網絡、數據持久性以及其他一些高級主題。
那么,讓我們開始吧。但在學習 docker 之前,你需要先了解容器/容器化。(本文內容較長,請耐心閱讀!)
容器和容器化
什么是容器?
容器是輕量級、獨立且可執行的軟件包,其中包含運行軟件所需的一切,包括代碼、運行時、系統工具、庫和設置。容器將軟件與其環境隔離開來,并確保其能夠統一運行,盡管開發和暫存之間存在差異。這意味著它們允許將應用程序及其所有依賴項和庫打包成一個單元,該單元可以在任何具有容器運行時(例如 Docker)的機器上運行。
什么是容器化?
容器化是將軟件代碼及其依賴項打包的過程,以便它可以在任何基礎架構上統一一致地運行。此方法可確保應用程序在從一個計算環境移動到另一個計算環境時可以輕松部署并可靠運行。
容器化的好處
-
一致性:無論應用程序在何處運行,其行為都相同。
-
效率:容器是輕量級的,共享主機操作系統內核,比虛擬機使用更少的系統資源。
-
可擴展性:隨著應用程序規模逐漸增長,可以輕松地擴大或縮小應用程序的規模。
-
隔離性:每個容器都在其隔離的環境中運行,提高了安全性和穩定性。
什么是 Docker?
Docker 是一個開源平臺,可讓開發人員輕松高效地構建、部署、運行、更新和管理容器化應用程序。以下是 Docker 受歡迎的一些主要原因:
Docker 簡化了開發工作流程,減少了“它在我的計算機上運行”的問題,并允許高效部署和擴展應用程序。
Docker 的主要優點:
-
可移植性:無論應用程序部署在何處,其運行方式都相同。
-
可擴展性:根據需求輕松地擴大或縮小應用程序的規模。
-
隔離性:容器封裝應用程序及其依賴項,確保它們彼此獨立運行。
Docker 的歷史
Docker于2013 年 3 月由 DotCloud(現為 Docker, Inc.)首次發布。Docker 的理念是創建一種輕量級、可移植且高效的方式,用于在不同環境中一致地打包和運行應用程序。這受到了集裝箱運輸概念的啟發,在集裝箱運輸概念中,應用程序及其依賴項被打包到可以輕松移動和部署的標準化容器中。
如今,Docker 已在各行各業得到廣泛采用,并得到了龐大而活躍的開發者和貢獻者社區的支持。它已成為容器化的基礎技術,并引發了其他相關技術的發展,例如用于容器編排的 Kubernetes。
Docker入門
在深入了解 Docker 之前,需要在系統上安裝它。Docker 適用于多個平臺,包括 Windows、macOS 和 Linux。
安裝 Docker
按照官方網站上適合的操作系統的說明進行操作。https://docs.docker.com/get-docker/
安裝后,驗證 Docker 是否正在運行:
docker — version
Docker 架構
了解Docker的架構:
Docker 組件
Docker 使用客戶端-服務器架構,包含幾個關鍵組件:
1.Docker 客戶端:允許用戶與 Docker 交互的命令行界面 (CLI) 工具。它與 Docker 守護程序通信以執行命令。
2.Docker Daemon(或 Docker Engine):Docker Engine 是一種開源容器化技術,允許開發人員將應用程序打包到容器中。容器是標準化的可執行組件,結合了應用程序源代碼與在任何環境中運行該代碼所需的操作系統 (OS) 庫和依賴項。它監聽 Docker API 請求并相應地處理它們。
3.containerd:管理容器生命周期的核心組件,包括啟動、停止和管理容器進程。
4.runc:一個輕量級的 CLI 工具,用于根據開放容器計劃 (OCI) 規范創建和運行容器。
5.Docker Registry:存儲和分發 Docker 鏡像的服務。Docker Hub 是默認的公共注冊表,但也可以使用私有注冊表。它類似于 GitHub,但它允許您推送鏡像而不是源代碼。
6.Docker 網絡:為容器提供網絡功能,使它們能夠相互通信并與外界通信。
7.Docker Volumes 和 Bind Mounts:實現容器和主機系統之間的數據持久性和共享。
8.Docker Compose一種使用 YAML 文件定義和運行多容器應用程序的工具。
Docker 如何運行應用程序
1.構建:Docker 客戶端向 Docker 守護進程發送構建請求,Docker 守護進程根據 中的指令創建鏡像Dockerfile。
2.運送:圖像存儲在 Docker 注冊表(公共或私有)中,可以從那里下載和共享。
3.運行:Docker 客戶端請求 Docker 守護進程根據鏡像創建并運行容器。
Docker 鏡像
Docker 鏡像是一個輕量級、獨立的可執行包,其中包含運行軟件所需的一切,包括代碼、運行時、庫、環境變量和配置文件。
拉取 Docker 鏡像
你可以從 Docker Hub 中提取鏡像:
docker pull hello-world
拉取鏡像后,可以使用 docker run 命令輕松運行鏡像。
docker 鏡像和容器之間的區別可以形象地想象,容器就是你從 github 獲取的一些源代碼在你的機器上運行 node app.js,而鏡像是 github 上的代碼庫。
基本docker命令
1.檢查Docker 版本
docker version
2.查看系統范圍的 Docker 信息
docker info
3.列出所有 Docker 鏡像
docker images
4.列出正在運行的容器
docker ps
docker ps -a // List All Containers (Running and Stopped)
5.從注冊表中提取鏡像
docker pull node:20 // Here 20 specifies a specific version of the node we want to pull
6.從映像創建并啟動新容器
在下面的例子中,我們以分離模式(-d)部署 NGINX 服務器,將主機端口 8080 映射到容器端口 80。
docker run -d -p 8080:80 nginx
7.停止正在運行的容器并將其刪除
docker stop <container_id>
docker rm <container_id> // Remove a Stopped Container
8.刪除圖像
docker rmi <image_id>
9.構建Docker 映像
docker build -t <your-image-name> .
10.)將鏡像推送至注冊表
docker push <Name of the image> <Name of the repo>
Docker 端口映射說明
Docker 中的端口映射是將主機上的端口映射到容器中的端口的過程。這對于從 Docker 主機外部訪問容器內運行的應用程序至關重要。
端口映射的工作原理
假設有一個在端口 3000 上的 Docker 容器內運行的 Web 服務器。默認情況下,此端口只能在 Docker 網絡內訪問,而不能從主機或外部網絡訪問。
為了使該服務器在容器外部可訪問,需要將端口從主機轉發到容器。
例子:
docker run -p [HOST_PORT]:[CONTAINER_PORT] [IMAGE-NAME]
-p是用于指定端口映射的標志。
Dockerfile
Dockerfile 是一個文本文件,其中包含一系列關于如何構建 Docker 鏡像的指令。每條指令都會在鏡像中創建一個層,并且這些層會被緩存以加快未來的構建速度。
Dockerfile 中的關鍵指令:
-
FROM:設置后續指令的基礎映像。
-
WORKDIR:設置容器內的工作目錄。
-
COPY:將文件從主機系統復制到容器。
-
RUN:在容器中執行命令。
-
CMD:指定容器啟動時運行的命令。
-
EXPOSE:記錄容器監聽的端口。
.dockerignore
.dockerignore 文件的工作方式類似于.gitignore 文件。它指定在構建 Docker 鏡像時應忽略哪些文件和目錄。這有助于保持鏡像的輕量級,避免不必要的文件。這會減少構建上下文的大小,并提高構建時間。添加 node_modules、dist 文件夾等等。
如何構建 docker 鏡像?
我們將以將基本的 mongo-express typescript 應用程序 docker 化為例。
1.初始化項目
mkdir ts-express-app
cd ts-express-app
npm init -y
npm install express mongoose dotenv
npm install --save-dev typescript @types/node @types/express @types/mongoose ts-node
tsc --init
2.創建 tsconfig.json
{
“compilerOptions” :{
“target” :“ES6” ,
“module” :“commonjs” ,
“outDir” :“。/dist” ,
“rootDir” :“。/src” ,
“strict” :true
}
}
3.創建 src/index.ts
import express from 'express';
import mongoose from 'mongoose';
import dotenv from 'dotenv';
dotenv.config();
const app = express();
const PORT = 3000;
const DB_URL = process.env.DATABASE_URL || '';
mongoose.connect(DB_URL, { useNewUrlParser: true, useUnifiedTopology: true })
.then(() => console.log('Connected to MongoDB'))
.catch(err => console.error('Could not connect to MongoDB', err));
app.get('/', (req, res) => {
res.send('Ram Ram bhai Sareya Ne');
});
app.listen(PORT, () => {
console.log(`Server is running on port ${PORT}`);
});
? ?
4.創建 package.json 文件和 .env 文件
"scripts": {
"start": "node dist/index.js",
"build": "tsc"
}
DATABASE_URL=mongodb://localhost:27017/ts-express-app
5.在項目根目錄中創建Dockerfile
# Use the Node.js 20 image as the base image
FROM node:20
# Set the working directory inside the container
WORKDIR /usr/src/app
# Copy package.json and package-lock.json
COPY package*.json ./
# Install dependencies
RUN npm install
# Copy the rest of the application code
COPY . .
# Build the TypeScript code
RUN npm run build
# Expose the port the app runs on
EXPOSE 3000
# Command to run the app
CMD ["npm", "start"]
6.在項目根目錄中創建一個文件:.dockerignore
node_modules
dist
npm-debug.log
7.)構建Docker 映像
docker build -t ts-express-app .
上述命令應該可以成功運行并給出類似如下的輸出:
8.)運行Docker容器
構建映像后,可以使用以下命令從中運行容器:
docker run -p 3000:3000 ts-express-app
就像我之前說的,上面的代碼運行了你的容器,并將主機上的端口 3000 映射到容器的端口 3000。你可以訪問 localhost:3000 并看到容器成功運行。
在上圖中,可以看到我的圖像列在 docker images 中,我可以看到容器在端口 3000 上運行,該端口與機器端口 3000 映射。花點時間在這里玩一玩,分析一下這里發生了什么。此外,在上面的命令中,我使用了一些我之前沒有解釋過的額外的東西。找出并了解它是你的家庭作業。如果你找到了它,請在評論部分對其進行評論,并對其進行適當的解釋 :)
現在,你可以使用 3 個簡單命令將鏡像推送到 docker hub 注冊表 -
9.將鏡像推送到Docker Registry
docker login
docker tag ts-express-app your-dockerhub-username/ts-express-app:latest
docker push your-dockerhub-username/ts-express-app:latest
在上方輸入您的 dockerhub 用戶名,代替“your-dockerhub-username”。我使用了表達式標簽,稍后我會解釋,現在請耐心等待!
恭喜你將第一個鏡像推送到 dockerhub。現在我相信您已經熟悉了構建鏡像和運行容器的基礎知識,讓我們更深入地了解一下。
現在在生產模式下,你可以隱藏 .env 文件以保護您的機密。那么如何在不使用 .env 文件的情況下將這些 .env 中的機密告知 docker 呢?
只需使用“-e”標志即可將環境變量發送到您的應用程序。
docker run -p 3000:3000 -e DATABASE_URL=mongodb://localhost:27017/ts-express-app ts-express-app
Docker Tags(標簽)
Docker 標簽傳達有關特定鏡像版本/變體的有用信息。標簽允許你從 Docker 注冊表中識別和提取鏡像的不同版本。它們是鏡像 ID 的別名,通常如下所示:f1477ec11d12。這只是一種引用鏡像的方式。一個很好的例子是 Git 標簽如何引用你歷史記錄中的特定提交。
標記 Docker 鏡像的一般語法是:
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
如果沒有指定標簽,Dockerlatest默認使用該標簽。
標簽使用的兩種最常見情況是:
1.在構建鏡像時,我們使用以下命令:
docker build -t username/image_name:tag_name .
2. 通過命令明確標記圖像tag。
docker tag SOURCE_IMAGE[:TAG] TARGET_IMAGE[:TAG]
3.版本管理:標簽通常用于指示鏡像的不同版本。例如,您可能有1.0、1.1、2.0等標簽,表示主要或次要版本更新。
4.環境或階段標識:標簽可以幫助區分開發、暫存和生產環境。例如,您可能有dev、staging和等標簽prod。
5.架構或平臺識別:標簽可以識別為不同架構或平臺構建的圖像,例如amd64、arm64或windows。
讓我們通過在命令中使用標簽來進一步理解它-
1.使用標簽構建 Docker 映像:
docker build -t express-mongo-app:1.0 .
2.拉取特定標簽:
docker pull node:14.18.0
3.使用新標簽標記現有圖像:
docker tag express-mongo-app:1.0 express-mongo-app:latest
4.使用標簽管理版本:
使用語義版本控制(MAJOR.MINOR.PATCH)—
docker build -t express-mongo-app:1.0.0 .
docker tag express-mongo-app:1.0.0 express-mongo-app:1.0
docker tag express-mongo-app:1.0.0 express-mongo-app:latest
?
Docker exec 命令
該docker exec命令允許你在正在運行的 Docker 容器內運行命令。這對于調試、運行管理任務、創建文件夾/卷或檢查容器的狀態非常有用。
基本docker exec用法
docker exec [OPTIONS] CONTAINER_ID|CONTAINER_NAME COMMAND [ARG…]
-
選項:各種選項,如-it交互模式。
-
CONTAINER:容器的名稱或 ID。
-
COMMAND:您想要在容器內運行的命令。
-
[ARG…]:命令的參數。
這將在正在運行的容器內打開一個交互式 Bash shell。然后你可以在容器環境中運行命令、檢查文件、創建/刪除卷或執行腳本。
選項-it代表docker exec“-interactive -tty”,它允許您與容器的shell進行交互。
現在你可能想知道我上面提到的卷是什么。讓我們深入探討一下!
Docker Volumes
Docker Volumes 是掛載在 Docker 容器上的文件系統,用于保存容器生成的數據。
什么是 Docker 文件系統?
Docker 容器執行 Docker 鏡像中指定的軟件堆棧。鏡像由在 Union File System 上運行的只讀層組成。當我們啟動新容器時,Docker 會在鏡像層之上添加一個讀寫層,使容器能夠像傳統的 Linux 文件系統一樣運行。因此,容器內的每個文件修改都會在讀寫層中生成一個可運行的副本。但是,當容器停止或刪除時,讀寫層就會消失。
Docker 管理保存在主機文件系統某個部分(Linux 上為 /var/lib/docker/volumes)中的卷。文件系統的這一部分不應由非 Docker 進程更改。在 Docker 中,卷是存儲數據的最有效方式。使用 docker volume create 命令,我們可以直接創建卷,或者 Docker 在創建容器或服務時可以為我們創建卷。
主要有三種類型的卷:
-
Named Volumes:由 Docker 管理并存儲在主機文件系統上的某個位置。
-
Bind Mounts:將目錄或文件從主機掛載到容器中。在主機系統上,綁定掛載可以保存在任何地方。這些可能是關鍵的系統文件夾或文件。它們始終可由在 Docker 主機或 Docker 容器中運行的非 Docker 進程修改。相比之下,綁定掛載不如卷有用。
-
tmpfs Mounts:將臨時文件系統掛載到容器中,存儲在主機的內存中。這些掛載永遠不會寫入主機系統的文件系統;相反,它們僅保存在主機系統的內存中。無論是在 Docker 主機上還是在容器中,它都不會存儲在磁盤上。敏感或非持久狀態數據可以在容器的持續時間內存儲在 tmpfs 掛載上。
命名卷:
使用以下命令創建命名卷:
docker volume create my-ts-app-data
現在,讓我們將卷掛載到容器內的目錄中。我們正在將卷掛載my-ts-app-data到/app/data容器內的目錄中。寫入/app/data容器內的任何數據都將存儲在主機上的命名卷中。
docker run -d -p 3000:3000 -e DATABASE_URL=mongodb://mongo:27017/ts-express-app -v my-ts-app-data:/data/db ts-express-app
使用docker volume inspect “my-ts-app-data”命令顯示有關卷的詳細信息,包括其在主機文件系統上的位置。
要刪除不再需要的卷,只需使用“rm”命令。
docker volume rm my-ts-app-data
Docker 中卷的工作
現在,讓我們嘗試一些新東西。假設我想在 mongoDB 指南針應用中可視化我的數據。但是我如何將它連接到容器中的卷?
通過運行以下命令在本地啟動 mongo 容器 -
docker run -p 27017:27017 -d mongo
打開你的mongoDB指南針并連接到27017端口。創建一個數據庫和集合并在其中插入一些數據并保存。
添加了一個新的數據庫和一些隨機數據
現在終止容器,然后重新啟動它。打開 mongoDB 指南針并檢查我們之前創建的數據庫和數據。你看到了什么?它不見了,對吧。
那么我們如何保存數據?你猜對了。使用卷!
我們之前已經創建了一個名為“my-ts-app-data”的卷,我們只使用它。將卷掛載到 mongo 容器的/data/db目錄中,然后使用以下命令運行它。
docker run -d -v my-ts-app-data:/data/db -p 27017:27017 mongo
現在重復上述步驟,創建一個數據庫并在其中添加數據。關閉容器,重新啟動它并重新檢查您之前輸入的數據。您將看到您的數據已持久保存!
現在,既然我們已經了解了命名卷,現在讓我們深入研究一些核心 docker 主題。正如您在上面注意到的,我在解釋 docker 卷時使用了“層”這個詞。但什么是層?讓我們看看……
Docker 中的層(Layers In Docker)
到目前為止,我們知道 Docker 構建由一系列有序的構建指令組成。Dockerfile 中的每個指令大致轉換為一個層,也稱為鏡像層。當您從鏡像創建新容器時,會在鏡像層頂部添加一個新的可寫層,從而允許容器進行更改而無需修改底層鏡像層。
什么是 Docker 層?
1.基礎層:這是 Docker 鏡像的起點。它包含操作系統,例如 Ubuntu、Alpine 等等(無論您的 dockerfile 指定什么)。此層是不可變的,并作為后續層的基礎。
2.中間層:這些層代表 Dockerfile 中的指令,例如RUN、COPY和ADD。每條指令都會在前一條指令之上創建一個新層。中間層是只讀且緩存的。
3.頂部讀/寫層:當您從鏡像運行容器時,Docker 會在只讀鏡像層之上添加一個可寫層。這允許容器進行更改而無需修改底層鏡像。
4.可重復使用和可共享:層可緩存并可在不同的鏡像之間重復使用,從而提高鏡像的構建和共享效率。如果多個鏡像是從同一個基礎鏡像構建的,或者共享通用指令,則它們可以重復使用相同的層,從而減少存儲空間并加快鏡像下載和構建速度。
如何創建圖層
層是根據 Dockerfile 中指定的指令創建的。Dockerfile 中的每個指令都會在先前的層之上生成一個新層。以下是 Dockerfile 示例:
FROM ubuntu: 18.04 // This instruction creates a base layer by pulling the ubuntu: 18.04 image from the Docker registry.
COPY . /app // This instruction creates a new layer on top of the base layer. It copies the entire contents of the build context (the directory containing the Dockerfile) into the /app directory inside the container.
RUN make /app // This instruction creates another layer by running the make /app command inside the container. This command builds the application located in the /app directory.
CMD python /app/app.py // This creates a new layer and specifies the default command to run when the container starts, which is python /app/app.py.
? ? ? ?
在上圖中我們可以看到,每條指令都會在之前的指令之上創建一個新層,形成一個層堆棧,構成最終的 Docker 鏡像。為了更加直觀,您可以參考下圖來了解這里到底發生了什么。
圖層的圖像表示
層緩存(Layer Caching)
當我們使用 Dockerfile 構建 Docker 鏡像時,Docker 會按順序處理每條指令并為每個指令創建一個新層。如果鏡像的某個層未更改,則 Docker 構建器會從構建緩存中獲取該層。如果某個層自上次構建以來發生了變化,則必須重建該層及其后面的所有層。讓我用一個例子來解釋一下——
首次構建圖像
對 app.js 文件進行微小修改,第二次構建圖像
正如你在上面的屏幕截圖中看到的,在第一張圖片中,我已經將我的 express 應用程序構建為一個圖像,我們可以看到每個層都是從頭開始構建的。現在我做了一個小改動(只是console.log('hi')在 app.js 文件中添加了一個,現在我正在重建圖像。所以現在在第二張圖片中你可以看到第 2、3、4 層被緩存,因為它們沒有變化,但是由于文件發生了變化,docker 確認了該變化,因此第 5 層沒有被緩存并從頭開始構建。并且由于第 5 層已更改,因此在其上構建的所有層(在其之后)都將從頭開始重建。
注意:盡管截圖中仍未顯示緩存,但圖 2 中的第 1 層仍處于緩存狀態。我其實不知道為什么,如果您發現了,請在評論中告訴我。不過不用擔心,它確實被緩存了。
現在,你已經對將應用程序 docker 化以及其內部工作原理以及 docker 中的層有了很好的了解。現在,在繼續前進之前,請稍事休息,擺弄卷,創建它們并在軟件中訪問它們。還可以通過構建和重建它們,使用多個基于技術堆棧的應用程序來玩轉您的 dockerfile。嘗試優化 dockerfile 以減少步驟/層,并最大限度地利用緩存層來提高效率。
Docker 網絡
默認情況下,Docker 容器無法相互通信。因此,docker 網絡允許容器相互通信并與外界通信。它們支持隔離、安全性以及對 Docker 容器之間通信的控制。
Docker 網絡的類型
Docker 提供了幾種類型的網絡:
1.橋接網絡:
獨立容器的默認網絡類型。橋接網絡在主機和容器之間創建基于軟件的橋梁。連接到網絡的容器可以相互通信,但它們與網絡外部的容器隔離。網絡中的每個容器都分配有自己的 IP 地址。由于網絡橋接到主機,因此容器也能夠在 LAN 和互聯網上通信。但它們不會作為物理設備出現在 LAN 上。
2.主機網絡:
使用主機網絡模式的容器共享主機的網絡堆棧,沒有任何隔離。它們沒有分配自己的 IP 地址,端口綁定將直接發布到主機的網絡接口。這意味著偵聽端口 80 的容器進程將綁定到<your_host_ip>:80
3.覆蓋網絡:
覆蓋網絡是跨多個 Docker 主機的分布式網絡。該網絡允許任何主機上運行的所有容器相互通信,而無需操作系統級路由支持。覆蓋網絡實現了 Docker Swarm 集群的網絡,但當您運行兩個單獨的 Docker Engine 實例且容器必須直接相互聯系時,您也可以使用它們。這允許您構建自己的類似 Swarm 的環境。
4.Macvlan網絡:
Macvlan 是另一個高級選項,它允許容器作為物理設備出現在您的網絡上。它的工作原理是為網絡中的每個容器分配一個唯一的 MAC 地址。此網絡類型要求您將主機的一個物理接口專用于虛擬網絡。還必須適當配置更廣泛的網絡,以支持運行許多容器的活動 Docker 主機可能創建的大量 MAC 地址。
5.ipvlan:
IPvLAN 是一種驅動程序,可精確控制分配給容器的 IPv4 和 IPv6 地址,以及第 2 層和第 3 層 VLAN 標記和路由。當您將容器化服務與現有物理網絡集成時,此驅動程序非常有用。IPvLAN 網絡分配有自己的接口,與基于橋接的網絡相比,它具有性能優勢。
6. 無網絡:
隔離的、沒有網絡接口的容器。
讓我們嘗試讓容器互相對話。
使用以下命令創建網絡(默認情況下它是橋接網絡):—
當您運行一個容器而沒有指定網絡時,它將連接到橋接網絡。
docker network create my-first-network
docker network ls
在 Bridge 網絡上運行容器 —
docker run -d --name c1 --network my-first-network nginx
docker run -d --name c2 --network my-first-network nginx
現在讓我們將容器 1 連接到容器 2,我們將進入 c1,然后 ping c2
docker exec -it c1 /bin/bash
ping c2
你可以看到它正在運行。現在讓我們嘗試一些新東西。我將在一個容器中運行 mongo,在另一個容器中運行我的 express 應用程序,然后嘗試通過我的 express 應用程序訪問 mongo 容器。使用我們之前創建的相同的 express 應用程序代碼,只需在下面的 .env 文件中即可 ——
DATABASE_URL=[container_name]://mongodb:27017/ts-express-app-dbDATABASE_URL=mongodb://mongodb:27017/ts-express-app-db
docker run -d --name mongodb --network my-first-network -v my-ts-app-data:/data/db -p 27017:27017 mongodocker run -d -p 3000:3000 --network my-first-network -e DATABASE_URL='mongodb://mongodb:27017/ts-express-app-db' ts-express-appYou can see both container up, now try adding some data using postman or curl command in your terminal. You will see a success response, to confirm that the data is in mongodb, you can go inside the container and run below mongo commands.
docker exec -it mongodb mongo use mydatabase db.users.find().pretty()
你還可以檢查 mongoDB 的容器日志來確認數據是否存儲。
刪除網絡——
docker network rm my-first-network
# remove all unused network (networks that aren't connected to even a single container)
docker network prune
斷開容器與網絡的連接——
docker network disconnect my-first-network mongodb
Docker 組成
Docker Compose 是一款可用于定義和運行多容器 Docker 應用程序的工具。它使用 YAML 文件 ( docker-compose.yml) 來配置和編排組成應用程序的服務,包括它們的依賴項、網絡、卷和其他配置設置。
到目前為止,我們一直在使用的 Express 應用程序的docker-compose.yml文件示例:
version: '3.9'
services:
ts-express-app:
build: .
image: "express-mongo-ts-docker"
container_name: ts-express-app
ports:
- "3000:3000"
environment:
- MONGO_URL=mongodb://mongodb:27017/ts-express-app-db
depends_on:
- mongodb
mongodb:
image: mongo
container_name: mongodb
volumes:
- my-ts-app-data:/data/db
ports:
- "27017:27017"
volumes:
my-ts-app-data:
讓我們逐行解釋一下上述文件的含義——
1.版本聲明:
version: '3.9':指定Docker Compose文件格式的版本。
2.服務:
服務是部署單元,用于定義要使用哪個容器鏡像。我在上面的文件中定義了 2 個服務
a.) ts-express-app
這項服務定義了我們的 Express 應用程序。
-
build:?從當前目錄中的 Dockerfile 構建 Docker 鏡像。
-
image: "express-mongo-ts-docker":將圖像命名為express-mongo-ts-docker。(可選添加)
-
container_name: ts-express-app:設置容器名稱為ts-express-app。
-
ports: - "3000:3000":端口映射照常,無需解釋。
-
environment: - MONGO_URL=mongodb://mongodb:27017/ts-express-app-dbMONGO_URL:設置我們的應用用于連接 MongoDB 的環境變量。此 URL 指向mongodb下面 Compose 文件中定義的服務。
-
depends_on: - mongodb:確保ts-express-app服務在服務后啟動mongodb。
B)mongodb:
該服務定義 MongoDB 數據庫。
-
image: mongo:使用來自 Docker Hub 的官方 MongoDB 鏡像。
-
container_name: mongodb:設置容器名稱為mongodb。
-
volumes: - my-ts-app-data:/data/db:將 Docker 卷掛載my-ts-app-data到/data/db容器中,這是 MongoDB 存儲數據的地方。(同樣,我們之前已經學過這一點,因此需要深入解釋)
-
ports: - "27017:27017":端口映射照常(再次無需解釋……呼……)
3.卷Volumes
my-ts-app-data:我們在文件末尾定義了我們在這里使用的卷。
好的,既然我們已經學會了編寫文件,請復制上述代碼并docker-compose.yml在應用程序的根目錄中定義一個文件。然后進入終端并運行命令docker-compose up --build,等待它構建您的圖像并啟動容器。您將看到成功消息,現在您的 mongo 和 express 應用程序容器終于在同一個網絡上運行,并正確連接到我們定義的卷,可供使用。
要停止應用程序,請使用命令 -docker-compose down
下面是我們的 docker 儀表板的圖片,可以在其中看到一個 docker 容器在我們正在運行的兩個容器中運行(我們的 mongo 和 express 應用程序)。在第三張圖片中,我使用 POSTMAN 添加了一些數據,然后使用 GET req 從我們的數據庫中檢索了數據。
很簡單,不是嗎!:)
此外,我們還可以定義如下所示的自定義網絡和一些其他自定義的自解釋內容。如果我們沒有像上面那樣定義網絡,docker 將自動為我們的服務創建一個默認網絡。此默認網絡通常以我們的 docker-compose.yml 文件所在的項目目錄命名。
我還在下面附加了我們的 express 應用程序的 github 存儲庫鏈接,只需克隆、安裝庫、按照文件中的定義創建卷docker-compose.yml并運行docker-compose up --build命令即可。
是的,就是這樣。這就是你的docker-compose主要目標!剩下的就等你去探索了!
在 docker 中還有很多更高級的東西需要學習,但本文就講到這里。我很快就會寫這篇文章的第二部分,其中一部分是關于 kubernetes 的。到那時,我們就可以練習今天學到的東西了。
最后的想法
在本文中,我通過示例介紹了 docker 的幾乎所有基本概念。我嘗試解釋初學者需要了解的所有內容,我可以自信地說,你已經為 docker 做好準備了!
我希望你理解并能理解其中的大部分內容,我知道這篇文章可能會很長,但請相信我,我試圖總結初學者開始使用 docker 所需的一切。像往常一樣,遇到麻煩或想自己嘗試使用 docker 的新事物時,請務必閱讀官方文檔(https://docs.docker.com/guides/)的具體內容。(原文鏈接:https://levelup.gitconnected.com/docker-beginner-to-expert-tutorial-68555aa3e544)
由TesterHome社區主辦的MTSC2024第十三屆中國互聯網測試開發大會,將于2024年7月20日在上海舉行。
大會日程:主會場+5個平行專場(LLM測試創新、質量保障、效能提升、游戲、智能終端質效),詳情:MTSC2024上海大會主會場、五大專場→議題亮點
8折優惠購票限期發售中!(掃描下方圖片二維碼了解詳情)