Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you cache Yarn Dependencies for a Docker image build in CircleCI?

My yarn installs take ~5 minutes right now. I'm trying to figure out a way to cut them down.

Right now in my Dockerfile I have the following:

COPY package.json yarn.lock node_modules /usr/src/app/
COPY ${YARN_CACHE} /root/.cache/yarn/
WORKDIR /usr/src/app

# We are doing this so that we can make use of layer caching 
# (i.e. most likely yarn deps won't change as often as the app code)
COPY . /usr/src/app

# yarn install
RUN yarn install

And in my circle file I have

  - restore_cache:
     keys:
       # only restores cache if the yarn file is the same
       - yarn-packages-v4-{{ checksum "yarn.lock" }}
  - run: docker pull "xxx.dkr.ecr.us-east-1.amazonaws.com/website:latest"
  - run: docker build --build-arg NODE_ENV=production --build-arg YARN_CACHE=$(yarn cache dir) --force-rm -t xxx.dkr.ecr.us-east-1.amazonaws.com/website:build-${CIRCLE_BUILD_NUM} .

However my yarn install still takes 5 minutes. Am I doing something wrong?

like image 584
Toli Avatar asked Oct 05 '18 22:10

Toli


People also ask

How does CircleCI caching work?

Caching is one of the most effective ways to make jobs faster on CircleCI. By reusing the data from previous jobs, you also reduce the cost of fetch operations. After an initial job run, subsequent instances of the job run faster, as you are not redoing work.

How do you cache yarn?

yarn cache By default, yarn will store every package in your user directory on the file system. To print out every cached package, you need to run yarn cache list on the command line. Running yarn cache list - -pattern <pattern> will print out all the packages that match the pattern provided.

Where are Docker images cached?

In a default install, these are located in /var/lib/docker. During a new build, all of these file structures have to be created and written to disk — this is where Docker stores base images. Once created, the container (and subsequent new ones) will be stored in the folder in this same area.

How does Docker build cache work?

Docker's build-cache is a handy feature. It speeds up Docker builds due to reusing previously created layers. You can use the --no-cache option to disable caching or use a custom Docker build argument to enforce rebuilding from a certain step.


2 Answers

The problem is that the result of yarn cache dir is an external folder, that either doesn't exist in the docker build or is just empty. You've got a couple of options

  • Setup a .yarnrc with "cache-folder" set (see https://yarnpkg.com/lang/en/docs/cli/cache/) make a cache folder inside your build directory, and then run yarn install outside of the Docker run
  • Give unspecified amounts of cash to CircleCI to get Docker layer caching enabled, which will speed up builds where there's no package changes
  • Try one of the other magic options (e.g https://blog.jondh.me.uk/2018/04/strategies-for-docker-layer-caching-in-circleci/) to manually setup caching
like image 115
Tom Parker-Shemilt Avatar answered Oct 11 '22 17:10

Tom Parker-Shemilt


As per Tom's first point, putting this anywhere before RUN yarn install within same Docker build stage can help by caching all yarn cache to volumed directory.

ENV YARN_CACHE_FOLDER=/usr/local/yarn-cache
VOLUME /usr/local/yarn-cache
like image 33
hasnat Avatar answered Oct 11 '22 17:10

hasnat