Why Embedded Development Needs Docker?
Solving Cross-Compilation Environment Issues
- Toolchain Version Conflicts: Different projects require different
gcc-arm-none-eabiversions. - Dependency Management: Avoid system pollution and isolate various libraries.
- Team Collaboration: Ensure all developers use the identical compilation environment.
Rapid Environment Setup
- One-Click Launch: Get a complete embedded development environment in seconds.
- Version Control: Development environments can also be versioned.
- Cross-Platform: Unified development experience on Windows, Linux, and macOS.
Core Concepts
Image
Think of it as a “development environment installer” containing all necessary tools and libraries.
Container
An “instance of your development environment” launched from an image, where you write code and compile programs.
Volume Mounting
“Mounting” your host machine’s code directory into the container, so any code changes are saved synchronously.
Quick Installation
Ubuntu/Debian Installation
# One-line installation script
curl -fsSL https://get.docker.com | sh
# Configure user permissions (to avoid sudo every time)
sudo usermod -aG docker $USER
# Log out and log back in, or run:
newgrp docker
Verify Installation
docker --version
docker run hello-world
Common Commands for Embedded Development
Get Embedded Development Images
# ARM development environment
docker pull arm32v7/gcc
# STM32 development environment
docker pull stm32duino/arduino-core-stm32
# ESP32 development environment
docker pull espressif/idf
# Generic cross-compilation environment
docker pull multiarch/crossbuild
Start a Development Container
# Basic launch (mount current directory)
docker run -it -v $(pwd):/workspace arm32v7/gcc bash
# With port mapping (for debugging servers)
docker run -it -v $(pwd):/workspace -p 3333:3333 arm32v7/gcc bash
# Run container in the background
docker run -d --name my-dev -v $(pwd):/workspace arm32v7/gcc tail -f /dev/null
# Enter a background container
docker exec -it my-dev bash
Common Operations
# View running containers
docker ps
# Stop a container
docker stop my-dev
# Delete a container
docker rm my-dev
# View local images
docker images
Hands-on: STM32 Development Environment
Create an STM32 Development Image
Create Dockerfile.stm32:
FROM ubuntu:20.04
# Prevent interactive installation
ENV DEBIAN_FRONTEND=noninteractive
# Install basic tools
RUN apt-get update && apt-get install -y \
build-essential \
git \
wget \
curl \
unzip \
python3 \
python3-pip
# Install ARM toolchain
RUN apt-get install -y gcc-arm-none-eabi
# Install STM32CubeMX (optional)
RUN apt-get install -y default-jre
# Set working directory
WORKDIR /workspace
# Set entrypoint
CMD ["/bin/bash"]
Build and Use
# Build image
docker build -f Dockerfile.stm32 -t stm32-dev .
# Start development environment
docker run -it -v $(pwd):/workspace stm32-dev
# Compile inside the container
cd /workspace
make clean && make
Hands-on: ESP32 Development Environment
Use Official ESP-IDF Environment
# Pull ESP-IDF image
docker pull espressif/idf:latest
# Start ESP32 development environment
docker run --rm -v $PWD:/project -w /project -it espressif/idf:latest
# Operate inside the container
idf.py build
idf.py flash
Simplify Script
Create esp-dev.sh:
#!/bin/bash
docker run --rm -v $PWD:/project -w /project -it \
--device=/dev/ttyUSB0 \
espressif/idf:latest bash
Usage:
chmod +x esp-dev.sh
./esp-dev.sh
Data Persistence
Mount Project Directory
# Mount current directory to /workspace in the container
docker run -it -v $(pwd):/workspace image_name
# Mount a specific directory
docker run -it -v /home/user/projects:/workspace image_name
# Read-only mount (prevent container from modifying host files)
docker run -it -v $(pwd):/workspace:ro image_name
Data Volumes (for toolchain caching)
# Create a data volume to store compilation cache
docker volume create build-cache
# Use the data volume
docker run -it -v $(pwd):/workspace -v build-cache:/cache image_name
Multi-Project Management
Using Docker Compose
Create docker-compose.yml:
version: '3.8'
services:
stm32-dev:
build:
context: .
dockerfile: Dockerfile.stm32
volumes:
- ./stm32-project:/workspace
working_dir: /workspace
stdin_open: true
tty: true
esp32-dev:
image: espressif/idf:latest
volumes:
- ./esp32-project:/project
working_dir: /project
devices:
- /dev/ttyUSB0:/dev/ttyUSB0
stdin_open: true
tty: true
Usage:
# Start STM32 development environment
docker-compose run stm32-dev
# Start ESP32 development environment
docker-compose run esp32-dev
Handy Tips
Simplify Commands
Add aliases to .bashrc:
# STM32 Development
alias stm32='docker run -it --rm -v $(pwd):/workspace stm32-dev'
# ESP32 Development
alias esp32='docker run -it --rm -v $(pwd):/project -w /project espressif/idf:latest'
# ARM Cross-compilation
alias arm-gcc='docker run -it --rm -v $(pwd):/workspace arm32v7/gcc'
Device Access
# Access USB devices (debugger, programmer)
docker run -it --device=/dev/ttyUSB0 -v $(pwd):/workspace image_name
# Access multiple devices
docker run -it \
--device=/dev/ttyUSB0 \
--device=/dev/ttyACM0 \
-v $(pwd):/workspace image_name
Network Debugging
# Map GDB debug port
docker run -it -p 3333:3333 -v $(pwd):/workspace image_name
# Map Web service port (for online debugging tools)
docker run -it -p 8080:8080 -v $(pwd):/workspace image_name
Common Issues
USB Device Access Permissions
# Add user to dialout group
sudo usermod -aG dialout $USER
# Or temporarily modify device permissions
sudo chmod 666 /dev/ttyUSB0
Slow Compilation Inside Container
# Use compilation cache volume
docker run -it -v build-cache:/tmp -v $(pwd):/workspace image_name
# Limit parallel compilation processes
make -j$(nproc)
Cleaning Up Space
# Clean up stopped containers
docker container prune
# Clean up unused images
docker image prune
# One-command clean up all unused resources
docker system prune
Practical Examples
Embedded Linux Development
# Use cross-compilation environment
docker run -it --rm \
-v $(pwd):/workspace \
-e CROSS_COMPILE=arm-linux-gnueabihf- \
multiarch/crossbuild bash
RTOS Project Compilation
# FreeRTOS Project
docker run -it --rm \
-v $(pwd):/workspace \
-w /workspace \
arm32v7/gcc \
make -f freertos.mk
Summary
Docker’s main value in embedded development:
- Environment Isolation: Different projects use different toolchain versions.
- Rapid Deployment: Team members quickly get consistent development environments.
- Cross-Platform: Windows/Linux/macOS unified development experience.
- Version Management: Development environments can also be version controlled.
Just remember these commands:
# Start development environment
docker run -it -v $(pwd):/workspace image_name
# View containers
docker ps
# Stop container
docker stop container_name
# Clean up resources
docker system prune
Focus on solving real problems; don’t get bogged down by complex concepts. Docker is just a better “virtual machine” that simplifies embedded development.