【问题标题】:How to rebuild dockerfile quick by using cache?如何使用缓存快速重建 dockerfile?
【发布时间】:2014-03-28 15:55:56
【问题描述】:

我想优化我的 Dockerfile。我希望将缓存文件保存在磁盘中。 但是,我在运行docker build . 时发现它总是尝试从网络中获取每个文件。

我希望在构建期间共享我的缓存目录(例如 /var/cache/yum/x86_64/6)。 但是,它只适用于docker run -v ...

有什么建议吗?(在这个例子中,只安装了 1 个 rpm,在实际情况下,我需要安装数百个 rpm)

我的 Dockerfile 草案

FROM centos:6.4
RUN yum update -y
RUN yum install -y openssh-server
RUN sed -i -e 's:keepcache=0:keepcache=1:' /etc/yum.conf
VOLUME ["/var/cache/yum/x86_64/6"] 
EXPOSE 22

第二次,我想构建一个类似的图像

FROM centos:6.4
RUN yum update -y
RUN yum install -y openssh-server vim

我不想再次从 internat 获取 openssh-server(它很慢)。在我的实际情况下,它不是一个包,大约是 100 个包。

【问题讨论】:

  • 只是为了确保我正确理解了这个问题:如果你运行该 Dockerfile 两次,第二次会很快,对吧?如果没有,您的 Docker 设置可能有问题,因为这应该可以正常工作。但是,如果您的问题是关于“我如何构建多个 Dockerfile 并拥有一个共同的 yum/apt 缓存”,那么情况就不同了 :-)
  • 所提出的问题是特定于 CentOS 的,但对于使用 Debian 及其衍生产品的读者,请参阅 docs.docker.com/examples/apt-cacher-ng
  • 你可以做一个通用的基础镜像,并从 mybaseimage 使用它,但我相信你说的是缓存代理,那是另一回事(例如 apt-cacher,或积极的代理缓存),或者您可以在构建 Dockerfile 之前下载所有包并添加它们。

标签: caching centos docker


【解决方案1】:

对先前答案的更新,当前 docker build 接受 --build-arg 传递环境变量,如 http_proxy 而不将其保存在生成​​的图像中。

例子:

# get squid
docker run --name squid -d --restart=always \
  --publish 3128:3128 \
  --volume /var/spool/squid3 \
  sameersbn/squid:3.3.8-11

# optionally in another terminal run tail on logs
docker exec -it squid tail -f /var/log/squid3/access.log

# get squid ip to use in docker build
SQUID_IP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' squid)

# build your instance
docker build --build-arg http_proxy=http://$SQUID_IP:3128 .

【讨论】:

  • 这个解决方案听起来不错,但它无法缓存我希望它缓存的大 tarball(master.qt.io/archive/qt/5.12/5.12.0/submodules/…,48289352 字节)。每次 docker 运行curl 时,squid 日志都会显示 TCP_MISS/200 并且会发生真正的下载。 squid 的配置中是否有我需要调整的最大文件大小?
  • 找到它:serverfault.com/questions/596890/… 解释了将什么用作 squid 的配置文件(注意 maximum_object_size 应该在 cache_dir 之前),然后可以让 docker 使用该本地配置文件通过在docker run 命令中传递--volume $PWD/squid.conf:/etc/squid3/squid.conf。来自 squid 的奇怪默认值...
【解决方案2】:

只需使用中间/基础图像:

基础 Dockerfile,使用 docker build -t custom-base 或其他东西构建它:

FROM centos:6.4
RUN yum update -y
RUN yum install -y openssh-server vim
RUN sed -i -e 's:keepcache=0:keepcache=1:' /etc/yum.conf

应用程序 Dockerfile:

FROM custom-base
VOLUME ["/var/cache/yum/x86_64/6"] 
EXPOSE 22

【讨论】:

    【解决方案3】:

    您应该使用缓存代理(例如 Http Replicator、squid-deb-proxy ...)或 apt-cacher-ng 用于 Ubuntu 来缓存安装包。我想,你可以把这个软件安装到主机上。

    编辑:

    选项 1 - 缓存 http 代理 - 修改 Dockerfile 的更简单方法:

    > cd ~/your-project
    > git clone https://github.com/gertjanvanzwieten/replicator.git
    > mkdir cache
    > replicator/http-replicator -r ./cache -p 8080 --daemon ./cache/replicator.log  --static   
    

    添加到您的 Dockerfile(在第一个 RUN 行之前):

    ENV http_proxy http://172.17.42.1:8080/
    

    您应该不时清除缓存。

    选项 2 - 缓存透明代理,不修改 Dockerfile:

    > cd ~/your-project
    > curl -o r.zip https://codeload.github.com/zahradil/replicator/zip/transparent-requests
    > unzip r.zip
    > rm r.zip
    > mv replicator-transparent-requests replicator
    > mkdir cache
    > replicator/http-replicator -r ./cache -p 8080 --daemon ./cache/replicator.log --static
    

    您需要以某个用户(非 root!)身份启动复制器。

    设置透明重定向:

    > iptables -t nat -A OUTPUT -p tcp -m owner ! --uid-owner <replicator-user> --dport 80 -j REDIRECT --to-port 8080
    

    禁用重定向:

    > iptables -t nat -D OUTPUT -p tcp -m owner ! --uid-owner <replicator-user> --dport 80 -j REDIRECT --to-port 8080
    

    这种方法最透明通用,不需要修改你的Dockerfile。您应该不时清除缓存。

    【讨论】:

    • 谢谢,这是我想要的,但是,因为发布的图像会被其他人使用。因此,在 docker 镜像中设置代理设置似乎不是完美的解决方案。
    猜你喜欢
    • 1970-01-01
    • 2014-12-03
    • 2023-04-03
    • 2021-05-16
    • 1970-01-01
    • 2019-06-19
    • 1970-01-01
    • 2021-04-06
    相关资源
    最近更新 更多