從入門到深入,Docker新手學習教程

圖片

圖片

編譯整理|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 psdocker 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-appcd ts-express-appnpm init -y
npm install express mongoose dotenvnpm install --save-dev typescript @types/node @types/express @types/mongoose ts-nodetsc --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 imageFROM node:20
# Set the working directory inside the containerWORKDIR /usr/src/app
# Copy package.json and package-lock.jsonCOPY package*.json ./
# Install dependenciesRUN npm install
# Copy the rest of the application codeCOPY . .
# Build the TypeScript codeRUN npm run build
# Expose the port the app runs onEXPOSE 3000
# Command to run the appCMD ["npm", "start"]

6.在項目根目錄中創建一個文件:.dockerignore

node_modulesdistnpm-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 logindocker tag ts-express-app your-dockerhub-username/ts-express-app:latestdocker 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.0docker 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-networkdocker network ls

在 Bridge 網絡上運行容器 —

docker run -d --name c1 --network my-first-network nginxdocker 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折優惠購票限期發售中!(掃描下方圖片二維碼了解詳情)

圖片

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/40903.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/40903.shtml
英文地址,請注明出處:http://en.pswp.cn/web/40903.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

InspireFace-商用級的跨平臺開源人臉分析SDK

InspireFace-商用級的跨平臺開源人臉分析SDK InspireFaceSDK是由insightface開發的?款?臉識別軟件開發?具包&#xff08;SDK&#xff09;。它提供了?系列功能&#xff0c;可以滿?各種應?場景下的?臉識別需求&#xff0c;包括但不限于閘機、?臉?禁、?臉驗證等。 該S…

ubuntu22 sshd設置

專欄總目錄 一、安裝sshd服務 sudo apt updatesudo apt install -y openssh-server 二、配置sshd 使用文本編輯器打開/etc/ssh/sshd_config sudo vi /etc/ssh/sshd_config &#xff08;一&#xff09;配置sshd服務的偵聽端口 建議將ssh的偵聽端口改為7000以上的端口&#…

【bazel】快速下載教程

bazel下載鏈接&#xff1a; https://github.com/bazelbuild/bazel/releases?page11 直接在github上下載&#xff0c;會因為網絡不穩定&#xff0c;而頻繁下載錯誤 這里提供一個超級快速的方法&#xff01;&#xff01;&#xff01; 用迅雷下載&#xff01; 1.從github上復…

cpp http server/client

httplib 使用httplib庫 basedemo server.cpp #include "httplib.h" #include <iostream> using namespace httplib;int main(void) {Server svr;svr.Get("/hello", [](const Request& req, Response& res) {std::cout << "lo…

實現Java Web應用的高性能負載均衡方案

實現Java Web應用的高性能負載均衡方案 大家好&#xff0c;我是微賺淘客系統3.0的小編&#xff0c;也是冬天不穿秋褲&#xff0c;天冷也要風度的程序猿&#xff01; 在高并發的網絡環境中&#xff0c;負載均衡是確保Web應用程序高性能和可靠性的關鍵策略之一。本文將探討如何…

【力扣 - 每日一題】3115. 質數的最大距離(一次遍歷、頭尾遍歷、空間換時間、埃式篩、歐拉篩、打表)Golang實現

原題鏈接 題目描述 給你一個整數數組 nums。 返回兩個&#xff08;不一定不同的&#xff09;質數在 nums 中 下標 的 最大距離。 示例 1&#xff1a; 輸入&#xff1a; nums [4,2,9,5,3] 輸出&#xff1a; 3 解釋&#xff1a; nums[1]、nums[3] 和 nums[4] 是質數。因此答…

算法系列--分治排序|再談快速排序|快速排序的優化|快速選擇算法

前言:本文就前期學習快速排序算法的一些疑惑點進行詳細解答,并且給出基礎快速排序算法的優化版本 一.再談快速排序 快速排序算法的核心是分治思想,分治策略分為以下三步: 分解:將原問題分解為若干相似,規模較小的子問題解決:如果子問題規模較小,直接解決;否則遞歸解決子問題合…

策略模式的應用

前言 系統有一個需求就是采購員審批注冊供應商的信息時&#xff0c;會生成一個供應商的賬號&#xff0c;此時需要發送供應商的賬號信息&#xff08;賬號、密碼&#xff09;到注冊填寫的郵箱中&#xff0c;通知供應商賬號信息&#xff0c;當時很快就寫好了一個工具類&#xff0…

Python 學習中什么是字典,如何操作字典?

什么是字典 字典&#xff08;Dictionary&#xff09;是Python中的一種內置數據結構&#xff0c;用于存儲鍵值對&#xff08;key-value pair&#xff09;。字典的特點是通過鍵來快速查找值&#xff0c;鍵必須是唯一的&#xff0c;而值可以是任何數據類型。字典在其他編程語言中…

vue實現搜索文章關鍵字,滑到指定位置并且高亮

1、輸入搜索條件&#xff0c;點擊搜索按鈕 2、滑到定位到指定的搜索條件。 <template><div><div class"search_form"><el-inputv-model"searchVal"placeholder"請輸入關鍵字查詢"clearablesize"small"style&quo…

HashMap的底層實現原理詳解

HashMap是Java中最常用的集合類之一&#xff0c;其基于哈希表的Map接口實現&#xff0c;提供了快速的鍵值對存儲和檢索功能。深入理解HashMap的底層實現原理&#xff0c;對于提升編程技能、應對技術面試以及優化程序性能都具有重要意義。以下從技術難點、面試官關注點、回答吸引…

數據庫作業day3

創建一個student表用于存儲學生信息 CREATE TABLE student( id INT PRIMARY KEY, name VARCHAR(20) NOT NULL, grade FLOAT ); 向student表中添加一條新記錄 記錄中id字段的值為1&#xff0c;name字段的值為"monkey"&#xff0c;grade字段的值為98.5 insert into …

對于老百姓而言VR到底能做什么?

VR技術自誕生以來不斷發展&#xff0c;已經廣泛應用于教育、醫療、工程、軍事、航空、航海、影視、娛樂等方面&#xff0c;譬如&#xff0c;大型工程或軍事活動VR預演可以大幅度減少人力物力投入&#xff1b;在航空領域&#xff0c;航天飛行員在訓練艙中面對屏幕進行各種駕駛操…

mysql修改密碼失敗報錯無法登錄解決辦法

mysql: [Warning] Using a password on the command line interface can be insecure. ERROR 1045 (28000): Access denied for user root@localhost (using password: YES) 這個問題是因為在嘗試使用命令行連接MySQL時,使用了明文密碼,這是不安全的。同時,由于某種原因,您…

Kylin中的查詢引擎:大數據查詢加速的引擎解析

Kylin中的查詢引擎&#xff1a;大數據查詢加速的引擎解析 Apache Kylin是一個開源的分布式分析引擎&#xff0c;專為大規模數據集提供快速的SQL查詢和多維分析&#xff08;OLAP&#xff09;能力。在Kylin的架構中&#xff0c;查詢引擎&#xff08;Query Engine&#xff09;扮演…

【Linux進階】文件系統4——文件系統特性

1.磁盤組成與分區的復習 首先說明一下磁盤的物理組成&#xff0c;整塊磁盤的組成主要有&#xff1a; 圓形的碟片&#xff08;主要記錄數據的部分&#xff09;&#xff1b;機械手臂&#xff0c;與在機械手臂上的磁頭&#xff08;可擦寫碟片上的數據);主軸馬達&#xff0c;可以…

打開瀏覽器控制臺,點擊應用,瀏覽器崩潰

調試的時候&#xff0c;打開控制臺&#xff0c;點擊 “應用” 立馬瀏覽器奔潰&#xff0c;但是點擊別的沒問題 調查發現是因為manifest.json這個文件引起的 manifest.json 最主要的原因是因為沒有設置這個sizes字段 Google瀏覽器更新大概到126之后的版本會有問題&#xff0c;之…

AI多模態教程:Qwen-VL多模態大模型實踐指南

一、模型介紹 Qwen-VL&#xff0c;由阿里云研發的大規模視覺語言模型&#xff08;Large Vision Language Model, LVLM&#xff09;&#xff0c;代表了人工智能領域的一個重大突破。該模型具有處理和關聯圖像、文本、檢測框等多種類型數據的能力&#xff0c;其輸出形式同樣多樣…

代碼隨想錄Day69(圖論Part05)

并查集 // 1.初始化 int fa[MAXN]; void init(int n) {for (int i1;i<n;i)fa[i]i; }// 2.查詢 找到的祖先直接返回&#xff0c;未進行路徑壓縮 int.find(int i){if(fa[i] i)return i;// 遞歸出口&#xff0c;當到達了祖先位置&#xff0c;就返回祖先elsereturn find(fa[i])…

py基礎語法簡述

py基礎&#xff0c;常用sdk 一些要點 python中是沒有常量的關鍵字的&#xff0c;只是我們常常約定使用大寫字符組合的變量名表示常量&#xff0c;也有“不要對其進行賦值”的提醒操作 PI 3.14python3中有六個標準的數據類型&#xff1a; Number(數字)、String(字符串)、Boo…