当前位置: 首页 > news >正文

【Docker】解决:构建(docker build)或重新运行容器时,丢失apt-get update问题

一、解决:构建(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 容器是无状态的:所有运行时修改都会在容器停止后丢失。
  • 镜像才是持久化的载体:通过 Dockerfiledocker commit 将更改保存到镜像。

如果你的目标是让容器每次启动时都自动安装工具(不推荐),可以在启动脚本中写入安装命令(如 ENTRYPOINT),但这会显著增加启动时间。

二、实战

要在 Dockerfile 中固化 apt-get update 和安装工具,同时保持与你的 docker-compose.yaml 兼容,你可以按照以下步骤操作:


1. 创建自定义 Nginx 镜像的 Dockerfile

在你的项目目录中创建一个 Dockerfile,基于 nginx:1.17.6 并添加所需的工具(如 vimcurl 等):

# 使用你的 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

关键注意事项

  1. volumes 会覆盖镜像中的文件

    • 如果你的 Dockerfile 中有 COPY nginx.conf /etc/nginx/nginx.conf,但 docker-compose.yaml 又挂载了 ./nginx.conf:/etc/nginx/nginx.conf,则挂载的配置文件会覆盖镜像中的文件。
    • 如果不需要动态修改配置文件,建议直接在 Dockerfile 中固化配置。
  2. 减少镜像层数

    • 将多个 RUN 命令合并为一个(如示例中用 && 连接),避免生成过多镜像层。
  3. 清理缓存

    • rm -rf /var/lib/apt/lists/* 可以显著减小镜像体积。
  4. 生产环境建议

    • 如果工具只是调试用,建议通过 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/

这样最终镜像只包含必要的工具,不保留编译环境。

相关文章:

  • 【Docker基础】Docker容器管理:docker ps及其参数详解
  • HexHub开发运维利器Database, Docker, SSH, SFTP
  • 数据库外连接详解:方式、差异与关键注意事项
  • 基于fpga的串口控制的音乐播放器
  • Franka 机器人在配置空间距离场实验中的突破性应用:从算法优化到动态场景适配
  • Stable Diffusion 3终极提示词库:2000个工业设计场景生成公式(2025企业级实战指南)
  • html css js网页制作成品——HTML+CSS湘菜网页设计(4页)附源码
  • Ehcache、Caffeine、Spring Cache、Redis、J2Cache、Memcached 和 Guava Cache 的主要区别
  • 自动化保护 AWS ECS Fargate 服务:使用 Prisma Cloud 实现容器安全
  • 无人机防护装置技术解析
  • 5,FreeRTOS中断管理
  • 本地部署 WordPress 博客完整指南(基于 XAMPP)
  • 替代创维GL3213S 读卡DD3118方案3.0国产 GL3224-32 TF/SD卡解码芯片
  • 【开源项目】「安卓原生3D开源渲染引擎」:Sceneform‑EQR
  • 汽车涂胶车间的“通信桥梁”:PROFIBUS DP转ETHERNET/IP网关的应用实践
  • 高防IP在服务器中的作用都有哪些?
  • 微信小程序进度条progress支持渐变色
  • iOS 网络请求断连重试失败?抓包分析丢包原因的完整流程
  • 设计模式精讲 Day 15:解释器模式(Interpreter Pattern)
  • .net8创建tcp服务接收数据通过websocket广播