介紹

在微服務和雲端運算的時代,Docker 已經成為應用程式開發和部署中不可或缺的工具。容器化允許開發人員將應用程式及其依賴項打包成一個可攜式單位,確保可預測性、可擴展性和快速部署。然而,容器的效率在很大程度上取決於您的 Dockerfile 是如何優化編寫的。

在本文中,我們將探討創建 Dockerfile 的最佳實踐,幫助您構建輕量級、快速且安全的容器。

Dockerfile 基礎

什么是 Dockerfile?

Dockerfile 是一個文本文件,包含一組指令以組裝 Docker 映像。每條指令執行特定的操作,例如安裝套件、複製文件或定義啟動命令。正確使用 Dockerfile 指令對於構建高效的容器至關重要。

主要 Dockerfile 指令

  • FROM:設置新映像的基本映像。
  • RUN:在當前映像之上執行命令並提交結果形成新層。
  • CMD:指定容器啟動時運行的默認命令。
  • COPY:將文件和目錄從構建上下文複製到容器文件系統。
  • ADD:類似於 COPY,但具有提取檔案的附加功能。
  • ENV:設置環境變量。
  • EXPOSE:告訴 Docker 容器在運行時監聽哪些端口。
  • ENTRYPOINT:配置容器作為可執行文件運行。
  • VOLUME:為外部存儲卷創建掛載點。
  • WORKDIR:設置後續指令的工作目錄。

撰寫 Dockerfile 的最佳實踐

使用最小的基本映像

基本映像是您 Docker 映像的基礎。選擇輕量級的基本映像可以大幅減少最終映像的大小並最小化攻擊面。

  • Alpine Linux:一個流行的最小映像,約為 5 MB 大小。

    FROM alpine:latest

    優點:小型、安全、下載快速。
    缺點:可能需要額外配置;某些套件可能缺失或因使用 musl 而行為不同於 glibc。

  • Scratch:一個空映像,適合可以編譯靜態二進位檔的語言(如 Go、Rust)。

    FROM scratch
    COPY myapp /myapp
    CMD ["/myapp"]

減少層數

每條 RUNCOPYADD 指令都會為您的映像添加一個新層。合併命令有助於減少層數和整體映像大小。

低效:

RUN apt-get update
RUN apt-get install -y python
RUN apt-get install -y pip

高效:

RUN apt-get update && apt-get install -y \
    python \
    pip \
 && rm -rf /var/lib/apt/lists/*

優化層緩存

Docker 使用層緩存來加速構建。指令的順序會影響緩存的效率。

  • 首先複製依賴文件:在複製其餘源代碼之前,先複製變更頻率較低的文件(如 package.jsonrequirements.txt)。

    COPY package.json .
    RUN npm install
    COPY . .
  • 最小化早期層中的變更:早期層的變更會使所有後續層的緩存失效。

明智地安裝依賴

安裝套件後移除臨時文件和緩存以減少映像大小。

RUN pip install --no-cache-dir -r requirements.txt

小心管理秘密信息

永遠不要在 Dockerfile 中包含敏感數據(密碼、API 金鑰)。

  • 使用環境變量:在運行時使用環境變量傳遞秘密。
  • 利用 Docker Secrets:使用 Docker Swarm 或 Kubernetes 機制來管理秘密。

優化映像大小

  • 刪除不必要的文件:安裝後清理緩存、日誌和臨時文件。

    RUN apt-get clean && rm -rf /var/lib/apt/lists/*
  • 最小化安裝的套件:僅安裝您需要的套件。

    RUN apt-get install -y --no-install-recommends package
  • 使用優化工具:如 Docker Slim 的工具可以自動優化您的映像。

使用 .dockerignore

.dockerignore 文件讓您能排除構建上下文中的文件和目錄,減少發送到 Docker 守護進程的數據量並保護敏感信息。

示範 .dockerignore:

.git
node_modules
Dockerfile
.dockerignore

採用多階段構建

多階段構建允許您使用中間映像並僅將必要的工件複製到最終映像中。

Go 應用程序的示例:

# 構建階段
FROM golang:1.16-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp

# 最終映像
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]

以非根用戶身份運行

為了增強安全性,避免以根用戶身份運行應用程式。

RUN adduser -D appuser
USER appuser

掃描漏洞

  • 使用掃描工具:如 TrivyAnchoreClair 的工具可以幫助識別已知漏洞。
  • 定期更新映像:保持基本映像和依賴項更新。

日誌和監控

  • 直接將日誌發送到 STDOUT/STDERR:這樣可以更容易地收集和分析日誌。
  • 與監控系統集成:使用如 Prometheus 或 ELK 堆疊的工具來監控容器健康狀況。

例子和建議

優化的 Node.js 應用程序 Dockerfile 示例

# 使用基於 Alpine Linux 的官方 Node.js 映像
FROM node:14-alpine

# 設置工作目錄
WORKDIR /app

# 複製套件文件並安裝依賴
COPY package*.json ./
RUN npm ci --only=production

# 複製其餘的應用程式代碼
COPY . .

# 創建非根用戶並切換到該用戶
RUN addgroup appgroup && adduser -S appuser -G appgroup
USER appuser

# 開放應用程式端口
EXPOSE 3000

# 定義運行應用的命令
CMD ["node", "app.js"]

附加建議

  • 固定版本:使用基礎映像和套件的特定版本以確保構建可重現性。

    FROM node:14.17.0-alpine
  • 保持更新:定期更新依賴項和基本映像,以包括安全補丁。

  • 使用元數據:添加 LABEL 指令來提供映像元數據。

    LABEL maintainer="[email protected]"
  • 設置適當的權限:確保文件和目錄擁有適當的權限。

  • 避免以 Root 身份使用:始終切換到非根用戶來運行應用程式。

結論

創建高效的 Docker 映像既是一門藝術,也是一門科學。通過遵循編寫 Dockerfile 的最佳實踐,您可以顯著改善容器的性能、安全性和可管理性。持續更新您的知識,並隨時了解容器化生態系統中的新工具和方法。記住,優化是一個持續過程,總有改進的空間。


原文出處:https://dev.to/idsulik/dockerfile-best-practices-how-to-create-efficient-containers-4p8o

按讚的人:

共有 0 則留言