考虑以下场景。有一个应用程序依赖库“A”、“B”、“C”来构建和运行,否则会抛出错误。在不知道依赖项“B”和“C”的情况下,创建了一个 Dockerfile,用于构建安装了依赖项“A”的镜像。
应用程序在从图像启动的容器中运行,应用程序无法构建,因为容器缺少依赖项“B”和“C”。
现在如果镜像被销毁并重建,之前下载的依赖项将再次重新下载。一种解决方法是编写一个 Dockerfile 以从现有图像(安装了依赖项“A”)导入,并在其上提及依赖项“B”和“C”的安装。
但这样一来,每次需要添加新的依赖项时,都必须构建一个新的 docker 镜像,该镜像将从旧镜像导入,因此,旧镜像和新镜像都很重要。
我的问题是
- 是否有任何方法可以在不重新下载旧依赖项的情况下继续构建提及新依赖项的镜像?
- 不从旧镜像导入依赖项?
- 并且,无需在 dockerfile 中编写新的“FROM”?
对于这种情况,最干净的解决方案是什么?
最佳答案
<强>1。是否有任何方法可以在不重新下载旧依赖项的情况下继续构建提及新依赖项的图像?
好吧,我经常使用层缓存来优化 Dockerfile。每当您在 Dockerfile 中写下命令时,它都会创建一个新层。在两次构建之间,docker 自上而下比较 Dockerfile 的命令,并从检测到命令更改的位置进行重建。所以我经常将稳定层(如依赖项、环境设置)放在 dockerfile 的顶部。否则像 EXPOSE Port 或 CMD 这样的层我经常改变所以我把它们放在文件的底部。通过这样做,无论何时重建图像,它都可以节省大量时间。
您还可以使用多阶段构建。但我不经常使用它,所以你可以在这里查看:https://docs.docker.com/develop/develop-images/multistage-build/
<强>2。不保留旧图像并将其导入新图像?
有时当我想重新安装所有东西时,我只是重建图像使用选项 --no-cache。**
docker build --no-cache=true .
<强>3。无需在 dockerfile 中编写新的“FROM”
有时我会使用像 linux alpine 这样的基础镜像,并从头开始安装我需要的所有东西,这样我的镜像就会有更小的尺寸,并且不包含我不需要的东西。 FROM 只是从 Dockerhub 中拉取以某种方式创建的图像。
例如镜像 nginx-alpine 的 Dockerfile: https://github.com/nginxinc/docker-nginx/blob/2ef3fa66f2a434cd5e44e35a02f4ac502cf50808/mainline/alpine/Dockerfile
您可以查看 alpine linux 以获取更多详细信息:https://alpinelinux.org/
关于docker - 更新Dockerfile中的依赖并创建镜像,无需重新下载前面提到的依赖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62651863/