freeswitch container from scratch using DIND

In this post, I’m going to demonstrate how to build a docker container from a scratch image that will run FreeSWITCH. I’ve always liked scratch because it’s the most minimal docker image available, and in my mind, that really meshes well with the entire concept of docker containers. But I’ll give a bit of my background with scratch and why I’ve used it.

Scratch is simple with Go

I’ve worked with docker containers as microservices for many years now. And I’ve used go to build 99% of microservices I’ve ever written. Go and docker seem to go hand in hand when building microservices. When building microservices written in go, the most practical docker image is scratch.

Scratch works great for software written in go because go doesn’t have any dependencies on external libraries. You can compile your go code for the target environment and add the binary to your container based on scratch. Depending on the size of your go code, you’ll end up with a container that’s only a few megabytes.

Example:

# compile your go app:
CGO_ENABLED=0 GOOS=linux GOARCH=amd64 go build -o myapp

Dockerfile:

FROM scratch
ADD myapp /
CMD ["/myapp"]

Build your container and run it:

docker build . -t myapp:latest
docker run --rm --name myapp myapp:latest

Not so simple with FreeSWITCH

I’ve talked about how easy it is to use scratch with software written in go. But when you are dealing with software written in C which require external libraries, like FreeSWITCH, it becomes difficult to use the scratch image. The reason for this is, scratch doesn’t come with any libraries at all. This means if you want to use scratch for something like FreeSWITCH, you must include those externally linked libraries in your docker container.

Thankfully, the external libraries FreeSWITCH requires are readily available when you install it on Debian. They will automatically be installed when you use the SignalWire apt-get repo. But finding and adding those external libraries into your docker container isn’t so easy.

I spent a bit of time building FreeSWITCH in a container based on a Debian image. Then I stumbled upon the SignalWire repo which contained a handy script (make_min_archive.sh) to find all the linked libraries FreeSWITCH depends on. I borrowed (and modified) the make_min_archive.sh script quite a bit to fit my needs. Once I was able to build FreeSWITCH in a Debian based container, I wanted to take it a step further and use scratch. I learned about Docker-In-Docker (DinD) at some point along the way.

DinD is a method to use a single Dockerfile to run multiple docker images in order to build a single container. With DinD, I used a Debian 10 image to install FreeSWITCH, run the make_min_archive.sh script to build a binary image which included all linked libraries, then copy the binary over to scratch where everything will run. You end up with a 44M image that runs FreeSWITCH in docker!

The container listed <none> is the DinD container which uses Debian 10. The size of the FreeSWITCH container is significantly smaller.
Dockerfile using DinD

If you’re interested in trying this yourself, I’ve posted my work on github at https://github.com/voipxswitch/freeswitch-docker.