Why Embedded Development Needs Docker?
1. 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.
2. 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
1# One-line installation script
2curl -fsSL https://get.docker.com | sh
3
4# Configure user permissions (to avoid sudo every time)
5sudo usermod -aG docker $USER
6
7# Log out and log back in, or run:
8newgrp docker
Verify Installation
1docker --version
2docker run hello-world
Common Commands for Embedded Development
1. Get Embedded Development Images
1# ARM development environment
2docker pull arm32v7/gcc
3
4# STM32 development environment
5docker pull stm32duino/arduino-core-stm32
6
7# ESP32 development environment
8docker pull espressif/idf
9
10# Generic cross-compilation environment
11docker pull multiarch/crossbuild
2. Start a Development Container
1# Basic launch (mount current directory)
2docker run -it -v $(pwd):/workspace arm32v7/gcc bash
3
4# With port mapping (for debugging servers)
5docker run -it -v $(pwd):/workspace -p 3333:3333 arm32v7/gcc bash
6
7# Run container in the background
8docker run -d --name my-dev -v $(pwd):/workspace arm32v7/gcc tail -f /dev/null
9
10# Enter a background container
11docker exec -it my-dev bash
3. Common Operations
1# View running containers
2docker ps
3
4# Stop a container
5docker stop my-dev
6
7# Delete a container
8docker rm my-dev
9
10# View local images
11docker images
Hands-on: STM32 Development Environment
1. Create an STM32 Development Image
Create Dockerfile.stm32:
1FROM ubuntu:20.04
2
3# Prevent interactive installation
4ENV DEBIAN_FRONTEND=noninteractive
5
6# Install basic tools
7RUN apt-get update && apt-get install -y \
8 build-essential \
9 git \
10 wget \
11 curl \
12 unzip \
13 python3 \
14 python3-pip
15
16# Install ARM toolchain
17RUN apt-get install -y gcc-arm-none-eabi
18
19# Install STM32CubeMX (optional)
20RUN apt-get install -y default-jre
21
22# Set working directory
23WORKDIR /workspace
24
25# Set entrypoint
26CMD ["/bin/bash"]
2. Build and Use
1# Build image
2docker build -f Dockerfile.stm32 -t stm32-dev .
3
4# Start development environment
5docker run -it -v $(pwd):/workspace stm32-dev
6
7# Compile inside the container
8cd /workspace
9make clean && make
Hands-on: ESP32 Development Environment
1. Use Official ESP-IDF Environment
1# Pull ESP-IDF image
2docker pull espressif/idf:latest
3
4# Start ESP32 development environment
5docker run --rm -v $PWD:/project -w /project -it espressif/idf:latest
6
7# Operate inside the container
8idf.py build
9idf.py flash
2. Simplify Script
Create esp-dev.sh:
1#!/bin/bash
2docker run --rm -v $PWD:/project -w /project -it \
3 --device=/dev/ttyUSB0 \
4 espressif/idf:latest bash
Usage:
1chmod +x esp-dev.sh
2./esp-dev.sh
Data Persistence
Mount Project Directory
1# Mount current directory to /workspace in the container
2docker run -it -v $(pwd):/workspace image_name
3
4# Mount a specific directory
5docker run -it -v /home/user/projects:/workspace image_name
6
7# Read-only mount (prevent container from modifying host files)
8docker run -it -v $(pwd):/workspace:ro image_name
Data Volumes (for toolchain caching)
1# Create a data volume to store compilation cache
2docker volume create build-cache
3
4# Use the data volume
5docker run -it -v $(pwd):/workspace -v build-cache:/cache image_name
Multi-Project Management
Using Docker Compose
Create docker-compose.yml:
1version: '3.8'
2
3services:
4 stm32-dev:
5 build:
6 context: .
7 dockerfile: Dockerfile.stm32
8 volumes:
9 - ./stm32-project:/workspace
10 working_dir: /workspace
11 stdin_open: true
12 tty: true
13
14 esp32-dev:
15 image: espressif/idf:latest
16 volumes:
17 - ./esp32-project:/project
18 working_dir: /project
19 devices:
20 - /dev/ttyUSB0:/dev/ttyUSB0
21 stdin_open: true
22 tty: true
Usage:
1# Start STM32 development environment
2docker-compose run stm32-dev
3
4# Start ESP32 development environment
5docker-compose run esp32-dev
Handy Tips
1. Simplify Commands
Add aliases to .bashrc:
1# STM32 Development
2alias stm32='docker run -it --rm -v $(pwd):/workspace stm32-dev'
3
4# ESP32 Development
5alias esp32='docker run -it --rm -v $(pwd):/project -w /project espressif/idf:latest'
6
7# ARM Cross-compilation
8alias arm-gcc='docker run -it --rm -v $(pwd):/workspace arm32v7/gcc'
2. Device Access
1# Access USB devices (debugger, programmer)
2docker run -it --device=/dev/ttyUSB0 -v $(pwd):/workspace image_name
3
4# Access multiple devices
5docker run -it \
6 --device=/dev/ttyUSB0 \
7 --device=/dev/ttyACM0 \
8 -v $(pwd):/workspace image_name
3. Network Debugging
1# Map GDB debug port
2docker run -it -p 3333:3333 -v $(pwd):/workspace image_name
3
4# Map Web service port (for online debugging tools)
5docker run -it -p 8080:8080 -v $(pwd):/workspace image_name
Common Issues
1. USB Device Access Permissions
1# Add user to dialout group
2sudo usermod -aG dialout $USER
3
4# Or temporarily modify device permissions
5sudo chmod 666 /dev/ttyUSB0
2. Slow Compilation Inside Container
1# Use compilation cache volume
2docker run -it -v build-cache:/tmp -v $(pwd):/workspace image_name
3
4# Limit parallel compilation processes
5make -j$(nproc)
3. Cleaning Up Space
1# Clean up stopped containers
2docker container prune
3
4# Clean up unused images
5docker image prune
6
7# One-command clean up all unused resources
8docker system prune
Practical Examples
Embedded Linux Development
1# Use cross-compilation environment
2docker run -it --rm \
3 -v $(pwd):/workspace \
4 -e CROSS_COMPILE=arm-linux-gnueabihf- \
5 multiarch/crossbuild bash
RTOS Project Compilation
1# FreeRTOS Project
2docker run -it --rm \
3 -v $(pwd):/workspace \
4 -w /workspace \
5 arm32v7/gcc \
6 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:
1# Start development environment
2docker run -it -v $(pwd):/workspace image_name
3
4# View containers
5docker ps
6
7# Stop container
8docker stop container_name
9
10# Clean up resources
11docker 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.