Skip to content

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 的一些主要特點:

  1. 服務定義: 可以在 docker-compose.yml 檔案中定義應用程序的服務。這包括建構映像、環境變數、端口映射和卷配置。

  2. 多容器協作: Docker Compose 允許多個容器共同工作,例如,一個容器運行 web 應用,另一個運行資料庫。

  3. 一鍵部署: 透過單一命令 docker-compose up,可以創建並啟動所有定義在 docker-compose.yml 的服務。

  4. 環境隔離: Docker Compose 確保每個服務在隔離的環境中運行,確保項目間的獨立性。

  5. 可重複使用的配置: docker-compose.yml 檔案可以在不同的環境中重複使用,確保了環境一致性和部署的簡化。

使用 Docker Compose 的一個典型例子是在開發環境中,開發者可以使用它來創建和管理包含應用程序、資料庫、消息隊列等多個容器的完整環境。

version: '3'
services:
  web:
    build: .
    ports:
      - "5000:5000"
  redis:
    image: "redis"

以上是一個簡單的 docker-compose.yml 檔案示例,其中定義了兩個服務:webredisweb 服務是使用 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 是一個強大的工具,允許開發者自動化他們的構建、測試和部署流程。

  1. 創建 Dockerfile:
    • 在專案根目錄創建一個 Dockerfile,定義所需的環境。
  2. 編寫 .gitlab-ci.yml:
    • .gitlab-ci.yml 文件中定義 CI/CD 工作流程。
    • 可以指定使用 Docker 映像作為執行環境。
  3. 自動化測試和部署:
    • 每當有代碼推送到 GitLab,就會觸發 CI/CD 流程。
    • 使用 Docker 容器運行單元測試和集成測試。
    • 若測試通過,可自動將 Docker 容器部署到生產環境。

Azure DevOps CI

Azure DevOps 提供了一系列的 DevOps 工具,包括 Azure Pipelines,可用於實現 Docker 的 CI/CD。

  1. 創建 Dockerfile:
    • 同樣,首先在專案中創建 Dockerfile
  2. 配置 Azure Pipelines:
    • 在 Azure DevOps 中創建一個新的 pipeline,選擇源代碼庫。
    • 編寫 azure-pipelines.yml 文件,定義構建和測試流程。
    • 可以設定使用 Docker 映像作為構建和測試環境。
  3. 構建和部署:
    • 每次代碼更新都會觸發 pipeline。
    • 在 Docker 容器中進行構建和測試。
    • 成功後,可以將應用程式部署到各種服務,如 Azure Kubernetes Service (AKS)。

這些流程大大提高了開發的效率和一致性,同時減少了由於環境差異引起的錯誤。

Docker 安全性與效能

當討論 Docker 安全性與效能時,我們會專注於兩個主要方面:確保映像檔(Image)的安全性,以及透過使用資源限制(如 CPU、記憶體限制)來提升容器(Container)的效能。以下是對這些主題的更詳細說明:

確保映像檔的安全

映像檔是 Docker 容器運行的基礎,因此保障其安全性對於整體容器環境的安全至關重要。以下是一些關鍵步驟:

  1. 使用信譽良好的映像檔來源:只從可靠且受信任的來源(如 Docker Hub 的官方映像檔)下載映像檔。避免使用未經過驗證的第三方映像檔。

  2. 映像檔安全掃描:使用工具(如 Clair、Trivy)來掃描映像檔,檢查潛在的安全漏洞和不安全的配置。

  3. 定期更新映像檔:定期更新映像檔,以確保含有最新安全補丁和更新。

  4. 最小化映像檔大小:建立映像檔時,只包含必要的應用程式和依賴,以減少潛在的攻擊面。

  5. 映像檔簽名與驗證:使用 Docker Content Trust(DCT)等機制來簽名和驗證映像檔,以確保映像檔的完整性和來源的可靠性。

使用資源限制來提升容器效能

在 Docker 中,合理配置資源限制(如 CPU、記憶體)可以有效提升容器的效能和穩定性。以下是配置資源限制的關鍵考量:

  1. CPU 限制:可以透過 --cpus 參數指定容器可以使用的 CPU 核心數量。這有助於避免單個容器佔用過多的 CPU 資源,從而影響其他容器的效能。

  2. 記憶體限制:使用 --memory 參數來限制容器可以使用的記憶體量。這有助於防止單個容器消耗過多記憶體資源,導致系統不穩定。

  3. I/O 限制:配置 I/O 限制可以控制容器對磁碟的讀寫速度,這有助於平衡多個容器對 I/O 資源的使用,確保系統效能。

  4. 網路頻寬限制:透過 --network 參數設定網路頻寬的限制,以避免單個容器佔用過多的網路資源。

通過以上的配置和策略,可以大幅提高 Docker 容器的安全性和效能。這些措施不僅保護了容器本身,也保護了整個容器運行環境的穩定性和效能。