Building with Docker / Devcontainers
The Betaflight repository includes a preconfigured devcontainer that provides a consistent build environment across all platforms.
Prerequisites
Docker Desktop (Windows/macOS)
- Download and install Docker Desktop:
- Ensure Docker is running (check the system tray icon)
Docker Engine (Linux)
Follow the official installation guide for your distribution.
# After installation, add your user to the docker group
sudo usermod -aG docker $USER
# Log out and back in for changes to take effect
Option 1: VS Code with Dev Containers (Recommended)
This provides the best development experience with full IDE integration.
Setup
- Install Visual Studio Code
- Install the Dev Containers extension
- Fork and clone the Betaflight repository:
# Fork betaflight/betaflight on GitHub first, then:git clone https://github.com/YOUR_USERNAME/betaflight.gitcd betaflight
- Open the folder in VS Code
- When prompted "Reopen in Container", click Yes
- Or press
Ctrl+Shift+P→ "Dev Containers: Reopen in Container"
- Or press
VS Code will build the container and open a terminal inside it. This may take a few minutes the first time.
Building Firmware
Once inside the container, use the integrated terminal:
# Build a specific target
make TARGET=SPEEDYBEEF405WING
# Build all targets
make all
# Clean build artifacts
make clean
# See available targets and options
make help
Option 2: Command Line Only
If you prefer not to use VS Code, you can build directly from the command line.
Build the Container Image
cd betaflight
docker build -t betaflight-dev -f .devcontainer/containerfile .devcontainer/
Build Firmware
# Build a specific target
docker run --rm -v ${PWD}:/workspace -w /workspace betaflight-dev make TARGET=SPEEDYBEEF405WING
# Interactive shell for multiple builds
docker run --rm -it -v ${PWD}:/workspace -w /workspace betaflight-dev bash
On Windows PowerShell, use ${PWD} for the current directory. On CMD, use %cd% instead.
Option 3: Podman (Rootless Alternative)
Podman is a rootless, daemonless alternative to Docker.
# Install Podman (see https://podman.io/docs/installation)
# Build the container
podman build -t betaflight-dev -f .devcontainer/containerfile .devcontainer/
# Build firmware
podman run --rm -v ${PWD}:/workspace:Z -w /workspace betaflight-dev make TARGET=SPEEDYBEEF405WING
Hardware Access (Flashing via DFU or UART)
The devcontainer includes dfu-util for flashing over USB DFU and stm32flash for flashing an STM32 through its UART bootloader with a USB-to-serial adapter (FTDI, CP210x, CH340 and similar). The container runs privileged with the host's /dev mounted, so access to these devices is granted by udev rules on the host.
Linux Host
Set up udev rules on your host system for device access:
-
Create
/etc/udev/rules.d/70-betaflight.rules:# STM32 Virtual COM PortSUBSYSTEM=="tty", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="5740", TAG+="uaccess"# STM32 DFUSUBSYSTEM=="usb", ATTR{idVendor}=="0483", ATTR{idProduct}=="df11", TAG+="uaccess"# USB-to-serial adapters for stm32flash (these vendors make only bridge chips, so all products match)# FTDISUBSYSTEM=="tty", ATTRS{idVendor}=="0403", TAG+="uaccess"# Silicon Labs CP210xSUBSYSTEM=="tty", ATTRS{idVendor}=="10c4", TAG+="uaccess"# WCH CH34x / CH343 / CH9102SUBSYSTEM=="tty", ATTRS{idVendor}=="1a86", TAG+="uaccess"# Prolific PL2303SUBSYSTEM=="tty", ATTRS{idVendor}=="067b", TAG+="uaccess"Keep each comment on its own line: udev rejects a rule line that ends in a comment and silently skips that rule.
The file number must stay below 73: systemd applies
uaccessin73-seat-late.rules, so a tag added by a later file is ignored.The rules set no
MODE, so each device keeps the distribution's default (serial portsroot:dialout, orroot:uucpon Arch, mode0660; DFU devicesroot:root, mode0664) anduaccessadds access only for the user logged in at the machine. The container user has the same uid (1000) as the usual first desktop user, so that access carries into the container. On a host without a local login session, for example over SSH,uaccessgrants nothing: run the flashing tool withsudoinside a Docker container (sudo stm32flash,sudo dfu-util). With Podman, add your host user todialout(uucpon Arch) and add--group-add=keep-groupstorunArgsin.devcontainer/devcontainer.json; this covers serial ports only, not DFU. -
Reload udev rules:
sudo udevadm control --reload-rulessudo udevadm trigger -
Unplug and replug your flight controller or USB-to-serial adapter
To flash over UART, wire the adapter to the flight controller's UART1 (TX to RX, RX to TX, GND to GND), hold the BOOT button while powering up so the MCU starts in its bootloader, then run inside the container:
stm32flash -w obj/betaflight_*_SPEEDYBEEF405WING.hex -v -g 0x0 /dev/ttyUSB0
Replace SPEEDYBEEF405WING with the target you built, and /dev/ttyUSB0 with your adapter's port (ls /dev/ttyUSB* shows it).
Windows Host
DFU flashing from within the container on Windows requires additional setup. It's recommended to:
- Build in the container
- Flash using Betaflight Configurator on your Windows host
Troubleshooting
Container Build Fails
Ensure Docker has enough resources allocated:
- Memory: At least 4GB (8GB recommended for H7 targets)
- Disk: At least 10GB free space
Permission Denied Errors
On Linux, ensure your user is in the docker group:
sudo usermod -aG docker $USER
# Log out and back in
Slow Builds on Windows/macOS
Docker on Windows and macOS runs in a VM, which can slow file operations. For better performance:
- Clone the repository inside the container's filesystem
- Ensure Docker Desktop is using the WSL2 backend (default on modern installations)
Further Reading
- Devcontainer README - Detailed devcontainer documentation
- Development Container Specification - Official devcontainer spec