在本教學課程中,您將瞭解如何將資料保存在容器應用程式中。 當您執行或更新它時,數據仍可供使用。 有兩種主要類型的磁碟區可用來保存數據。 本教學課程著重於 具名磁碟區。
您也會瞭解 系結掛接,以控制主機上的確切裝入點。 您可以使用系結掛接來保存數據,但它也可以將更多數據新增至容器。 在處理應用程式時,您可以使用系結掛接將原始程式碼掛接至容器,讓它看到程式代碼變更、回應,以及讓您立即看到變更。
本教學課程也會介紹影像分層、圖層快取和多階段組建。
在本教學課程中,您將瞭解如何:
- 瞭解跨容器的數據。
- 使用具名磁碟區保存數據。
- 使用系結掛接。
- 檢視影像圖層。
- 快取相依性。
- 瞭解多階段組建。
先決條件
本教學課程會繼續進行上一個教學課程: 使用Visual StudioCode建立及共用容器應用程式。 首先,選擇其中包含必要條件的一個。
瞭解跨容器的數據
在本節中,您將啟動兩個容器,並在每個容器中建立檔案。 在一個容器中建立的檔案無法在另一個容器中使用。
使用此指令啟動
ubuntu
容器:docker run -d ubuntu bash -c "shuf -i 1-10000 -n 1 -o /data.txt && tail -f /dev/null"
此命令會透過
&&
來啟動並叫用兩個命令。 第一個部分會挑選單一隨機數,並將它寫入/data.txt
。 第二個命令正在監控檔案,確保容器持續運行。在 VS Code 的 [容器瀏覽器] 中,以滑鼠右鍵按一下 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
命令來移除它們。
使用具名磁碟區保存您的 Todo 數據
根據預設,待辦事項應用程式會將其數據儲存在 的 /etc/todos/todo.db
中。
SQLite 資料庫是儲存單一檔案之數據的關係資料庫。
此方法適用於小型專案。
您可以在主機上保存單一檔案。 當您將它傳遞至下一個容器時,應用程式可以繼續從中斷的地方開始。 藉由建立一個磁碟區並將其連接或 掛載到存放資料的資料夾中,您可以保留資料。 容器會寫入 todo.db 檔案,並且該數據會持續保存至主機的卷中。
請在此部分使用名為 的卷。 Docker 會管理磁碟上的磁碟區實體位置。 請參閱磁碟區的名稱,而 Docker 提供正確的數據。
使用
docker volume create
命令建立磁碟區。docker volume create todo-db
在 [CONTAINERS] 底下,選取 [入門指南],然後按下滑鼠右鍵。 選取 [停止] 以停止應用程式容器。
若要從命令行停止容器,請使用
docker stop
命令。使用下列命令啟動 getting-started 容器。
docker run -dp 3000:3000 -v todo-db:/etc/todos getting-started
volume 參數指定要掛接的磁碟區和位置,
/etc/todos
。刷新瀏覽器以重新載入應用程式。 如果您已關閉瀏覽器視窗,請移至
http://localhost:3000/
。 將一些專案新增至您的 Todo 清單。拿掉 todo 應用程式的 快速入門 容器。 以滑鼠右鍵按兩下容器總管中的容器,然後選取 [移除 ] 或使用
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 |
使用容器的內容寫入新磁碟區 | 是的 | 不 |
支援磁碟區驅動程式 | 是的 | 不 |
有許多磁碟區驅動程式外掛程式可用來支援 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:lts-alpine sh -c "yarn install && yarn run dev"
此命令包含下列參數。
-
-dp 3000:3000
與之前相同。 以分離模式執行,並建立端口映射。 -
-w /app
容器內的工作目錄。 -
-v ${PWD}:/app"
Bind 會將目前目錄從容器中的主機掛接至/app
目錄。 -
node:lts-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 +。
在 VS Code 中,開啟 src/static/js/app.js。 變更行 109 上 [新增專案 ] 按鈕的 文字。
- {submitting ? 'Adding...' : 'Add Item'} + {submitting ? 'Adding...' : 'Add'}
儲存您的變更。
重新整理瀏覽器。 您應該會看到變更。
移除
node:lts-alpine
容器。在
app
資料夾中,執行下列命令來移除node_modules
在先前步驟中建立的資料夾。rm -r node_modules
檢視影像圖層
您可以查看組成影像的層次。
執行 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:lts-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:lts-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:lts-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進行變更。 例如,將標題變更為 「真棒的 Todo 應用程式」。
現在使用
docker build
再次建置 Docker 映像。 這次,您的輸出看起來應該有點不同。Sending build context to Docker daemon 219.1kB Step 1/6 : FROM node:lts-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:lts-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:lts-alpine
映射來執行建置,以最大化圖層快取,然後將輸出複製到 nginx 容器中。
清除資源
請保留到目前為止所做的一切,以繼續這一系列的教學課程。
後續步驟
您已瞭解儲存容器應用程式資料的選項。
接下來您要做什麼?
使用 Docker Compose 處理多個容器:
使用 MySQL 和 Docker Compose 建立多容器應用程式
部署至 Azure Container Apps:
部署至 Azure App Service