gpt4 book ai didi

caching - 下载资源时有哪些策略可以使 Dockerfile 指令缓存失效

转载 作者:行者123 更新时间:2023-12-04 23:20:55 30 4
gpt4 key购买 nike

我们的一些 Docker 镜像需要从负责分发 Java、Node.js、移动(Android 和 iOS)应用程序的 Nexus 服务器或互联网下载更大的二进制文件。例如,使用 ADD 或 RUN 指令进行下载。

RUN curl -o docker https://get.docker.com/builds/Linux/x86_64/docker-latest

考虑到命令“docker build”将根据文件的 mtime 查看指令和缓存,在构建这些图像时利用缓存机制的方法是什么,避免重新下载整个二进制文件? https://stackoverflow.com/a/26612694/433814 .

另一个问题是,如果资源发生变化,Docker 将不会下载最新版本。

最佳答案

解决方案

在使用“RUN curl”或 ADD 下载之前,Docker 不会查看任何缓存机制。它将重复下载步骤。但是,如果文件的 mtime 已更改,Docker 会使缓存失效 https://stackoverflow.com/a/26612694/433814 , 除其他事项外。 https://github.com/docker/docker/blob/master/pkg/tarsum/versioning.go#L84

这是我一直致力于解决这个问题的策略,当构建具有来自文件存储或存储库(例如 Nexus)的依赖项的 Dockerfile 时,Amazon S3 是从资源中检索 ETag,缓存它,并修改缓存的 mdtime -标志文件。 ( https://gist.github.com/marcellodesales/721694c905dc1a2524bc#file-s3update-py-L18 )。它遵循在 Python ( https://stackoverflow.com/a/25307587 )、Node.js ( http://bitjudo.com/blog/2014/03/13/building-efficient-dockerfiles-node-dot-js/ ) 项目中执行的方法。

这是我们可以做的:

  • 获取资源的 ETag 并将其保存在 Dockerfile 之外
  • 在下载之前使用 ADD 指令添加可缓存文件
  • Docker 会检查文件的 mtime 元数据是否使缓存失效。
  • 像往常一样使用 RUN 指令下载内容
  • 如果之前的指令无效,Docker 将重新下载该文件。如果没有,将使用缓存。

  • 这是演示此策略的设置:

    例子
  • 创建一个 Web Server 来处理 HEAD 请求并返回一个 ETag header ,通常由服务器返回。
  • 这模拟了文件的 Nexus 或 S3 存储。
  • 构建镜像并验证依赖层会第一次下载资源
  • 缓存 ETag 的当前值
  • 重建图像并验证依赖层将使用缓存值。
  • 更改 Web 服务器处理程序返回的 ETag 值以模拟更改。
  • 此外,如果文件已更改,则保留更改。在这个原因是...
  • 重建镜像并验证依赖层将失效,触发下载。
  • 再次重建镜像并验证是否使用了缓存。

  • 1. Node.js 服务器

    假设您有以下 Node.js 服务器服务文件。让我们实现一个 HEAD 操作并返回一个值。
    // You'll see the client-side's output on the console when you run it.

    var restify = require('restify');

    // Server
    var server = restify.createServer({
    name: 'myapp',
    version: '1.0.0'
    });

    server.head("/", function (req, res, next) {
    res.writeHead(200, {'Content-Type': 'application/json; charset=utf-8',
    'ETag': '"{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8555}}"'});
    res.end();
    return next();
    });

    server.get("/", function (req, res, next) {
    res.writeHead(200, {'Content-Type': 'application/json; charset=utf-8',
    'ETag': '"{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8555}}"'});
    res.write("The file to be downloaded");
    res.end();
    return next();
    });

    server.listen(80, function () {
    console.log('%s listening at %s', server.name, server.url);
    });

    // Client
    var client = restify.createJsonClient({
    url: 'http://localhost:80',
    version: '~1.0'
    });

    client.head('/', function (err, req, res, obj) {
    if(err) console.log("An error ocurred:", err);
    else console.log('HEAD / returned headers: %j', res.headers);
    });

    执行这个会给你:
    mdesales@ubuntu [11/27/201411:10:49] ~/dev/icode/fuego/interview (feature/supportLogAuditor *) $ node testserver.js 
    myapp listening at http://0.0.0.0:8181
    HEAD / returned headers: {"content-type":"application/json; charset=utf-8",
    "etag":"\"{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8555}}\"",
    "date":"Thu, 27 Nov 2014 19:10:50 GMT","connection":"keep-alive"}

    2.根据ETag值构建镜像

    考虑以下将 ETag header 缓存在文件中的构建脚本。
    #!/bin/sh

    # Delete the existing first, and get the headers of the server to a file "headers.txt"
    # Grep the ETag to a "new-docker.etag" file
    # If the file exists, verify if the ETag has changed and/or move/modify the mtime of the file
    # Proceed with the "docker build" as usual
    rm -f new-docker.etag
    curl -I -D headers.txt http://192.168.248.133:8181/ && \
    grep -o 'ETag[^*]*' headers.txt > new-docker.etag && \
    rm -f headers.txt

    if [ ! -f docker.etag ]; then
    cp new-docker.etag docker.etag
    else
    new=$(cat docker.etag)
    old=$(cat new-docker.etag)
    echo "Old ETag = $old"
    echo "New ETag = $new"
    if [ "$old" != "$new" ]; then
    mv new-docker.etag docker.etag
    touch -t 200001010000.00 docker.etag
    fi
    fi

    docker build -t platform.registry.docker.corp.intuit.net/container/mule:3.4.1 .

    3. 重建和使用缓存

    考虑到我正在使用当前缓存,构建结果如下。
    mdesales@ubuntu [11/27/201411:54:08] ~/dev/github-intuit/docker-images/platform/mule-3.4 (master) $ ./build.sh 
    HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    ETag: "{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8555}}"
    Date: Thu, 27 Nov 2014 19:54:16 GMT
    Connection: keep-alive

    Old ETag = ETag: "{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8555}}"
    New ETag = ETag: "{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8555}}"
    Sending build context to Docker daemon 51.71 kB
    Sending build context to Docker daemon
    Step 0 : FROM core.registry.docker.corp.intuit.net/runtime/java:7
    ---> 3eb1591273f5
    Step 1 : MAINTAINER Marcello_deSales@intuit.com
    ---> Using cache
    ---> 9bb8fff83697
    Step 2 : WORKDIR /opt
    ---> Using cache
    ---> 3e3c96d96fc9
    Step 3 : ADD docker.etag /tmp/docker.etag
    ---> Using cache
    ---> db3f82289475
    Step 4 : RUN cat /tmp/docker.etag
    ---> Using cache
    ---> 0d4147a5f5ee
    Step 5 : RUN curl -o docker https://get.docker.com/builds/Linux/x86_64/docker-latest
    ---> Using cache
    ---> 6bd6e75be322
    Successfully built 6bd6e75be322

    4.模拟ETag变化

    更改服务器上ETag的值并重新启动服务器以模拟新的更新将导致更新缓存标志文件并使缓存失效。例如,Etag 更改为“465fb0d9b9f143ad691c7c3bcf3801b47284f8333”。重建将触发新的下载,因为 ETag 文件已更新,Docker 将在“ADD”指令期间验证这一点。在这里,第 5 步将再次运行。
    mdesales@ubuntu [11/27/201411:54:16] ~/dev/github-intuit/docker-images/platform/mule-3.4 (master) $ ./build.sh 
    HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    ETag: "{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8333}}"
    Date: Thu, 27 Nov 2014 19:54:45 GMT
    Connection: keep-alive

    Old ETag = ETag: "{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8333}}"
    New ETag = ETag: "{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8555}}"
    Sending build context to Docker daemon 50.69 kB
    Sending build context to Docker daemon
    Step 0 : FROM core.registry.docker.corp.intuit.net/runtime/java:7
    ---> 3eb1591273f5
    Step 1 : MAINTAINER Marcello_deSales@intuit.com
    ---> Using cache
    ---> 9bb8fff83697
    Step 2 : WORKDIR /opt
    ---> Using cache
    ---> 3e3c96d96fc9
    Step 3 : ADD docker.etag /tmp/docker.etag
    ---> ac3b200c8cdc
    Removing intermediate container 4cf0040dbc43
    Step 4 : RUN cat /tmp/docker.etag
    ---> Running in 4dd38d30549a
    ETag: "{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8333}}"
    ---> 4fafbeac2180
    Removing intermediate container 4dd38d30549a
    Step 5 : RUN curl -o docker https://get.docker.com/builds/Linux/x86_64/docker-latest
    ---> Running in de920c7a2e28
    % Total % Received % Xferd Average Speed Time Time Time Current
    Dload Upload Total Spent Left Speed
    100 13.5M 100 13.5M 0 0 1361k 0 0:00:10 0:00:10 --:--:-- 2283k
    ---> 95aff324da85
    Removing intermediate container de920c7a2e28
    Successfully built 95aff324da85

    5. 再次重用缓存

    考虑到 ETag 没有改变,缓存标志文件将继续保持不变,Docker 将使用缓存进行超快速构建。
    mdesales@ubuntu [11/27/201411:54:56] ~/dev/github-intuit/docker-images/platform/mule-3.4 (master) $ ./build.sh 
    HTTP/1.1 200 OK
    Content-Type: application/json; charset=utf-8
    ETag: "{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8333}}"
    Date: Thu, 27 Nov 2014 19:54:58 GMT
    Connection: keep-alive

    Old ETag = ETag: "{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8333}}"
    New ETag = ETag: "{SHA1{465fb0d9b9f143ad691c7c3bcf3801b47284f8333}}"
    Sending build context to Docker daemon 51.71 kB
    Sending build context to Docker daemon
    Step 0 : FROM core.registry.docker.corp.intuit.net/runtime/java:7
    ---> 3eb1591273f5
    Step 1 : MAINTAINER Marcello_deSales@intuit.com
    ---> Using cache
    ---> 9bb8fff83697
    Step 2 : WORKDIR /opt
    ---> Using cache
    ---> 3e3c96d96fc9
    Step 3 : ADD docker.etag /tmp/docker.etag
    ---> Using cache
    ---> ac3b200c8cdc
    Step 4 : RUN cat /tmp/docker.etag
    ---> Using cache
    ---> 4fafbeac2180
    Step 5 : RUN curl -o docker https://get.docker.com/builds/Linux/x86_64/docker-latest
    ---> Using cache
    ---> 95aff324da85
    Successfully built 95aff324da85

    该策略已被用于构建 Node.js、Java 和其他 App 服务器或预构建的依赖项。

    关于caching - 下载资源时有哪些策略可以使 Dockerfile 指令缓存失效,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27180538/

    30 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com