Deployment and development can be done using Docker. Respective sources are available at https://github.com/FieldTracks/docker-env.
Motivation and the Situation before Docker
For some time now, both development and deployment was solely happening in Linux Container (LXC) containers. These containers are run on dedicated development machine and provisioned using Ansible. However, this approach has certain shortcomings. Onboarding new developers results in grating access and configuring additional test environments as needed. Furthermore, all Ansible templates are tailored to Debian/Buster. All components (fieldmon, StoneAggregator, StoneFlashtool) are required to be packaged using, for instance Debian or pip packages. Also, the Ansible templates rely on inbound Internet connectivity, making it hard for local Development environments.
This motivates to start experimenting with docker. In essence, the setup is supposed to:
- Enable local containers for development
- Reduce the complexity for deployment
Nevertheless, the fieldtracks stack is more challenging compared to web-application typically addressed by Docker.
Challenges for providing Docker images
By design, the fieldtracks technology stack contains various components and technologies. For instance, this includes HTTP and MQTT servers as well as software developed as a part of the fieldtracks project. Tight dependencies exist between all components. For instance, Mosquitto relies on Apache for authenticating MQTT users based on JWT/HTTP.
Additional complexity is introduced by Transport Layer Security (TLS). A local certificate authority (CA) is used to secure MQTT-traffic between JellingStone and the MQTT broker. This requires generating certificates for the broker and distributing key material using StoneFlash Tool. An Internet based CA such as Let’s encrypt cannot be used due to requiring inbound Internet connectivity. However, this can hardly be fulfilled in local development and offline site deployments.
Both, using various components and operating a custom CA are rather uncommon for typical web-applications. In total, docker packaging is required for the following components:
- fieldmon (HTTP)
- WebDAV (HTTP)
- MQTT service (i.e. Mosquitto)
- JWT services for both HTTP and MQTT.
- StoneSimulator (when used in development)
- Local CA (i.e. easy-rsa)
- Let’s encrypt client (when used in field deployments)
In result, the large number of different services and application makes it unpractical to provide distinct images the various components. This reasons to differ from conventional docker designs, which aggregate different, single-process images. Creating a docker-compose YAML file for nine different applications would have resulted in an elaborate configuration with complex service-interactions.
The docker-env repository
Fieldtracks uses a single Docker images for packaging all components except for Let’s encrypt client and StoneFlashtool. It is available at https://github.com/FieldTracks/docker-env. Images for Amd64 and Arm64 are provided on Docker Hub.
The Amd64 image is called fieldtracks, whereas fieldtracks-rpi is built for Arm64 devices such as Raspberry Pis.
When used for development, the Image can be started as follows
mkdir data # Mind to create data directory for certificates and easy-rsa data. docker run \ --name fieldtracks \ --hostname local-dev.fieldtracks.org \ --rm \ -it \ -p 8485:80 \ -p 8443:443 \ -p 2225:22 \ -p 2883:1883 \ -p 8883:8883 \ --mount type=bind,source="$(pwd)"/data,target=/data \ fieldtracks:latest
Certificate data is placed at
data/tls and can easily be added to the local browser. A detailed discussion on files
present in data is given in
For deployments, the situation is more complex. Generating valid TLS certificates requires a Let’s encrypt client in addition. An example for a corresponding Docker compose file is available at https://github.com/FieldTracks/docker-env/blob/master/docker-compose.yml.
Still experimenting with docker yet, the Image is not complete. Most notable, the stone simulator is not started by default and there is the StoneFlashtool is not configured, yet. The latter also concerns configuring USB-port shares in Docker.
Happy Hacking 😉.