一、解決:構建(docker build)或重新運行容器時,丟失apt-get update問題
在 Docker 容器中,每次構建(docker build
)或重新運行容器時,默認情況下所有更改都會丟失,因為容器是基于鏡像的臨時實例。要保留 apt-get update
和安裝的工具,你需要將這些操作固化到 Docker 鏡像中,而不是在容器運行時執行。以下是幾種方法:
方法 1:在 Dockerfile 中固化更新和安裝
將 apt-get update
和安裝命令寫入 Dockerfile
,這樣每次構建鏡像時都會自動執行這些操作,并保留在鏡像中。
示例 Dockerfile
FROM ubuntu:22.04 # 替換成你的基礎鏡像# 更新 apt 緩存并安裝工具(推薦合并 RUN 以減少層數)
RUN apt-get update && \apt-get install -y \curl \wget \vim \git \&& \rm -rf /var/lib/apt/lists/* # 清理緩存減小鏡像體積# 其他操作...
CMD ["bash"]
構建鏡像
docker build -t my-custom-image .
運行容器
docker run -it my-custom-image
優點:
- 所有更改都會固化到鏡像中,后續運行容器時無需重新安裝。
- 適合長期使用的環境。
方法 2:使用 docker commit
保存臨時更改
如果你已經在運行的容器中執行了 apt-get update
和安裝工具,可以通過 docker commit
將當前容器狀態保存為新鏡像:
# 1. 啟動一個臨時容器
docker run -it ubuntu:22.04 bash# 2. 在容器內執行更新和安裝
apt-get update && apt-get install -y curl wget# 3. 在另一個終端中提交容器為新鏡像
docker ps # 查看容器ID
docker commit <CONTAINER_ID> my-updated-image# 4. 之后可以用新鏡像運行
docker run -it my-updated-image
適用場景:
- 臨時調試后需要保存狀態。
- 不適合生產環境(推薦用 Dockerfile)。
方法 3:掛載卷(Volume)持久化數據
如果某些工具或配置文件需要持久化(如 /var/cache/apt
),可以使用 Docker 卷(Volume):
# 創建卷
docker volume create apt-cache# 運行容器并掛載卷
docker run -it -v apt-cache:/var/cache/apt ubuntu:22.04 bash
適用場景:
- 緩存
apt
數據加速后續安裝(但工具仍需重新安裝)。 - 不適合固化已安裝的工具。
方法 4:使用 docker build --cache-from
重用緩存
如果頻繁構建鏡像,可以利用 Docker 緩存避免重復下載:
# 首次構建(緩存會存儲)
docker build -t my-image .# 后續構建時重用緩存
docker build --cache-from my-image -t my-image .
適用場景:
- 加速構建過程,但不會改變鏡像內容。
最佳實踐總結
場景 | 推薦方法 |
---|---|
固化工具到鏡像 | 在 Dockerfile 中寫 RUN apt-get update && apt-get install |
臨時修改后保存 | docker commit (僅調試用) |
持久化緩存 | 掛載 Volume(如 /var/cache/apt ) |
加速構建 | docker build --cache-from |
關鍵點:
- Docker 容器是無狀態的:所有運行時修改都會在容器停止后丟失。
- 鏡像才是持久化的載體:通過
Dockerfile
或docker commit
將更改保存到鏡像。
如果你的目標是讓容器每次啟動時都自動安裝工具(不推薦),可以在啟動腳本中寫入安裝命令(如 ENTRYPOINT
),但這會顯著增加啟動時間。
二、實戰
要在 Dockerfile 中固化 apt-get update
和安裝工具,同時保持與你的 docker-compose.yaml
兼容,你可以按照以下步驟操作:
1. 創建自定義 Nginx 鏡像的 Dockerfile
在你的項目目錄中創建一個 Dockerfile
,基于 nginx:1.17.6
并添加所需的工具(如 vim
、curl
等):
# 使用你的 Nginx 基礎鏡像
FROM nginx:1.17.6# 更新 apt 緩存并安裝工具(合并 RUN 以減少鏡像層數)
RUN apt-get update && \apt-get install -y \vim \curl \wget \net-tools \ # 包含 ifconfig 等網絡工具&& \rm -rf /var/lib/apt/lists/* # 清理緩存減小鏡像體積# 復制你的 Nginx 配置文件(如果和 docker-compose.yaml 的 volumes 沖突,可注釋掉)
# COPY nginx.conf /etc/nginx/nginx.conf# 聲明容器啟動時執行的命令(可省略,因為基礎鏡像已有 CMD)
# CMD ["nginx", "-g", "daemon off;"]
2. 修改 docker-compose.yaml
使用自定義鏡像
更新 docker-compose.yaml
,將 image: nginx:1.17.6
替換為你構建的自定義鏡像:
version: '3.1'services:nginx:restart: alwayscontainer_name: nginx-basebuild: . # 使用當前目錄的 Dockerfile 構建鏡像# image: nginx:1.17.6 # 注釋掉,改用 buildtty: trueports:- 2500:2500- 3001:3001# ...(其他端口映射保持不變)volumes:- ./nginx.conf:/etc/nginx/nginx.conf- ./log:/var/log/nginx- ./html:/etc/nginx/html- ./cert:/etc/nginx/certnetworks:default:external:name: xph_network
3. 構建并啟動容器
運行以下命令構建自定義鏡像并啟動服務:
docker-compose build # 構建鏡像(僅第一次或 Dockerfile 變更時需要)
docker-compose up -d # 啟動容器
4. 驗證工具是否已安裝
進入容器檢查工具是否生效:
docker exec -it nginx-base bash
# 在容器內測試工具
vim --version
curl --version
關鍵注意事項
-
volumes
會覆蓋鏡像中的文件:- 如果你的
Dockerfile
中有COPY nginx.conf /etc/nginx/nginx.conf
,但docker-compose.yaml
又掛載了./nginx.conf:/etc/nginx/nginx.conf
,則掛載的配置文件會覆蓋鏡像中的文件。 - 如果不需要動態修改配置文件,建議直接在
Dockerfile
中固化配置。
- 如果你的
-
減少鏡像層數:
- 將多個
RUN
命令合并為一個(如示例中用&&
連接),避免生成過多鏡像層。
- 將多個
-
清理緩存:
rm -rf /var/lib/apt/lists/*
可以顯著減小鏡像體積。
-
生產環境建議:
- 如果工具只是調試用,建議通過
docker exec
手動安裝,而不是固化到鏡像中。
- 如果工具只是調試用,建議通過
擴展:多階段構建(如需復雜工具)
如果安裝過程較復雜(如需要編譯),可以使用多階段構建優化鏡像大小:
FROM nginx:1.17.6 as builderRUN apt-get update && \apt-get install -y build-essential && \# 編譯某些工具...rm -rf /var/lib/apt/lists/*FROM nginx:1.17.6COPY --from=builder /usr/local/bin/some-tool /usr/local/bin/
這樣最終鏡像只包含必要的工具,不保留編譯環境。