Structuring Applications with Multiple Services
Best practices guide on Hhw to structure larger applications consisting of multiple services efficiently and optimize storage requirements
Some applications are composed of multiple micro-services, as is the case in our Photo Gallery example application. Docker promotes the idea of running each micro-service that comprises an application as a separate docker container. This is generally no issue for servers or even desktop computers, but special consideration is required on embedded systems such as Skynode where resources are limited.
Below are a few tips on how to efficiently structure applications consisting of multiple containers, which are described in more detail down below:
- 1.Package your services that are docker images into a single application. This ensures that the user only needs to handle a single
- 2.Write a common base
Dockerfilefor a shared environment used by your services. This ensures that the resulting
.auterionosfile, as well as the storage space requirements after installation are as low as possible.
While your app can be composed of multiple docker containers, we advise that they are all packaged into a single Application. The user should only need to handle a single
.auterionosfile when installing or updating your application. This brings a few benefits:
- You can specify the launch order of the individual docker containers, in case some services rely on others
- You can provide all your services at the exact version required for a specific release of the application
- There is no risk of your application being installed incompletely
- There is no risk of your application being updated only partially, resulting in a mismatch of the services inside
docker build --platform=arm64 ./src/camera-control -t camera-control:1.0.0
docker build --platform=arm64 ./src/gallery-service -t gallery-service:1.0.0
In the Makefile's target rule for building your application, you need to export all services as a single image, for example:
build: build-camera-control build-gallery-service
docker save camera-control:1.0.0 gallery-service:1.0.0 | gzip > gallery.image
Docker builds its images using layers. Images that share the same base image can therefore reuse its layers, thus saving storage space. More details can be found in Docker's official documentation.
In the context of Skynode and AuterionOS, identifying, breaking out and reusing base images in your application brings the following advantages:
- Your app uses less space on Skynode, because the base needs to be stored only once in Docker
- Smaller download size of your app, which saves time and bandwidth for downloading files, and speeds up the installation process. This benefit is only achieved when all micro-services are packaged together.
The example below uses a custom base image. The same principle can be applied when most of your services inherit from an existing public image such as "arm64v8/python:buster" for example.
Example folder structure using a base Dockerfile and services:
│ ├── app.py
│ └── Dockerfile
Create Dockerfile.base that defines a common environment for your micro-service's images:
# Install common dependencies for the micro-services
RUN apt-get update \
Create one Dockerfile for each of your services and reuse the base image:
# Install dependencies specific to this service
RUN apt-get update \
In the Makefile, build the base image as well as your services:
docker build --platform=arm64 ./src -f src/Dockerfile.base -t my-arm64-base
docker build --platform=arm64 ./src/service-1 -t service-1:1.0.0
docker build --platform=arm64 ./src/service-2 -t service-2:1.0.0
Combine the use of base images with the method for packaging multiple micro-services into one application to achieve the most compact .auterionos files.