這可能是一個突然的問題,但是您是否隨意編寫了 Dockerfile?
只需一點點聰明才智,您就可以使您的程式碼更輕巧、更易讀,因此這裡有一些技巧可以幫助您。
本文是手寫。
Docker 的多階段建置可讓您將最終映像拆分為用於建置和執行的映像,從而使最終映像緊湊。
讓我們以實際建立go
容器為例,看看它能帶來什麼好處。
初學者的 Dockerfile
FROM golang:1.25
WORKDIR /app
COPY . .
RUN go build -o myapp .
CMD ["./myapp"]
專業的 Dockerfile
# Stage 1: Build
FROM golang:1.25 AS builder
WORKDIR /app
COPY . .
RUN go build -o myapp .
# Stage 2: Run
FROM alpine:3.22.1
WORKDIR /app
COPY --from=builder /app/myapp .
CMD ["./myapp"]
讓我們實際建立上面的兩個文件,看看它們的大小差異有多大。首先,使用main.go
和go.mod
建立一個 Go 應用程式。
主機程式
package main
import "fmt"
func main() {
fmt.Println("Hello, Docker!")
}
go.mod
module myapp
go 1.21
建構每個
docker build -f Dockerfile.junior -t myapp-junior .
docker build -f Dockerfile.senior -t myapp-senior .
實際建構並進行比較後,差異竟高達80倍。這是在小型配置下完成的,所以差異大概就是這樣,但如果大量使用的話,差異似乎會更大。
isoda@shota-mac junior % docker images | grep myapp
myapp-junior latest f1c396cf8580 41 seconds ago 888MB
myapp-senior latest eab45bab740d About a minute ago 10.8MB
如果您忽略了這一點,今天可以執行的建置明天可能就無法執行了。
NG
FROM golang:latest
即使今天使用上述方法建立成功,但如果明天更新最新版本會怎麼樣?
建置可能會突然失敗。
好的一個例子
FROM golang:1.25-alpine
要點如下:
明確指定特定的 LTS 版本
盡可能使用輕量級影像(例如 alpine 或 bullseye-slim)
指定版本有助於防止意外問題,也有助於減少鏡像大小。鏡像大小可以減少約四倍。
isoda@shota-mac junior % docker image ls | grep golang
golang latest d7e6adee7899 7 days ago 855MB
golang 1.25-alpine 6ea50bc9f564 7 days ago 211MB
接下來的一點是盡可能減少層數。這樣做有以下好處:
影像尺寸縮小(不留下不必要的文件)
提高快取效率(減少重建時間)
更快的分發和部署(更少的層意味著更快的推送/拉取)
NG
FROM debian:bullseye
RUN apt-get -y update
RUN apt-get install -y python
好的一個例子
FROM debian:bullseye
RUN apt-get -y update && apt-get install -y python && rm -rf /var/lib/apt/lists/*
在這個例子中,我們沒有看到映像大小有任何減少,但對於較大的 Dockerfile 來說,差異將是顯著的。
isoda@shota-mac junior % docker images | grep myapp
myapp-junior latest c30825b58d07 19 seconds ago 216MB
myapp-senior latest 818501d91809 34 seconds ago 198MB
.dockerignore
這允許您以類似於.gitignore
的方式指定不應包含在圖像中的檔案。
例如,如果您有以下 Dockerfile:
COPY . /app
如果您的目錄包含以下不必要的檔案該怎麼辦?
您可以透過在.dockerignore
中列出這些不必要的檔案來節省空間。
venv/
.git/
logs
node_modules
...etc
編寫.dockerignore
很簡單。只需在專案根目錄中建立一個名為.dockerignore
的文件,並列出不需要的文件。
node_modules
.git
*.log
Dockerfile
...etc
*如果您在建置時指定如下所示的選項,您可以檢查實際發送的文件,因此請嘗試一下。
docker build . --no-cache --progress=plain
以下是四個需要牢記的 Docker 安全最佳實踐:
使用可靠且正確的基礎鏡像來減輕重量
使用多階段建置
影像定期重建
檢查鏡像漏洞
我們將詳細解釋每一個。
首先,使用可信賴的基礎影像非常重要。
Docker Hub 上有大量可用的映像,但建議使用Official Image
或Verified Publisher
。
Docker 官方映像有以下標記:
此外,盡可能嘗試使用最小的影像( alpine
或slim
)來減少攻擊面和漏洞。
如上所述,透過利用多階段建置,您可以確保最終圖像中不包含不必要的工具和檔案。
這有助於避免不必要工具中的漏洞並減少攻擊面。
例如,如果您繼續使用幾年前建立的映像並且不重建它,即使發現並解決了該映像中使用的軟體中的漏洞,您仍將繼續使用未解決該漏洞的映像。
因此,請定期重建影像,如下所示:
docker build --no-cache -t myImage:myTag myPath/
* 使用--no-cache
將阻止使用快取。 (使用此選項可確保已安裝新檔案。)
定期掃描漏洞並在發現任何漏洞時更新/重建影像也很重要。
最簡單的診斷工具是docker scout
,這是一個官方工具,目前可以免費掃描本地映像。
docker scout cves <image-name>
我實際執行了我建立的圖像並檢查了輸出。 (省略了一些部分)
✓ Image stored for indexing
✓ Indexed 356 packages
✓ Provenance obtained from attestation
✗ Detected 29 vulnerable packages with a total of 106 vulnerabilities
## Overview
│ Analyzed Image
────────────────────┼─────────────────────────────────────────────
Target │ <image-name>:latest
digest │ XXXXXXXXXXXXX
platform │ linux/arm64
provenance │ [email protected]:XXXXXXXXXXXXX/XXXXXXXXXXXXX.git
│ XXXXXXXXXXXXXXXXXXXXXXXXXXX
vulnerabilities │ 0C 1H 3M 102L
size │ 249 MB
packages │ 356
## Packages and Vulnerabilities
0C 1H 0M 11L XXXXXXXXXXXXX XXXXXXXXXXXXX
pkg:deb/debian/XXXXXXXXXXXXX
os_distro=XXXXXXXXXXXXX
✗ HIGH CVE-2025-55154
https://scout.docker.com/v/CVE-2025-55154
Affected range : >=8:7.1.1.43+dfsg1-1
Fixed version : not fixed
--- 略 ---
106 vulnerabilities found in 29 packages
CRITICAL 0
HIGH 1
MEDIUM 3
LOW 102
What's next:
View base image update recommendations → docker scout recommendations XXXXXXXXXXXXX:latest
定期執行這些掃描並解決偵測到的任何漏洞。
這裡介紹的技巧並不難實施,我認為你只要稍加註意就能將它們融入日常開發中。回顧起來,有五件事要考慮:
利用多階段建置→輕量級鏡像並消除不必要的依賴
基礎鏡像始終是固定版本→提高可重複性並防止意外的建置錯誤
更少的層數→提高快取效率、建置速度和映像大小
使用.dockerignore
→ 消除不必要的檔案並實現高效建置
注重安全→選擇可靠的鏡像,定期重建,並檢查漏洞
透過簡單地一點一點地融入這些,您的影像將變得更輕、更快、更安全。
下次編寫 Dockerfile 時,請嘗試其中一個。