Skip to main contentDocker: Your Embedded Development Environment Supercharger | IoT Worker

Docker: Your Embedded Development Environment Supercharger

Why Embedded Development Needs Docker?

1. Solving Cross-Compilation Environment Issues

  • Toolchain Version Conflicts: Different projects require different gcc-arm-none-eabi versions.
  • 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:

  1. Environment Isolation: Different projects use different toolchain versions.
  2. Rapid Deployment: Team members quickly get consistent development environments.
  3. Cross-Platform: Windows/Linux/macOS unified development experience.
  4. 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.