Why I Started Using This Tool

If you've ever heard a colleague say "it works on my machine" you already know the problem. When I started working on embedded C code, my test suite ran perfectly locally but failed the moment a teammate cloned the repo. Different versions of GCC, different system libraries, missing dependencies. It was a mess and i will need to jump in to troubleshoot.

I needed a way to guarantee that everyone on the team was compiling and testing in exactly the same environment. That's when I started using Docker to run my C test suite, and I haven't looked back since.


What It Does

Docker lets you package a complete build environment, compiler, libraries, tools into a lightweight, portable container. Instead of installing GCC, make, and your testing framework directly on your machine (and hoping everyone else's setup matches), you define the environment once in a file called a Dockerfile, and Docker handles the rest.

Think of it like a separate, lightweight computer living inside your computer, except it starts in seconds, is free to create and throw away, and behaves identically on every machine it runs on.

Important: Docker is designed for CLI-based workflows. It does not support GUI applications โ€” but for compiling and testing C code, the command line is all you need.

  • Consistency โ€” your test suite runs in the same environment every time, on every machine
  • Isolation โ€” no conflicts with your local toolchain or system libraries
  • Reproducibility โ€” perfect for CI/CD pipelines and onboarding new team members
  • Easy reset โ€” delete a container and spin up a fresh one in seconds

My Honest Pros & Cons

โœ… What I Love

  • Zero environment conflicts โ€” no more "works on my machine" debugging sessions
  • Great for embedded C code โ€” you can target a specific compiler version that matches your embedded toolchain
  • CI/CD ready โ€” the same Docker setup you use locally can run in GitHub Actions or any other pipeline with no changes
  • Free and open source โ€” Docker Desktop is free for personal and small-team use

โŒ What Could Be Better

  • Initial learning curve โ€” Docker introduces new concepts (images, containers, volumes) that take a little time to understand
  • Not for GUI tools โ€” if your testing workflow relies on a graphical IDE or debugger UI, Docker won't help there directly

Prerequisites

Before getting started, make sure you have the following:


Key Docker Concepts

Before jumping into the steps, here are three concepts you'll use constantly:

Docker Image A Docker image is a snapshot of a complete environment โ€” it includes the operating system, installed tools, and any configuration you define. Think of it as the blueprint. You build it once from a Dockerfile.

Docker Container A container is a running instance of an image. You can spin up as many containers as you like from the same image, and they're completely free to create and use. When you're done, just delete it. Nothing is left behind on your actual machine.

Docker Volume A volume is how you connect your local files to the container. Without a volume, the container is isolated and can't see your C source files. With a volume mount, your local project folder appears inside the container โ€” so you can edit files in VS Code and compile them inside Docker without copying anything manually.


Step-by-Step Setup Guide

1. Write Your Dockerfile

Create a file named Dockerfile in the root of your project. This file defines your build environment.

Here's a minimal example for C development with make and the cmocka unit testing library:

dockerfile

FROM ubuntu:22.04

RUN apt-get update && apt-get install -y \
    gcc \
    make \
    libcmocka-dev \
    && rm -rf /var/lib/apt/lists/*

WORKDIR /project

This tells Docker to:

  • Start from a clean Ubuntu 22.04 base
  • Install GCC, Make, and the cmocka testing library
  • Set /project as the default working directory inside the container

2. Build the Docker Image

Open a terminal in your project root and run:

bash

docker build -t c-test-env .

This reads your Dockerfile and builds an image named c-test-env. You only need to do this once (or whenever you change the Dockerfile).

3. Launch a Container with a Volume Mount

Now run a container from your image, mounting your local project folder into it:

bash

docker run -it --rm -v $(pwd):/project c-test-env

Here's what each flag does:

Flag Meaning
-it Interactive mode โ€” gives you a terminal inside the container
--rm Automatically removes the container when you exit
-v $(pwd):/project Mounts your current local directory into /project inside the container

You'll land inside the container's terminal, with your C source files visible at /project.

For the full list of docker run options, see the official documentation: Running containers โ€” Docker Docs


Running Your Test Suite

Once inside the container, navigate to your project (you should already be in /project if you used the Dockerfile above) and run your Makefile targets:

Clean previous build artifacts:

bash

make clean

This removes any previously compiled object files and binaries, ensuring a fresh build.

Build the project:

bash

make build

This compiles your C source files and test files using GCC.

Run the tests:

bash

make test

This executes your compiled test binary and prints the results to the terminal โ€” pass/fail for each test case.

A typical session looks like this:

bash

$ docker run -it --rm -v $(pwd):/project c-test-env
root@a1b2c3d4:/project# make clean
rm -f build/*
root@a1b2c3d4:/project# make build
gcc -o build/test_runner src/module.c tests/test_module.c -lcmocka
root@a1b2c3d4:/project# make test
./build/test_runner
[==========] Running 4 test(s).
[ PASSED  ] 4 test(s).

Pricing: Is It Worth It?

Docker Desktop is free for personal use, open-source projects, and small teams (fewer than 250 employees and under $10M in revenue). For larger commercial teams, paid plans start at a few dollars per user per month.

For the workflow in this post, running C tests locally, the free tier covers everything you need.

My take: For embedded C developers, Docker is essentially free infrastructure that saves hours of environment debugging. It's one of the best value tools in the ecosystem.


Final Verdict

If you're writing C code, especially for embedded systems, and you want your tests to run reliably on every machine without fighting toolchain differences, Docker is the answer. The setup takes about 15 minutes the first time, and from that point on, your test environment is locked, portable, and reproducible.

Who should use this: C and embedded software developers who share code across teams, want to add CI/CD pipelines, or have ever lost time debugging environment issues instead of actual bugs.

Who can skip it: Solo developers working on a single machine who never need to share their build environment, though even then, the reproducibility benefits are worth the small setup cost.