I am working on moving the build for a C++ project into a docker image. The image will be built and pushed by a Jenkins job. Prior to docker, I made heavy use of ccache to speed up my builds on Jenkins, especially in the case of builds where very little changed. The trouble with docker is that the build now runs in an isolated environment, so I can no longer benefit from ccache. Is there a way to build inside of an ephemeral container while still taking advantage of ccache?
It's not essential to develop for Docker, inside Docker. You use a Docker container as your development environment. This is especially useful if you need special software installed in your development environment.
Yes, we can run docker in docker, we'll need to attach the unix socket /var/run/docker. sock on which the docker daemon listens by default as volume to the parent docker using -v /var/run/docker. sock:/var/run/docker.
Docker allows you to run a container in interactive mode. This means you can execute commands inside the container while it is still running. The command prompt will change, moving you to the bash shell as in the example below.
The best way is to put the Dockerfile inside the empty directory and then add only the application and configuration files required for building the docker image. To increase the build's performance, you can exclude files and directories by adding a . dockerignore file to that directory as well.
You can still use ccache in conjunction with your build.
Create a Data Volume to allow data to persist between compilations/builds using the following command:
$ docker create -v /mnt/ccache:/ccache --name ccache debian
Then create your container that “mounts” the data container created above using the --volumes-from
command line option.
$ docker run -e CCACHE_DIR=/ccache --volumes-from ccache -it debian
Now you'll be in the shell of the debian container and can install the required apps and test ccache:
root@15306d02505a:/# apt-get update && apt-get install -y gcc ccache
Now at this point you can check the cache, and it will be empty as expected:
root@15306d02505a:/# ccache -s
cache directory /ccache
cache hit (direct) 0
cache hit (preprocessed) 0
cache miss 0
files in cache 0
cache size 0 Kbytes
max cache size 1.0 Gbytes
The data volume will persist, so even after the container is terminated, the cache is still there. Future builds that mount the volume (and specify the -e ENV variable) will utilize the cache.
Then create a simple app, run it, and check the cache again:
root@15306d02505a:/# cat > foo.c << __EOF__
int main(int argc, char **argv)
{
return 0;
}
__EOF__
root@15306d02505a:/# PATH=/usr/lib/ccache:$PATH gcc -o foo.o -c foo.c
root@15306d02505a:/# ccache -s
cache directory /ccache
cache hit (direct) 1
cache hit (preprocessed) 0
cache miss 1
files in cache 2
cache size 8 Kbytes
max cache size 1.0 Gbytes
You can see the cache is now populated, and further builds will see performance improvements because of it.
The data volume will persist, so even after the container is terminated, the cache is still there. Future builds that mount the volume (and specify the -e ENV
variable) will utilize the cache.
This blog post does a good job of explaining it:
Using Ccache with Docker
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With