从图像的特定层构建docker图像

时间:2019-01-29 03:00:58

标签: docker

我想要的

我有一个不再构建的Dockerfile,因为它的某些初始构建步骤依赖于不再可用的服务,因此进行反向工程很痛苦。整个过程很快就会被重写,但是现在我只想使用包含问题步骤的图层中的修复程序来重建图像。

我的Dockerfile看起来像这样:

FROM ubuntu:14.04
RUN this_thing_that_breaks
RUN apt-get install etc
COPY blah

我本质上想将第3层用作基础层,并在此基础上构建。

我做了什么

  1. 从回购中提取工作图像:docker pull ecr/my-image:cache
  2. docker build --cache-from ecr/my-image:cache -t ecr/my-image:fix .

目前,我希望自己的构建使用:cache的现有层来构建:fix,但是我的构建从头开始,但失败了。

This layer explanation post似乎说1.10之后,docker镜像将其所有层作为一个整体运送出去,这些层实际上不再可访问。
但是,当我查看docker inspect ecr/my-image:cache时,会看到一大堆图层的sha256 ID。再次让我觉得应该有一种方法可以指向一个特定的层,并将其用作缓存的基础。

是否可以通过给出层的sha256 id列表来构建docker映像?

修复后,我打算对此进行核对,因此在这里不需要优雅。

其他信息

$ docker version
Version:           18.09.1
API version:       1.39
OS/Arch:           darwin/amd64

$ sw_vers
ProductName:    Mac OS X
ProductVersion: 10.14.1

2 个答案:

答案 0 :(得分:1)

要将某个图像的特定图层用作其他图像的基础,可以在public class CacheService { private readonly IDatabase cache; private static readonly string connectionString = ConfigurationManager.AppSettings["RedisConnection"]; private static LoadedLuaScript ruleLuaScript; public CacheService() { this.cache = Connection.GetDatabase(); ruleLuaScript = LoadLuaScriptForGetRule(@"Lua/getMultiHashWithParameter.lua"); } private static Lazy<ConnectionMultiplexer> lazyConnection = new Lazy<ConnectionMultiplexer>(() => { return ConnectionMultiplexer.Connect(connectionString); }); public static ConnectionMultiplexer Connection { get { return lazyConnection.Value; } } private LoadedLuaScript LoadLuaScriptForGetRule(string scriptUrl) { string script = File.ReadAllText(scriptUrl); LuaScript luaScript = LuaScript.Prepare(script); var endpoints = Connection.GetEndPoints(); var endpoint = endpoints[0]; IServer server = Connection.GetServer(endpoint); return luaScript.Load(server); } public void PrepareLuaScript(dynamic parameters) { RedisResult result = this.cache.ScriptEvaluate(ruleLuaScript, parameters); if (!result.IsNull) { //how to read result? } } } 指令中直接使用该图层的SHA256哈希。

例如,假设您有这个Dockerfile

FROM

,并且已经从该Dockerfile成功构建了映像(当时FROM ubuntu:14.04 RUN this_thing_that_breaks RUN apt-get install etc COPY blah 工作正常)。 this_thing_that_breaks最近停止工作,我们现在无法建立图片。

说,已构建的图像被标记为RUN this_thing_that_breaks。要找到要断开的确切图层的SHA256 ID,请运行my-image:cache并记下SHA256 ID(此处与docker history my-image:cache对应的ID)。

说记录下来的SHA256 ID是RUN this_thing_that_breaks。现在,删除066a73a3a0c4之前的所有说明,并将其替换为RUN this_thing_that_breaks

FROM 066a73a3a0c4

现在,使用FROM 066a73a3a0c4 RUN apt-get install etc COPY blah 构建新映像my-image:fix。现在,这应该使用已缓存为创建新图像的基础图像的特定中断层。

希望这会有所帮助!

上一个答案:

不使用缓存的原因可能是docker build --cache-from my-image:cache -t my-image:fix .中的ubuntu:14.04图像和本地缓存的ecr/my-image:cache图像与此处描述的不一样:

https://github.com/moby/moby/issues/26065#issuecomment-249046559

  

如果ubuntu:14.04映像发生更改,则不会重用缓存。这是有用的,实际上很重要,因为否则用户将无法检测到基本映像中存在重要的安全修复程序,因为他们始终使用缓存。但这也可能使某些用户感到惊讶。我认为我们不应该尝试通过破解来解决此问题,而是如果某些用户想要不同的行为,他们应该只使用不可变的标签或摘要作为FROM图像。

因此,我看到的一个选择是使用FROM删除本地缓存的ubuntu:14.04,然后运行docker rmi ubuntu:14.04

我希望这能奏效,但我尚未确认。如果这样做不起作用,建议您检查this issue并检查其中提到的选项。

答案 1 :(得分:0)

这种情况下的问题是void listBox1_MouseMove(object sender, MouseEventArgs e) { if (e.Button == MouseButtons.Left && listBox1.SelectedItems.Count > 0) { int mouseIndex = listBox1.IndexFromPoint(e.Location); if (mouseIndex > -1) { ListBox.SelectedObjectCollection x = new ListBox.SelectedObjectCollection(listBox1); if (Control.ModifierKeys == Keys.Shift) { int i1 = Math.Min(listBox1.SelectedIndex, mouseIndex); int i2 = Math.Max(listBox1.SelectedIndex, mouseIndex); for (int i = i1; i <= i2; ++i) { x.Add(listBox1.Items[i]); } } else { x = listBox1.SelectedItems; } var dropResult = DoDragDrop(x, DragDropEffects.Move); } } } docker build Certificate Usage Scenarios for the WCF Send Ports

该图像最初是使用docker-compose build构建的,而我使用的是直接使用的docker。 使用docker-compose时,按预期使用缓存层。

虽然这不能回答如何从某些特定图层构建图像的问题,但确实清除了我的障碍。