Docker - Dockerfile



Dockerfile是一個文字檔案,其中包含建立映象所需的所有指令。檔案的第一個條目指定基礎映象,這是一個預先製作的映象,包含應用程式所需的所有依賴項。然後,您可以向Dockerfile傳送命令來安裝附加軟體、複製檔案或執行指令碼。結果是一個Docker映象:一個自包含的可執行檔案,包含執行應用程式所需的所有資訊。

Dockerfile是建立和部署應用程式的一種有效方法。它們有助於以一致且可重複的方式更輕鬆地建立環境。Dockerfile還可以自動化部署過程。

Dockerfile用於建立根據特定需求單獨準備的新自定義映象。例如,Docker映象可以包含特定版本的Web伺服器或資料庫伺服器。

Dockerfile中使用的重要指令

Dockerfile是一個文字檔案,其中包含構建Docker映象的所有不同步驟和指令。Dockerfile中描述的主要元素是基礎映象、所需的依賴項以及在容器中執行應用程式部署的命令。

Dockerfile的基本指令如下所示:

FROM

此指令設定將構建新映象的基礎映象。它通常是Dockerfile中的第一條指令。

FROM ubuntu:22

RUN

這將是一條指令,將在構建過程中執行以在容器內執行命令。它通常可用於安裝應用程式、更新庫或執行常規設定。

RUN apt-get update && apt-get install -y python3

COPY

此指令將檔案和目錄從主機複製到容器映象中。

COPY ./app /app

ADD

類似於COPY,但功能更高階,例如它可以自動解壓縮存檔並從URL獲取檔案。

ADD https://example.com/file.tar.gz /app

WORKDIR

此指令設定工作目錄,Dockerfile中的後續命令將在其中執行。

WORKDIR /app

ENV

此命令中的ENV指令定義容器內的環境變數。

ENV FLASK_APP=main.py

EXPOSE

此選項向Docker定義容器在執行時偵聽已宣告的網路埠。

EXPOSE 8000

CMD

定義正在執行容器的預設值。Dockerfile中只能有一條CMD指令。如果您列出多個CMD,則只有最後一個CMD才會生效。

CMD ["python3", "main.py"]

ENTRYPOINT

此指令允許配置容器以將容器作為可執行檔案執行。

ENTRYPOINT ["python3", "main.py"]

LABEL

此命令提供映象的元資訊,例如維護者、版本或描述的詳細資訊。

LABEL maintainer="johndoe@example.com"

ARG

此命令定義一個變數,允許使用者在構建時使用docker build命令的“--build-arg”標誌將其傳遞給構建器。

ARG version=1 

VOLUME

它只是建立一個掛載點併為其分配給定的名稱,表明它將儲存來自本地主機或其他容器的外部掛載卷。

VOLUME /app/data

USER

此指令允許設定使用者名稱(或UID)以及可選的組(或GID),這些使用者名稱(或UID)和組(或GID)將在執行該映象時以及在Dockerfile中後續的任何RUN、CMD和ENTRYPOINT指令中使用。

USER johndoe

這些可能是Dockerfile中最常用和最重要的指令。但是,指令及其順序當然會根據要容器化的特定應用程式而有所不同。

Dockerfile最佳實踐

精心編寫的Dockerfile對於所有高效且安全的容器化應用程式至關重要。Dockerfile是構建Docker映象的藍圖,它詳細說明了應用程式順利執行所需的執行環境、依賴項和配置。

透過最佳實踐,您可以建立更精簡、更快、更可靠的Docker映象,最終實現開發工作流程的自動化並提高應用程式效率。下面是一套10個基本的Dockerfile最佳實踐:

  • 使用官方基礎映象 - 基於官方Docker Hub映象構建。它們往往是最小化且維護良好的。通常,它們針對安全性和大小進行了最佳化,為自定義映象奠定了堅實的基礎。
  • 使用多階段構建 透過刪除不需要的構建工具和依賴項來減少最終映象的大小。透過這種方式,您可以對構建和執行時環境進行分割槽以達到最佳效率。
  • 最小化層數 - 正如您前面瞭解到的,Dockerfile中的每個指令都會建立一個層。儘可能將任何相互關聯的命令組合到單個RUN指令中。這將有助於減少為任何構建建立的層數,使構建更易於快取。
  • 利用構建快取 - 確保可以更頻繁更改的Dockerfile指令(例如COPY)放在最後。這將使您在稍後階段進行更改時能夠更快地再次構建。
  • 僅安裝必要的包 - 只安裝應用程式中必要的包和依賴項,以減小映象大小並減少可能的漏洞。
  • 使用“.dockerignore” - 要從構建上下文排除不必要的檔案和目錄,請新增“.dockerignore”檔案。這將加快構建速度並防止敏感資訊洩露到您的映象中。
  • 使用非root使用者 - 使用非root使用者執行容器以增強安全性。始終建議在Dockerfile中指定特定使用者和組,從而增加另一層隔離。
  • 映象掃描 - 經常掃描您的Docker映象以查詢漏洞。您可以使用Trivy和Clair等技術來執行此類掃描。始終保持您的基礎映象和依賴項更新,以最大限度地降低潛在風險。
  • 記錄您的Dockerfile - 對Dockerfile進行註釋和解釋,您以後會感謝自己的。這有助於其他人,甚至未來的您,理解構建過程。
  • 固定版本 - 固定基礎映象和依賴項的版本,這可以確保可重複性並避免因更新而導致任何意外問題。

現在,您可以透過使用Dockerfile工作流中的最佳實踐建立健壯且高效的容器化應用程式,從而最佳化容器構建的速度、安全性和可維護性。

Dockerfile - 示例

我們將為一個簡單的Flask Web應用程式編寫一個Dockerfile,該應用程式提供“Hello,World!”訊息 - 特別是,我們將展示如何在建立和執行此應用程式(透過容器)時使用上述幾個指令。

Dockerfile 程式碼

# Use the official Python image as a base
FROM python:3.9-slim-buster

# Set environment variables
ENV PYTHONUNBUFFERED 1
ENV FLASK_APP=app.py
ENV FLASK_RUN_HOST=0.0.0.0

# Set the working directory in the container
WORKDIR /app

# Copy the requirements file and install dependencies
COPY requirements.txt requirements.txt
RUN pip install -r requirements.txt

# Copy the application code into the container
COPY . /app

# Expose port 5000 to the outside world
EXPOSE 5000

# Run the Flask app when the container launches
CMD ["flask", "run"]

程式碼解釋

  • FROM python:3.9-slim-buster - 此行將基礎映象設定為來自Docker Hub的官方Python 3.9 slim-buster映象 - 一個包含必要Python執行時的輕量級映象。
  • ENV PYTHONUNBUFFERED 1 - 設定環境變數並確保不緩衝輸出,這有助於除錯。
  • ENV FLASK_APP=app.py - 這指定了主應用程式檔案。
  • ENV FLASK_RUN_HOST=0.0.0.0 - Flask應用程式將對IP地址0.0.0.0可用。
  • WORKDIR /app - 此行將容器中的工作目錄設定為/app。從這一點開始的每個其他命令都將在該目錄中工作。
  • COPY requirements.txt requirements.txt - 這將requirements.txt檔案從您的本地計算機複製到容器內的/app目錄。
  • RUN pip install -r requirements.txt - 這將安裝requirements.txt檔案中列出的Python包依賴項。
  • COPY . /app - 這將當前目錄(Dockerfile和應用程式程式碼所在的目錄)的全部內容複製到容器內的/app目錄。
  • EXPOSE 5000 - 這告訴Docker容器在執行時偵聽埠5000。
  • CMD ['flask', 'run'] - 這是在容器啟動期間將執行的預設命令。它啟動Flask開發伺服器。

工作原理?

您需要生成一個 `requirements.txt` 檔案,列出 Flask 應用的所有依賴項,例如 Flask 本身。將此 Dockerfile(無需副檔名)另存為名為 `Dockerfile` 的檔案,與您的 Flask 應用程式碼(`app.py`)放在同一目錄下。然後,執行命令 `docker build -t my-flask-app` 建立 Docker 映象。(將 `my-flask-app` 替換為您想賦予映象的名稱)。

最後,使用 `docker run -p 5000:5000 my-flask-app` 執行容器。這將啟動 Flask 應用,您可以在瀏覽器中透過 https://:5000/ 訪問它。這樣,您的應用將在一個可移植且可重複的環境中執行,可以輕鬆地在不同的環境中部署和管理。

結論

總而言之,Docker 改變了我們開發、部署和整體管理應用程式的方式。透過 Docker 實現的容器化幫助開發者在各種不同的環境中實現更高的可移植性、可擴充套件性和一致性。簡單來說,Dockerfile 是容器化的單元;沒有 Dockerfile,就不會存在任何元件和配置。

在本文中,我們學習瞭如何使用已探索的最佳實踐和示例來使 Dockerfile 更有效和更安全。最佳化映象大小,利用構建快取,並遵循安全準則,以便我們的應用程式能夠在任何 Docker 環境中平穩可靠地執行。之後,請記住,掌握 Dockerfile 是釋放 Docker 強大功能並節省大量例行工作的方法。

常見問題

問 1. 什麼是 Dockerfile?為什麼需要它?

Dockerfile 差不多就是一個簡單的包含指令的文字檔案。它提供了一個構建 Docker 映象的藍圖,也就是容器的藍圖。Dockerfile 詳細說明了需要安裝的所有內容,從作業系統基礎到每個其他包依賴項,甚至指定容器啟動時需要執行的命令。

Dockerfile 將使映象建立過程更高效,並確保在多個環境中的一致性和可重複性。

問 2. Dockerfile 中的一些關鍵指令是什麼?

一些重要的指令包括:`FROM` - 定義開始構建的基礎映象;`RUN` - 執行作為映象構建過程一部分的命令,例如軟體安裝;`COPY` - 將檔案或目錄從本地機器複製到映象;`EXPOSE` - 用於宣告容器內應用程式將使用的埠;最後是 `CMD`,它設定容器啟動時要執行的預設命令。

問 3. Dockerfile 中 `COPY` 和 `ADD` 有什麼區別?

`ADD` 命令將檔案新增到 Dockerfile 中的映象。但是,`ADD` 和 `COPY` 之間存在重要區別。`COPY` 是以透明且可預測的方式將檔案或目錄從本地機器傳輸到映象的首選方法。

`ADD` 的一些其他功能包括能夠從遠端 URL 獲取檔案,甚至自動解壓縮壓縮存檔,例如 `.tar` 或 `.zip` 檔案。這使得 `ADD` 看起來更加靈活,但是它在解壓縮方面的奇異行為通常導致 `COPY` 更受青睞,因為它更簡單。

請注意,如果必須下載遠端檔案,則應通常使用 `curl` 或 `wget` 等下載工具將它們分離到不同的 `RUN` 指令中,以減少不必要的映象層。

問 4. 如何最佳化 Dockerfile 以減小映象大小?

較小的映象更有益,因為它們佔用空間更少,傳輸速度更快,啟動速度也更快。最重要的是,為了最小化映象大小,請使用最小的基礎映象,將多個 `RUN` 命令連結在一起以減少中間層的數量,使用多階段構建,丟棄不需要的工件,以及清理構建過程中使用的中間檔案和包。

問 5. Docker 中的多階段構建是什麼?

多階段構建意味著可以使用多個 `FROM` 指令從單個 Dockerfile 中指定。其核心思想是可以在一個階段構建應用程式,其中包含編譯所需的所有工具和依賴項,並在下一個階段僅將需要包含到較小、可用於生產環境的映象中的最終工件複製進去。這樣,最終映象會更小,因為構建環境不是它的一部分,並且部署高效且安全。

廣告