Docker 進階介紹
Docker Images 的操作與管理
Docker 映像檔的操作包括建立、下載及推送映像檔等。以下是主要命令及其參數說明:
docker build
用於根據 Dockerfile 建立新的映像檔。
參數 | 說明 |
---|---|
-t, --tag |
為建立的映像檔指定名稱和標籤 |
--file |
指定 Dockerfile 的路徑 |
--no-cache |
建立映像檔時不使用任何快取 |
--pull |
總是嘗試從遠程倉庫下載更新版本的基礎映像檔 |
--rm |
建立完畢後自動刪除中間容器 |
docker pull
從遠程倉庫下載映像檔。
參數 | 說明 |
---|---|
--all-tags |
下載映像檔的所有標籤 |
--disable-content-trust |
不驗證映像檔的完整性和可信度 |
docker push
將本地映像檔推送到遠程倉庫。
參數 | 說明 |
---|---|
--disable-content-trust |
不推送映像檔的完整性和可信度檢查數據 |
Docker Containers 的管理
Docker 容器的進階操作包括啟動、停止及執行命令等功能。
docker start
啟動一個或多個已停止的容器。
參數 | 說明 |
---|---|
-a, --attach |
附加到容器的 STDOUT/STDERR |
--interactive, -i |
使容器的 STDIN 保持開放 |
docker stop
停止一個運行中的容器。
參數 | 說明 |
---|---|
-t, --time |
設置停止容器前的等待秒數 |
docker exec
在運行的容器中執行命令。
參數 | 說明 |
---|---|
-i, --interactive |
保持 STDIN 開放,即使未附加到容器 |
-t, --tty |
為命令分配一個偽終端 |
--env |
設置在命令執行時的環境變數 |
Dockerfile
Dockerfile 是一種由 Docker 軟體使用的腳本,用於自動化 Docker 映像檔(Image)的建立過程。在 Dockerfile 中,您可以指定一系列指令和步驟,用於從基礎映像檔建立新的映像檔。這包括安裝軟體、複製檔案、設置環境變數等操作。
Single-Stage Build
以下是一個簡單的 Dockerfile 範例:
# 使用 Node.js 官方映像檔作為基礎
FROM node:14
# 設置工作目錄
WORKDIR /app
# 複製 package.json 和 package-lock.json
COPY package*.json ./
# 安裝 Angular CLI 和其他依賴
RUN npm install
RUN npm install -g @angular/cli
# 複製應用的其餘檔案
COPY . .
# 建構 Angular 應用
RUN ng build --prod
# 安裝並使用 serve 套件來提供靜態檔案服務
RUN npm install -g serve
CMD ["serve", "-s", "dist/my-angular-app", "-p", "80"]
# 暴露 80 端口
EXPOSE 80
解說:
Docker 指令 | 說明 |
---|---|
FROM node:14 |
使用 Node.js 版本 14 的官方映像檔作為基礎。 |
WORKDIR /app |
設置工作目錄為 /app 。 |
COPY package*.json ./ |
將 package.json 和 package-lock.json 複製到容器內。 |
RUN npm install RUN npm install -g @angular/cli |
安裝應用所需的 npm 套件以及全域安裝 Angular CLI。 |
COPY . . |
將當前目錄的其餘檔案(包括源代碼)複製到容器的工作目錄。 |
RUN ng build --prod |
執行 Angular 應用的建置過程,並使用生產模式(--prod )。 |
RUN npm install -g serve |
安裝 serve 套件,用於提供靜態檔案服務。 |
CMD ["serve", "-s", "dist/my-angular-app", "-p", "80"] |
使用 serve 啟動一個靜態檔案伺服器,服務於 80 端口。 |
EXPOSE 80 |
將容器的 80 端口暴露出來,供外部訪問。 |
這個 Dockerfile 將整個 Angular 應用建置和伺服器部署的過程合併在單一階段中,使用 Node.js 映像檔來執行所有必要的操作,包括應用建置和伺服。這種方法適合於簡單的應用或者開發、測試環境,但在生產環境中,建議使用多階段建置方法,以減少映像檔的大小和提高安全性。
Multi-Stage Build
# 階段 1: 使用 Node 映像檔建立 Angular 應用
FROM node:14 as build-step
# 設置工作目錄
WORKDIR /app
# 複製 package.json 和 package-lock.json
COPY package*.json /app/
# 安裝 Angular CLI 和其他依賴
RUN npm install
RUN npm install -g @angular/cli
# 複製應用的其餘檔案
COPY . /app
# 建構 Angular 應用
RUN ng build --prod
# 階段 2: 使用 Nginx 映像檔作為伺服器
FROM nginx:alpine
# 從 build-step 階段複製檔案到 Nginx 的服務目錄
COPY --from=build-step /app/dist/my-angular-app /usr/share/nginx/html
# 暴露 80 端口
EXPOSE 80
解說:
Docker 指令 | 說明 |
---|---|
FROM node:14 as build-step |
使用 Node.js 版本 14 的官方映像檔作為基礎,並開始第一階段的建置(稱為 build-step )。 |
WORKDIR /app |
設置工作目錄為 /app 。 |
COPY package*.json /app/ |
將 package.json 和 package-lock.json 複製到容器內。 |
RUN npm install RUN npm install -g @angular/cli |
安裝應用所需的 npm 套件以及全域安裝 Angular CLI。 |
COPY . /app |
將當前目錄的其餘檔案(包括源代碼)複製到容器的工作目錄。 |
RUN ng build --prod |
執行 Angular 應用的建置過程,並使用生產模式(--prod )。 |
FROM nginx:alpine |
開始第二階段的建置,使用 Nginx 的 Alpine Linux 版本映像檔。 |
COPY --from=build-step /app/dist/my-angular-app /usr/share/nginx/html |
從 build-step 階段複製建置好的 Angular 應用到 Nginx 伺服器的服務目錄。 |
EXPOSE 80 |
將容器的 80 端口暴露出來,供外部訪問。 |
這個 Dockerfile 用於建立一個 Angular 應用的 Docker 容器。第一階段主要負責建置 Angular 應用,而第二階段則設定一個 Nginx 伺服器來托管這個應用。這種多階段建置的方法可以減少最終映像檔的大小,因為它只包含運行應用所需的檔案。
Docker Compose
Docker Compose 是一個用於定義和運行多容器 Docker 應用程序的工具。它讓你使用 YAML 檔案來配置應用程序的服務,這讓部署複雜應用程序變得簡單。以下是 Docker Compose 的一些主要特點:
-
服務定義: 可以在
docker-compose.yml
檔案中定義應用程序的服務。這包括建構映像、環境變數、端口映射和卷配置。 -
多容器協作: Docker Compose 允許多個容器共同工作,例如,一個容器運行 web 應用,另一個運行資料庫。
-
一鍵部署: 透過單一命令
docker-compose up
,可以創建並啟動所有定義在docker-compose.yml
的服務。 -
環境隔離: Docker Compose 確保每個服務在隔離的環境中運行,確保項目間的獨立性。
-
可重複使用的配置:
docker-compose.yml
檔案可以在不同的環境中重複使用,確保了環境一致性和部署的簡化。
使用 Docker Compose 的一個典型例子是在開發環境中,開發者可以使用它來創建和管理包含應用程序、資料庫、消息隊列等多個容器的完整環境。
version: '3'
services:
web:
build: .
ports:
- "5000:5000"
redis:
image: "redis"
以上是一個簡單的 docker-compose.yml
檔案示例,其中定義了兩個服務:web
和 redis
。web
服務是使用 Dockerfile 在當前目錄建構的,而 redis
服務則是直接從 Docker Hub 拉取 Redis 映像。
Multi-Container & Networking
以下介紹如何使用 Docker 來配置一個 Nginx 容器(Container)作為負載均衡器(Load Balancer),實現 A/B 測試,將流量分配到兩個不同的 Angular 容器。以下是基於 Docker 和 Docker Compose 的配置步驟。
- 準備 Angular 容器
首先,假設您已經有兩個 Angular 應用,我們需要將它們各自打包成 Docker 容器。
Dockerfile for Angular App A & B:
# 基於 Node.js 建構 Angular 應用
FROM node:14 as build-step
WORKDIR /app
COPY package.json /app/
RUN npm install
COPY . /app/
RUN npm run build
# 基於 Nginx 服務 Angular 應用
FROM nginx:alpine
COPY --from=build-step /app/dist/angular-app /usr/share/nginx/html
上述 Dockerfile 適用於 Angular App A 和 B。您只需更改 COPY
指令中的 angular-app
路徑來指向相應的 Angular 應用。
- 配置 Nginx 容器作為負載均衡器
接下來,創建一個 Nginx 配置檔案來實現 A/B 測試。
nginx.conf:
http {
upstream backend {
server angular-app-a:80 weight=1;
server angular-app-b:80 weight=1;
}
server {
listen 80;
location / {
proxy_pass http://backend;
}
}
}
在這裡,angular-app-a 和 angular-app-b 是 Docker Compose 中定義的服務名稱,Nginx 會通過這些名稱在 angular-network 網路中找到對應的容器。
- 使用 Docker Compose 進行多容器配置
最後,使用 Docker Compose 來運行所有容器並實現網絡互聯。
docker-compose.yml:
version: '3'
services:
nginx:
image: nginx:alpine
volumes:
- ./nginx.conf:/etc/nginx/nginx.conf
ports:
- "80:80"
depends_on:
- angular-app-a
- angular-app-b
networks:
- angular-network
angular-app-a:
build:
context: ./path-to-angular-app-a
dockerfile: Dockerfile
networks:
- angular-network
angular-app-b:
build:
context: ./path-to-angular-app-b
dockerfile: Dockerfile
networks:
- angular-network
networks:
angular-network:
driver: bridge
在這個 docker-compose.yml
檔案中,我們定義了三個服務:Nginx 負載均衡器、Angular App A 和 Angular App B。Nginx 容器將通過掛載的 nginx.conf
檔案來配置 A/B 測試,而 Angular 容器則通過 Dockerfile 來建構。
配置中,angular-network 是一個自定義的橋接網路(bridge network),所有三個服務(Nginx、Angular App A、Angular App B)都被配置為使用這個網路。這樣,它們可以通過網路名稱互相發現和通訊。
- 執行與測試
完成以上配置後,您可以通過以下命令來啟動所有容器:
docker-compose up --build
然後,您可以通過訪問 http://localhost
來查看負載均衡器如何將請求分配到不同的 Angular 容器。每次刷新網頁時,Nginx 應該會交替地將您的請求轉發到 Angular App A 和 Angular App B。
Docker CI 的應用
Docker 在持續整合(Continuous Integration, CI)中的應用主要是提供一個一致且可重複的環境,讓軟體開發過程中的測試和部署變得更加高效和可靠。Docker 容器可以封裝應用程式和其依賴,確保在不同的開發、測試和生產環境中具有相同的運行狀態。這減少了因環境不一致導致的「在我機器上能運行」問題。
以下是以 GitLab 和 Azure DevOps 為例的 Docker CI 應用說明:
GitLab CI
GitLab CI/CD 是一個強大的工具,允許開發者自動化他們的構建、測試和部署流程。
- 創建 Dockerfile:
- 在專案根目錄創建一個
Dockerfile
,定義所需的環境。
- 在專案根目錄創建一個
- 編寫
.gitlab-ci.yml
:- 在
.gitlab-ci.yml
文件中定義 CI/CD 工作流程。 - 可以指定使用 Docker 映像作為執行環境。
- 在
- 自動化測試和部署:
- 每當有代碼推送到 GitLab,就會觸發 CI/CD 流程。
- 使用 Docker 容器運行單元測試和集成測試。
- 若測試通過,可自動將 Docker 容器部署到生產環境。
Azure DevOps CI
Azure DevOps 提供了一系列的 DevOps 工具,包括 Azure Pipelines,可用於實現 Docker 的 CI/CD。
- 創建 Dockerfile:
- 同樣,首先在專案中創建
Dockerfile
。
- 同樣,首先在專案中創建
- 配置 Azure Pipelines:
- 在 Azure DevOps 中創建一個新的 pipeline,選擇源代碼庫。
- 編寫
azure-pipelines.yml
文件,定義構建和測試流程。 - 可以設定使用 Docker 映像作為構建和測試環境。
- 構建和部署:
- 每次代碼更新都會觸發 pipeline。
- 在 Docker 容器中進行構建和測試。
- 成功後,可以將應用程式部署到各種服務,如 Azure Kubernetes Service (AKS)。
這些流程大大提高了開發的效率和一致性,同時減少了由於環境差異引起的錯誤。
Docker 安全性與效能
當討論 Docker 安全性與效能時,我們會專注於兩個主要方面:確保映像檔(Image)的安全性,以及透過使用資源限制(如 CPU、記憶體限制)來提升容器(Container)的效能。以下是對這些主題的更詳細說明:
確保映像檔的安全
映像檔是 Docker 容器運行的基礎,因此保障其安全性對於整體容器環境的安全至關重要。以下是一些關鍵步驟:
-
使用信譽良好的映像檔來源:只從可靠且受信任的來源(如 Docker Hub 的官方映像檔)下載映像檔。避免使用未經過驗證的第三方映像檔。
-
映像檔安全掃描:使用工具(如 Clair、Trivy)來掃描映像檔,檢查潛在的安全漏洞和不安全的配置。
-
定期更新映像檔:定期更新映像檔,以確保含有最新安全補丁和更新。
-
最小化映像檔大小:建立映像檔時,只包含必要的應用程式和依賴,以減少潛在的攻擊面。
-
映像檔簽名與驗證:使用 Docker Content Trust(DCT)等機制來簽名和驗證映像檔,以確保映像檔的完整性和來源的可靠性。
使用資源限制來提升容器效能
在 Docker 中,合理配置資源限制(如 CPU、記憶體)可以有效提升容器的效能和穩定性。以下是配置資源限制的關鍵考量:
-
CPU 限制:可以透過
--cpus
參數指定容器可以使用的 CPU 核心數量。這有助於避免單個容器佔用過多的 CPU 資源,從而影響其他容器的效能。 -
記憶體限制:使用
--memory
參數來限制容器可以使用的記憶體量。這有助於防止單個容器消耗過多記憶體資源,導致系統不穩定。 -
I/O 限制:配置 I/O 限制可以控制容器對磁碟的讀寫速度,這有助於平衡多個容器對 I/O 資源的使用,確保系統效能。
-
網路頻寬限制:透過
--network
參數設定網路頻寬的限制,以避免單個容器佔用過多的網路資源。
通過以上的配置和策略,可以大幅提高 Docker 容器的安全性和效能。這些措施不僅保護了容器本身,也保護了整個容器運行環境的穩定性和效能。