我们公司中有一个基于c ++的大型代码,我们正试图转向基于docker的微服务基础架构。
我们内部有几个库,可以帮助我们完成在代码中经常使用的诸如辅助函数和实用程序之类的事情。我们的想法是为已经安装了该库的开发人员创建一个基础映像,并将其用作我们的“基础”映像。这将使我们始终使用最新版本库的所有软件受益。
我的问题与Docker的缓存系统以及CI和外部依赖关系有关。可以说我们有一个像这样的Docker文件:
FROM ubuntu:latest
# Install External dependencys
RUN apt update && apt install -y\
boost-libs \
etc...
# Copy our software
...
# Build it
...
# Install it
...
如果我们的代码更改,我们可以触发CI,并且docker将了解它可以使用在复制我们的软件之前创建的缓存映像。如果我们的外部依赖项之一提供了较新的版本,该怎么办?缓存会自动失效吗?万一我们的任何软件包收到新版本,我们如何触发CI构建?
从本质上讲,我们如何确保始终使用可用于外部依赖项的最新软件包?
请记住,上面的Dockerfile只是一个示例,用来说明我们正在尝试在剧本中使用其他技巧,例如使用更浅的基础映像(而非Ubuntu)和多阶段构建,以避免在生产容器中使用dev-packages。
答案 0 :(得分:0)
Docker的缓存算法非常简单。它查看映像构建的先前状态以及正在运行的命令的字符串。如果执行的是COPY
或ADD
,它还会查看正在复制的那些文件的哈希。如果在服务器上找到具有相同先前状态并正在运行命令的先前版本,它将重新使用缓存。
这意味着外部更改,例如从外部存储库中提取软件包,将不会被检测到,并且缓存将被重用,而不是重新运行该行。我已经看到了两种解决方案:
选项1:通过将版本添加到依赖项来更改命令。当这些依赖关系之一发生变化时,您将需要更新构建。这是一项繁重的工作,但也可以确保仅提取准备就绪的版本。看起来就像(将boost-libs固定为1.5版本号):
# Install External dependencys
RUN apt update && apt install -y\
boost-libs=1.5 \
etc...
选项2:更改构建arg。这些作为环境变量注入到RUN
命令中,并且docker将环境中的变化视为要运行的另一条命令。看起来像:
# Install External dependencys
ARG UNIQUE_VAR
RUN apt update && apt install -y\
boost-libs \
etc...
然后您可以使用以下内容构建以上内容,以触发每天在该行上重新创建缓存:
docker build --build-arg "UNIQUE_VAR=$(date +%Y%m%d)" ...
请注意,您还可以随时选择不使用缓存进行构建:
docker build --no-cache ...
这将导致所有步骤(“ from”行除外)都忽略高速缓存。