# Caching apt-get packages

**URL:** <https://discuss.circleci.com/t/caching-apt-get-packages/9076>\
**Category:** Community\
**Tags:** caching, apt, performance\
**Created:** [December 23, 2016, 12:54pm UTC](https://discuss.circleci.com/t/caching-apt-get-packages/9076 "2016-12-23T12:54:35Z")\
**Posts on this page:** 4\
**Page:** 1

<div class="post-metadata">

**Author:** ![zzak](https://sea2.discourse-cdn.com/circleci/user_avatar/discuss.circleci.com/zzak/32/4233_2.png) [@zzak](https://discuss.circleci.com/u/zzak)\
**Post date:** [December 23, 2016, 12:54pm UTC](https://discuss.circleci.com/t/caching-apt-get-packages/9076/1 "2016-12-23T12:54:35Z")

</div>

Many [of you](https://discuss.circleci.com/t/add-ability-to-cache-apt-get-programs/598) have [asked about](https://discuss.circleci.com/t/caching-apt-get-install-results/563) caching apt-get installs.

I’m here to tell you that there’s a way!

Basically it involves downloading the apt packages and caching that directory between builds.

Additionally, I will show you how to use a custom `sources.list` to speed up `apt-get update` for your builds.

## A full example

We’ll start out with a full, commented, example and then walk through the what and why after.

```yaml
dependencies:
  cache_directories:
    # We will store packages in this directory
    - "vendor/apt"

  pre:
    # Remove the repositories provided in base image we don't need
    - sudo mv /etc/apt/sources.list.d /etc/apt/sources.list.d.save
    - sudo mkdir /etc/apt/sources.list.d

    # Copy the repository list from source tree to replace default
    - sudo cp sources.list /etc/apt/sources.list
    # Update to take effect sources repository database
    - sudo apt-get update

    # Make the cache dir if it doesn't exist
    - |
      if ! [[-d vendor/apt]]; then
        mkdir -p vendor/apt
      fi

    # Install aspell if it doesn't exist
    - |
      if [[! -e /usr/bin/aspell]]; then
        # First check for archives cache
        if ! [[-d vendor/apt/archives]]; then
          # It doesn't so download the packages
          sudo apt-get install --download-only aspell
          # Then move them to our cache directory
          sudo cp -R /var/cache/apt vendor/
          # Making sure our user has ownership, in order to cache
          sudo chown -R ubuntu:ubuntu vendor/apt
        fi

        # Install all packages in the cache
        sudo dpkg -i vendor/apt/archives/*.deb
      fi

  # Just echo something to avoid inference
  override:
    - echo "Nothing to do here."

# Another echo, so the build will succeed
test:
  override:
    - echo "Hello, world"

```

And here’s the `sources.list` file we’ve added to the project:

```auto
deb http://us-east-1.ec2.archive.ubuntu.com/ubuntu trusty main restricted
deb-src http://us-east-1.ec2.archive.ubuntu.com/ubuntu trusty main restricted

deb http://us-east-1.ec2.archive.ubuntu.com/ubuntu trusty-updates main restricted
deb-src http://us-east-1.ec2.archive.ubuntu.com/ubuntu trusty-updates main restricted

deb http://security.ubuntu.com/ubuntu trusty-security main
deb-src http://security.ubuntu.com/ubuntu trusty-security main

```

## The what and why

Now let’s explain what’s going on here.

So you have a better understanding before you put it to use.

### Sources

By default, our Ubuntu linux images contain a number of extra package sources to install common libraries and programs; for example mysql or postgres.

This means if you run `apt-get update` in your build you will also have to fetch and update these extra sources as well, which can add extra time to your build.

In this example, we’ve overridden the default sources to only the ones we care about – core packages from Ubuntu and security.

When using this approach, be sure to know which packages you need and where they come from.

You may have to modify the `sources.list` file above depending on your needs.

### Caching

This strategy makes use of the [“cache\_directories” option of the configuration](https://circleci.com/docs/configuration/#cache-directories) to keep a copy of the packages between builds in order to save time downloading them each build.

In order to cache them properly we have to ensure permissions are properly set to the `ubuntu` user within the cache directory.

The last part `sudo dpkg -i vendor/apt/archives/*.deb` should Just Work – but depending on your needs may require some tweaking.

For a small number of dependencies this strategy works perfectly, with that said Your Mileage May Very.

---

<div class="post-metadata">

**Author:** ![stevenspiel](https://sea2.discourse-cdn.com/circleci/user_avatar/discuss.circleci.com/stevenspiel/32/13729_2.png) [@stevenspiel](https://discuss.circleci.com/u/stevenspiel)\
**Post date:** [July 3, 2017, 7:22pm UTC](https://discuss.circleci.com/t/caching-apt-get-packages/9076/2 "2017-07-03T19:22:42Z")

</div>

Will this work with 2.0?

---

<div class="post-metadata">

**Author:** ![zzak](https://sea2.discourse-cdn.com/circleci/user_avatar/discuss.circleci.com/zzak/32/4233_2.png) [@zzak](https://discuss.circleci.com/u/zzak)\
**Post date:** [December 7, 2017, 5:56am UTC](https://discuss.circleci.com/t/caching-apt-get-packages/9076/3 "2017-12-07T05:56:16Z")

</div>

This guide was targeted at 1.0.

If you’re using 2.0, we highly recommend you [roll your own image](https://circleci.com/docs/2.0/custom-images/) including the `apt` packages you need pre-installed.

---

<div class="post-metadata">

**Author:** ![system](https://global.discourse-cdn.com/circleci/original/3X/5/1/511608acda8e85906e15909b57bd0a46c1dbe291.png) [@system](https://discuss.circleci.com/u/system)\
**Post date:** [June 18, 2018, 11:42am UTC](https://discuss.circleci.com/t/caching-apt-get-packages/9076/4 "2018-06-18T11:42:11Z")

</div>


