Docker is a powerful tool for building, deploying, and managing applications using containers. Docker provides a platform and ecosystem for developers and system administrators to create, distribute, and run containerized applications efficiently.

For information on how Docker compares to LXC, see Comparison between Docker and LXC

Configure your project for Docker support:

Follow these steps to build an image with Docker support:

  1. Edit your project’s conf/bblayers.conf configuration file and add meta-virtualization and meta-filesystems layers:

    conf/bblayers.conf
       /usr/local/dey-4.0/sources/meta-digi/meta-digi-arm \
       /usr/local/dey-4.0/sources/meta-digi/meta-digi-dey \
    +  /usr/local/dey-4.0/sources/meta-virtualization \
    +  /usr/local/dey-4.0/sources/meta-openembedded/meta-filesystems \
    "
  2. Include virtualization in your project. Edit conf/local.conf, and add the following:

    conf/local.conf
    DISTRO_FEATURES:append = " virtualization"
    IMAGE_INSTALL:append = " docker-ce"
    Note the required white space when appending a value to an array variable using the :append override syntax.

Build image with Docker support

  1. Once you have configured your project for Docker support, build the image. For example:

    $ bitbake dey-image-qt
    Check the size of the resulting rootfs image, as it may not fit on the default rootfs partition. You may need to change the partition table.
  2. Program the resulting images as explained in Update firmware.

  3. If you want to ensure your system is configured with Docker, you can use the docker-info command and verify the output.

Create a Docker container

Create a container from a pre-built image

DockerHub is a library of Docker images that contains a variety of distributions, releases, and architectures. Once you decide which image you want, run the following command:

# docker pull <dockerImage>

Where <dockerImage> is the name of the DockerHub image.

Create a custom container with a DockerFile

You can also use a custom Dockerfile to generate a Docker image.

For example, the following Dockerfile creates a container with a base Ubuntu 22.04 image and installs several packages:

# Download base image ubuntu 22.04
FROM ubuntu:22.04

# Disable Prompt During Packages Installation
ARG DEBIAN_FRONTEND=noninteractive

# Update Ubuntu Software repository
RUN apt update
RUN apt upgrade -y

# Install nginx, php-fpm and supervisord from ubuntu repository
RUN apt install -y net-tools
RUN apt install -y iputils-ping
RUN apt install -y gpiod

Refer to the Docker documentation for more information on creating a Dockerfile.

Work with containers

List your current available images
# docker images
List your current available containers
# docker ps -A
Start a container
# docker start <container-name>
Attach a container
# docker attach <container-name>
Run a container
# docker run  <container-name>
Stop a container
# docker stop <container-name>
Remove a container
# docker rm <container-name>
Remove an image
# docker rmi <image-name>

Share native peripherals

You can define specific resources of the native device for your containers to use, such as network interfaces or GPIO pins. This allows for precise control over what resources a container can use.

Use the following arguments to share resources when you attach or run the container:

  • Resource constraints: Specify CPU and memory limits for a container using the --cpus and --memory options, respectively.

  • Networking configuration: Specify network settings such as port mappings, network modes, and hostnames using the --network and --hostname options.

  • Volume mounts: Mount host directories or volumes into a container using the -v or --mount options to provide access to persistent data.

  • Environment variables: Set environment variables inside a container using the -e or --env options to configure application behavior.

  • Health checks: Specify health check commands to monitor the health of a container using the HEALTHCHECK instruction in the Dockerfile or the --health-cmd option at runtime.

  • Devices: Specify devices to limit the access of the container to a specific resource. For example, to specify a GPIO bank, use --device=/dev/gpiochip9.

Share a GPIO port

The following example shares GPIO10 port /dev/gpiochip9 of the native device with a container.

  1. List the device on the native system to see its type (char, block…​) and its major/minor numbers:

    # ls -la /dev/gpiochip9
    crw-rw----    1 root     digiapix  254,   9 Mar 20 10:01 /dev/gpiochip9
  2. Run the following command to create and start the container:

    # docker run -it --device=/dev/gpiochip9 --device-cgroup-rule='c 254:* rmw' --name <image-name> <container-name>

Share Ethernet

To share Ethernet between the native device and a Docker container, you can either share the native Ethernet or use a bridge.

Share the native Ethernet

This setup configures the container to directly share the native device’s primary network interface.

To do so, run the Docker container using the network of the native device:

# docker run --network host -it <image-name>

The container now has network access.

This approach is simpler but doesn’t isolate the network between the native device and the container.

Use a bridge

This method creates a bridge on the native device and attaches the container’s virtual network interface to this bridge. Macvlan is a type of network driver in Docker and Linux networking that allows a container to have its own unique MAC address on the same network as the host. This effectively makes the container appear as a separate physical device on the network.

  1. On the target, create a bridge named br0, attach the native device’s physical network interface eth0 to it, and obtain a dynamic IP:

    # ip link add name br0 type bridge
    # ip link set br0 up
    # ip addr flush dev eth0
    # ip link set eth0 master br0
    # ifconfig br0 up
    # udhcpc -i br0
  2. Create a macvlan network in Docker:

    # docker network create -d macvlan --subnet=<your-network-subnet>/<your-network-mask> --gateway=<your-network-gateway> -o parent=br0 macvlan_net

    Replace <your-network-subnet>/<your-network-mask> and <your-network-gateway> with your network’s subnet/mask and gateway.

  3. Run the container using the macvlan network:

    # docker run --network macvlan_net -it <image-name>