教學課程:在 VS Code 中使用磁碟區將資料保存在容器應用程式中
在本教學課程中,您將了解如何將資料保存在容器應用程式中。 當您執行或更新該應用程式時,資料仍然可用。 有兩種主要類型的磁碟區用來保存資料。 本教學課程專注於具名磁碟區。
您也會了解「繫結掛接」,其會控制主機上的確切掛接點。 您可以使用繫結掛接來保存資料,但其也可以將更多資料新增至容器。 在處理應用程式時,您可以使用繫結掛接,將原始程式碼掛接至容器,讓其看到程式碼變更、回應,以及讓您立即看到變更。
本教學課程也會介紹映像分層、圖層快取和多階段建置。
在本教學課程中,您會了解如何:
- 了解跨容器的資料。
- 使用具名磁碟區保存資料。
- 使用繫結裝載。
- 檢視映像圖層。
- 快取相依性。
- 了解多階段建置。
必要條件
本教學課程延續上一個教學課程:使用 Visual Studio Code 建立和共用 Docker 應用程式。 從這一項開始,其中包含必要條件。
了解跨容器的資料
在本節中,您將啟動兩個容器,並在每個容器中建立一個檔案。 在一個容器中建立的檔案無法在另一個容器中使用。
使用下列命令啟動
ubuntu
容器:docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
此命令會使用
&&
來叫用兩個命令。 第一個部分會挑選單一亂數,並將其寫入/data.txt
。 第二個命令正在監看檔案,讓容器保持執行中。在 VS Code 的 Docker 區域中,以滑鼠右鍵按一下 ubuntu 容器,然後選取 [連結殼層]。
終端機隨即開啟,其正在執行 Ubuntu 容器中的殼層。
執行下列命令以查看
/data.txt
檔案的內容。cat /data.txt
終端機會顯示介於 1 與 10000 之間的數字。
若要使用命令列來查看此結果,請使用
docker ps
命令取得容器識別碼,然後執行下列命令。docker exec <container-id> cat /data.txt
呼叫另一個
ubuntu
容器。docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
使用此命令來查看資料夾內容。
docker run -it ubuntu ls /
那裡應該沒有
data.txt
檔案,因為其只寫入第一個容器的臨時空間。選取這兩個 Ubuntu 容器。 按一下滑鼠右鍵並選取 [移除]。 從命令列中,您可以使用
docker rm -f
命令將其移除。
使用具名磁碟區保存您的待辦事項資料
根據預設,待辦事項應用程式會將其資料儲存在 SQLite 資料庫 (位於 /etc/todos/todo.db
) 中。
SQLite 資料庫是將資料儲存在單一檔案中的關聯式資料庫。
此方法適用於小型專案。
您可以在主機上保存單一檔案。 當您使其可供下一個容器使用時,應用程式可以挑選其離開的位置。 藉由建立磁碟區並將其連結或「掛接」至其中儲存資料的資料夾,您可以保存資料。 容器會寫入 todo.db 檔案,且該資料會保存至磁碟區中的主機。
針對本節,請使用具名磁碟區。 Docker 會維護磁碟上磁碟區的實體位置。 請參閱磁碟區的名稱,而 Docker 會提供正確的資料。
使用
docker volume create
命令建立磁碟區。docker volume create todo-db
在 [容器] 底下,選取 [入門],然後按一下滑鼠右鍵。 選取 [停止] 以停止應用程式容器。
若要從命令列停止容器,請使用
docker stop
命令。使用下列命令啟動 [入門] 容器。
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
volume 參數會指定要掛接的磁碟區,以及位置
/etc/todos
。重新整理瀏覽器以重新載入應用程式。 如果您已關閉瀏覽器視窗,請移至
http://localhost:3000/
。 將一些項目新增至您的待辦事項清單。移除待辦事項應用程式的 [入門] 容器。 以滑鼠右鍵按一下 Docker 區域中的容器,然後選取 [移除] 或使用
docker stop
和docker rm
命令。使用相同的命令啟動新的容器:
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
此命令會掛接與之前相同的磁碟機。 重新整理您的瀏覽器。 您新增的項目仍在清單中。
再次移除 [入門] 容器。
下面討論的具名磁碟區和繫結掛接是預設 Docker 引擎安裝所支援的主要類型磁碟區。
屬性 | 具名磁碟區 | 繫結掛接 |
---|---|---|
主機位置 | Docker 選擇 | 您的控制項 |
掛接範例 (使用 -v ) |
my-volume:/usr/local/data | /path/to/data:/usr/local/data |
將容器內容填入新的磁碟區 | 是 | No |
支援磁碟區驅動程式 | 是 | No |
有許多磁碟區驅動程式外掛程式可用來支援 NFS、SFTP、NetApp 等等。 這些外掛程式對於在叢集環境中的多個主機上執行容器特別重要,例如 Swarm 或 Kubernetes。
如果您想知道 Docker「實際」儲存資料的位置,請執行下列命令。
docker volume inspect todo-db
查看輸出,類似於下列結果。
[
{
"CreatedAt": "2019-09-26T02:18:36Z",
"Driver": "local",
"Labels": {},
"Mountpoint": "/var/lib/docker/volumes/todo-db/_data",
"Name": "todo-db",
"Options": {},
"Scope": "local"
}
]
Mountpoint
是儲存資料的實際位置。
在大部分的電腦上,您需要根存取權,才能從主機存取此目錄。
使用繫結裝載
透過「繫結掛接」,您可以控制主機上的確切掛接點。 此方法會保存資料,但通常用來將更多資料提供給容器。 您可以使用繫結掛接,將原始程式碼掛接至容器,讓其看到程式碼變更、回應,以及讓您立即看到變更。
若要執行容器來支援開發工作流程,您將採取下列步驟:
移除任何
getting-started
容器。在
app
資料夾中,執行下列命令。docker run -dp 3000:3000 -w /app -v ${PWD}:/app node:20-alpine sh -c "yarn install && yarn run dev"
此命令包含下列參數。
-dp 3000:3000
與之前相同。 以中斷連結模式執行,並建立連接埠對應。-w /app
容器內的工作目錄。-v ${PWD}:/app"
將目前目錄從容器中的主機繫結掛接至/app
目錄。node:20-alpine
要使用的映像。 此映像是應用程式的基礎映像,來自 Dockerfile。sh -c "yarn install && yarn run dev"
一個命令。 其會使用sh
啟動殼層,並執行yarn install
以安裝所有相依性。 然後其會執行yarn run dev
。 如果您查看package.json
,dev
指令碼正在啟動nodemon
。
您可以使用
docker logs
來監看記錄。docker logs -f <container-id>
$ nodemon src/index.js [nodemon] 2.0.20 [nodemon] to restart at any time, enter `rs` [nodemon] watching path(s): *.* [nodemon] watching extensions: js,mjs,json [nodemon] starting `node src/index.js` Using sqlite database at /etc/todos/todo.db Listening on port 3000
當您看到此清單上的最後一個項目時,應用程式正在執行。
當您完成監看記錄時,請選取終端機視窗中的任何金鑰,或在外部視窗中選取 Ctrl+C。
在 VS Code 中,開啟 src/static/js/app.js。 變更第 109 行上 [新增項目] 按鈕的文字。
- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
儲存您的變更。
重新整理您的瀏覽器。 您應該會看到變更。
檢視映像圖層
您可以查看組成映像的圖層。
執行 docker image history
命令以查看用來在映像內建立每個圖層的命令。
使用
docker image history
查看您稍早在教學課程中所建立「入門」映像中的圖層。docker image history getting-started
您的結果應該類似此輸出。
IMAGE CREATED CREATED BY SIZE COMMENT a78a40cbf866 18 seconds ago /bin/sh -c #(nop) CMD ["node" "/app/src/ind… 0B f1d1808565d6 19 seconds ago /bin/sh -c yarn install --production 85.4MB a2c054d14948 36 seconds ago /bin/sh -c #(nop) COPY dir:5dc710ad87c789593… 198kB 9577ae713121 37 seconds ago /bin/sh -c #(nop) WORKDIR /app 0B b95baba1cfdb 13 days ago /bin/sh -c #(nop) CMD ["node"] 0B <missing> 13 days ago /bin/sh -c #(nop) ENTRYPOINT ["docker-entry… 0B <missing> 13 days ago /bin/sh -c #(nop) COPY file:238737301d473041… 116B <missing> 13 days ago /bin/sh -c apk add --no-cache --virtual .bui… 5.35MB <missing> 13 days ago /bin/sh -c #(nop) ENV YARN_VERSION=1.21.1 0B <missing> 13 days ago /bin/sh -c addgroup -g 1000 node && addu… 74.3MB <missing> 13 days ago /bin/sh -c #(nop) ENV NODE_VERSION=12.14.1 0B <missing> 13 days ago /bin/sh -c #(nop) CMD ["/bin/sh"] 0B <missing> 13 days ago /bin/sh -c #(nop) ADD file:e69d441d729412d24… 5.59MB
每一行都代表映像中的一個圖層。 輸出顯示基礎圖層位於底部,而最新圖層位於頂端。 使用這項資訊,您可以看到每個圖層的大小,這可協助診斷大型映像。
有數行遭到截斷。 如果新增
--no-trunc
參數,您將取得完整輸出。docker image history --no-trunc getting-started
快取相依性
一旦圖層變更,所有下游圖層也都必須重新建立。 以下再次為 Dockerfile:
FROM node:20-alpine
WORKDIR /app
COPY . .
RUN yarn install --production
CMD ["node", "/app/src/index.js"]
Dockerfile 中的每個命令都會成為映像中的新圖層。
若要將圖層數目降至最低,您可以重新建構 Dockerfile 以支援相依性的快取。
針對節點型應用程式,這些相依性是在 package.json
檔案中定義的。
方法是首先只複製該檔案、安裝相依性,然後複製其他所有項目。
如果 package.json
發生了變更,此程序只會重新建立 yarn 相依性。
更新 Dockerfile 以先在
package.json
中進行複製、安裝相依性,然後複製其他所有項目。 以下是新的檔案:FROM node:20-alpine WORKDIR /app COPY package.json yarn.lock ./ RUN yarn install --production COPY . . CMD ["node", "/app/src/index.js"]
使用
docker build
建置新的映像。docker build -t getting-started .
您應該會看到類似下列結果的輸出:
Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:12-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Running in d53a06c9e4c2 yarn install v1.17.3 [1/4] Resolving packages... [2/4] Fetching packages... info fsevents@1.2.9: The platform "linux" is incompatible with this module. info "fsevents@1.2.9" is an optional dependency and failed compatibility check. Excluding it from installation. [3/4] Linking dependencies... [4/4] Building fresh packages... Done in 10.89s. Removing intermediate container d53a06c9e4c2 ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> a239a11f68d8 Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 49999f68df8f Removing intermediate container 49999f68df8f ---> e709c03bc597 Successfully built e709c03bc597 Successfully tagged getting-started:latest
已重建所有圖層。 這是預期的結果,因為您已變更 Dockerfile。
對 src/static/index.html 進行變更。 例如,變更標題以顯示「The Awesome Todo App」。
現在再次使用
docker build
建置 Docker 映像。 這次,您的輸出看起來應該有點不同。Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:12-alpine ---> b0dc3a5e5e9e Step 2/6 : WORKDIR /app ---> Using cache ---> 9577ae713121 Step 3/6 : COPY package* yarn.lock ./ ---> Using cache ---> bd5306f49fc8 Step 4/6 : RUN yarn install --production ---> Using cache ---> 4e68fbc2d704 Step 5/6 : COPY . . ---> cccde25a3d9a Step 6/6 : CMD ["node", "/app/src/index.js"] ---> Running in 2be75662c150 Removing intermediate container 2be75662c150 ---> 458e5c6f080c Successfully built 458e5c6f080c Successfully tagged getting-started:latest
因為您正在使用建置快取,所以其應該會快得多。
多階段建置
多階段建置是一個極其強大的工具,可協助使用多個階段來建立映像。 其有數個優點:
- 將建置階段相依性與執行階段相依性分開
- 僅透過傳送應用程式需要執行的內容,來降低整體映像大小
本節提供簡短的範例。
Maven/Tomcat 範例
建置 Java 型應用程式時,需要 JDK 才能將原始程式碼編譯為 Java 位元組程式碼。 生產中不需要該 JDK。 您可能使用 Maven 或 Gradle 之類的工具來協助建置應用程式。 最終映像中也不需要這些工具。
FROM maven AS build
WORKDIR /app
COPY . .
RUN mvn package
FROM tomcat
COPY --from=build /app/target/file.war /usr/local/tomcat/webapps
此範例會使用一個階段 (build
),以使用 Maven 執行實際的 Java 組建。
從「FROM tomcat」開始,第二個階段會在來自 build
階段的檔案中進行複製。
最終映像只是要建立的最後一個階段,可以使用 --target
參數將其覆寫。
React 範例
建置 React 應用程式時,您需要 Node 環境,才能將 JavaScript 程式碼、SASS 樣式表單等編譯成靜態 HTML、JavaScript 和 CSS。 如果您未執行伺服器端轉譯,則甚至不需要 Node 環境,即可進行生產建置。
FROM node:20-alpine AS build
WORKDIR /app
COPY package* yarn.lock ./
RUN yarn install
COPY public ./public
COPY src ./src
RUN yarn run build
FROM nginx:alpine
COPY --from=build /app/build /usr/share/nginx/html
此範例會使用 node:20
映像來執行建置,這會最大化圖層快取,然後將輸出複製到 nginx 容器。
清除資源
請保留到目前為止您所做的一切,以繼續這一系列的教學課程。
下一步
您已了解為容器應用程式保存資料的選項。
接下來您想要做什麼?
使用 Docker Compose 處理多個容器:
部署至 Azure 容器應用程式:
部署到 Azure App Service
意見反應
https://aka.ms/ContentUserFeedback。
即將登場:在 2024 年,我們將逐步淘汰 GitHub 問題作為內容的意見反應機制,並將它取代為新的意見反應系統。 如需詳細資訊,請參閱:提交並檢視相關的意見反應