Docker in Docker: Simplifying Altis code development

From the beginning, Altis has tried to make local development workflows simple and powerful. From the very first version, we shipped two full local development environments: one based off the Chassis WordPress project, and a new Docker-based Local Server modeled after the Altis Cloud infrastructure and containers.

Building environments for developers is difficult, as there is often a trade-off between an opinionated environment, simplicity and flexibility. Developers are highly advanced computer users, so while we don’t want complicated and arduous development workflows we want to be able to tailor everything to suite own preferences. A large part of the decision to support two development workflows was to allow for two opinionated approaches, and let developers choose based off their preference.

I am interested in how we can make it easier, faster and more accessible to contribute to Altis projects. So, I set about seeing how I could simplify our development setup, accepting that this is one way to make things simpler for someone to try Altis, run a demo or tweak some code.


At the time of writing, to use Altis Local Server, the user must have Docker, PHP 7.2+ (with a bunch of specific extensions) and Composer installed at a minimum. From there, they just need to run composer create-project altis/skeleton my-app to be up and running. It’s more than likely that we’ll also want Git, a decent shell and Node+NPM at appropriate versions for many common workflows.

While brainstorming creative ways to improve the known “Slow shared volumes on Docker for Mac” limitation, I ended up coming up with new “inside out” approach to my Altis development environment. A long standing pain-point on many local environments – whether VMWare, VirtualBox or Docker – is shared volumes with the host machine. In Altis or WordPress codebases it’s not unusual to have 60,000+ files in a single project, and a single page render is likely to have many hundreds of disk read operations. Local Server page generation times can be between 1 and 2 seconds because of the filesystem lag.

Rather than storing the codebase on the macOS host, and sharing it in to the Docker containers, I wondered about instead discarding shared volumes and keeping the project files inside the container. Coupled with VS Code’s neat ability to develop inside a container, I might be able to do away with the idea of needing to share anything with the host machine.

Some more mulling things over, and I realized I could still just run all the Local Server stack in my development container (as it turns out running Docker-in-Docker is a thing). I’d benefit from the project files still being within the Docker for Mac Virtual Machine, so shouldn’t cause any performance penalties. Docker-in-Docker also has virtually no overhead, as there’s still really only one Docker runtime and layer of abstraction.

I put together a minimal Dockerfile based off Debian with all the Altis Local Server dependencies, and voila! page loading times of 0.2+ seconds (down from 1.5 seconds average). Not only does this provide me with a faster development environment, it makes my development environment much more portable and reproducible. I can also run it in the cloud on a number of providers if I need more processing power or, say, want to code on an iPad.

Once my development container is running, VS Code has the ability to attach to the running container, providing me with the full project and integrated terminal.

More importantly, this means anyone else can also use my development environment setup. docker run -itp --privileged 443:443 joehoyle/altis-ide /bin/bash is now all you need to start building with Altis.

This image has an empty alt attribute; its file name is Screenshot-2020-11-16-at-8.38.38-PM.png

Looping back to the start of this post, this shouldn’t be the way to do Altis development but it can a way. A highly opinionated, all configured, decisions-made-for-you way.