这是我的Dockerfile
用于本地开发:
FROM node:12-alpine
WORKDIR /usr/app
ENV __DEV__ 1
COPY package.json ./
COPY yarn.lock ./
RUN yarn --frozen-lockfile
COPY tsconfig.json ./
COPY nodemon.json ./
RUN apk add --no-cache tini
ENTRYPOINT ["/sbin/tini", "--"]
CMD [ "yarn", "dev" ]
我是这样建造它的:
docker build --rm -f Dockerfile.dev --tag my-app .
我是这样运行的:
docker run --rm -it --volume $(pwd)/src:/usr/app/src -p 3000:3000 my-app
我只需要在src
文件夹之外的东西改变时构建它。例如,当我安装节点模块时。我如何让yarn
在某个地方缓存模块,这样它就不会在每次构建时拉取所有模块。
3条答案
按热度按时间yshpjwxd1#
用Docker构建容器的下一代是使用Buildkit,我推荐使用它,特别是因为它对缓存问题有一个优雅的解决方案,目前在普通Docker中确实没有一个好的解决方案;虽然您可以绕过它,但它非常麻烦。
我将在此列出这两种解决方案:
带构建工具包
Tarun's answer是正确的,但有一个更干净的方法。Buildkit支持将挂载指定为缓存。一旦您设置Docker以使用Buildkit,我们需要做的就是:
这将自动拉入上一次运行的缓存,或者在缓存不存在或已过期时创建缓存。
香草 Docker
或者,如果不使用Buildkit,您可以使用vanilla Docker。这里我们能做的最好的事情是使用
COPY
指令复制位于构建上下文中的某种“缓存”。例如,如果我们在构建上下文的根目录中创建一个目录.yarn_cache
,那么我们可以提供一个缓存:此外部缓存在映像构建时不会更新,它需要在映像之外 * 进行初始化和定期更新。* 您可以使用以下shell命令执行此操作(* 在第一次运行时清除任何本地
node_modules
以强制其预热该高速缓存 *):现在,虽然这个工作,它是非常黑客y和一些缺点:
.yarn_cache
目录需要包含在构建上下文中,这可能非常慢,更不用说它必须在每次构建时都这样做,* 即使没有任何更改 *。由于这些原因,前一种解决方案是优选的。
**额外的专业提示:**在上面的任何一种情况下包含Yarn缓存仍然会将其留在最终图像中,从而增加其大小。如果您使用多级构建,您可以缓解此问题:
tuwxkamq2#
您可以使用buildkit实现相同的功能
https://docs.docker.com/develop/develop-images/build_enhancements/
--mount=type=cache in buildkit
Yarn可以缓存在构建过程中下载的包。查看所有可用的选项
https://classic.yarnpkg.com/en/docs/cli/cache/
因此,您将在
dockerfile
中使用类似下面的内容你可以在你的dockerfile中使用一个
ENV
,这样你就不需要一次又一次地重复YARN_CACHE_FOLDER
rsaldnfx3#
Tarun Lalwani和SteveGoob的答案很好,但是他们忽略了一个重要的细节,人们可能会面临何时并行构建许多容器的问题。
在我的例子中,我使用
buildx bake
命令为两个体系结构并行地构建包含许多容器的docker组合文件:如果我按照建议插入
--mount
参数,构建将失败,因为buildx将尝试并行执行几个yarn install
,这会使缓存不一致并完全中断。所以我稍微修改了一下RUN命令。下面是一个新版本:
首先,我决定不创建自己的缓存目录,而是挂载到默认目录。我是如何获得默认目录的呢?
它打印了当前的yarn缓存目录路径,在我的例子中(可能在大多数其他例子中),它将是
/usr/local/share/.cache/yarn/v6
,所以不需要创建任何额外的文件夹并将其作为env变量传递。下一步是在
--mount
中添加sharing=locked
参数,使用这个参数,它将依次等待每个并行安装,第一个(用于第一个容器和第一个架构)将拉取所有的包,将它们保存该高速缓存中,所有接下来的yarn install
将重用该缓存。如果你不喜欢它们互相等待的时候,你可以使用
sharing=private
和一些冗余,这将为每个容器+拱对创建自己的缓存。