---
alias: operation-guide-connectiotinstallation-docker
tags:
- connect iot
description: "This documentation details Docker container setup for Connect IoT, including environment variables, paths, and configuration options"
---
# Docker Container Support
A Docker image is provided with support for x64 and Arm64 architectures.
!!! info
This and other images are available only through the DevOps Center section of the Customer Portal and require proper authorization to be accessed. For more information, visit .
## Variables to set
The image fills its configuration template from the following environment variables when the container starts. The template has no default values: set each variable that your authentication type uses. A variable that is not set stays in the configuration file as its `${...}` placeholder.
| Name | Configuration key | Description |
| ----------------------------------- | -------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------------------------- |
| CONNECT_IOT_MANAGER_NAME | `id` | **Automation Manager** ID, as defined in MES. The image also passes it to the manager as `--id`. |
| CONNECT_IOT_MONITOR_HOSTNAME | `hostName` | Address on which the controllers reach the drivers. Use `localhost` unless the controller and the driver run in different managers. |
| TENANT_NAME | `system.tenantName` | Tenant of MES. It is also part of the `openIdConfiguration` URL. |
| APPLICATION_PUBLIC_HTTP_ADDRESS | `system.address` | Address of MES. |
| APPLICATION_PUBLIC_HTTP_PORT | `system.port` | Port of MES. |
| APPLICATION_PUBLIC_HTTP_TIMEOUT | `system.timeout` | Timeout of the calls to MES, in milliseconds. |
| APPLICATION_PUBLIC_HTTP_TLS_ENABLED | `system.useSsl` | `true` when MES is reached over HTTPS. |
| APPLICATION_AUTHENTICATION_TYPE | `system.authentication.type` | `SecurityPortal` or `ClientCredentials`. Any other value is read as `SecurityPortal`. |
| SECURITY_PORTAL_CLIENT_ID | `system.authentication.settings.clientId` | ID of the client in Security Portal. |
| SECURITY_PORTAL_PUBLIC_URL | `system.authentication.settings.openIdConfiguration` | Public URL of Security Portal. The image builds `/tenant//.well-known/openid-configuration`. |
| APPLICATION_PAT | `system.authentication.settings.accessToken` | With `SecurityPortal`, the access token of the integration user. See [[operation-guide-connectiotadministration#access-tokens]]. |
| SECURITY_PORTAL_CLIENT_SECRET | None, read by the processes | With `ClientCredentials`, the client secret. |
Table: Environment variables read by the Connect IoT image
The template also fills `domain`, `username`, and `password` from `APPLICATION_AUTHENTICATION_DOMAIN`, `APPLICATION_AUTHENTICATION_USERNAME`, and `APPLICATION_AUTHENTICATION_PASSWORD`. No authentication type uses them, except that `ClientCredentials` takes `password` as the secret, and logs a warning, when `SECURITY_PORTAL_CLIENT_SECRET` is empty.
For any variable, you can set `_FILE` to the path of a file instead, for example a secret mounted in the container. The entry point of the image sets `` to the content of that file.
The processes also read the following optional variables:
- `MESSAGEBUS_GATEWAY_ADDRESS`, `MESSAGEBUS_GATEWAY_PORT`, and `MESSAGEBUS_GATEWAY_WS_PROTOCOL` - when all three are set, they replace the message bus address that MES publishes.
- `ENTRYPOINT_CUSTOM_CERTIFICATES` - see [Certificates](#certificates).
!!! note
The 12.0 image no longer reads `CONNECT_IOT_REPOSITORY_TYPE`, `CONNECT_IOT_REPOSITORY_LOCATION`, `CONNECT_IOT_STORAGE_RETENTION_TIME`, `STORAGE_RETENTION_TIME`, `DISCOVERY_SERVICES_URL_SUFFIX`, `DISCOVERY_SERVICES_ENABLED`, or `APPLICATION_ACCESS_TOKEN`. The repository, the storage, and the logging come from the configuration of the Automation Manager in MES. The authentication type `Password` no longer exists.
## Special Paths
| Path | Description |
| ---------------------------------------- | ---------------------------------------------------------------------------------------------------------------- |
| /usr/iot/ | Connect IoT root and working directory. |
| /usr/iot/manager/src/ | Manager (`index.js`) and monitor (`monitor.js`). |
| /opt/iot/manager/config.manager.json | Configuration template that the environment variables fill. |
| /usr/iot/manager/config.json | Configuration file generated from the template when the container starts. |
| /usr/iot/manager/config.downloaded.json | Full configuration that the monitor reads from MES, with the `system` section of `config.json`. |
| /opt/ca-certificates/ | Folder for custom certificate authority files. See [Certificates](#certificates). |
Table: Connect IoT Special Paths for Docker
The image has no fixed folders for the package cache, the persistency, and the logs. Their paths come from the `cache`, `storage`, and `logging` sections of the **Automation Manager** configuration in MES, which by default put them under `/ConnectIoT`, the temporary folder of the container. See [[operation-guide-connectiotadministration#data-on-the-manager-host]].
!!! note
Content kept inside the container is lost when the container is removed. Mount volumes for the persistency and the logs, and set the matching paths in the Automation Manager configuration.
## Configuration File Included
This is the raw configuration template. When the container starts, its placeholders are replaced with the values of the corresponding environment variables.
```json
{
"id": "${CONNECT_IOT_MANAGER_NAME}",
"hostName": "${CONNECT_IOT_MONITOR_HOSTNAME}",
"monitorApplication": "${pwd}/monitor.js",
"system": {
"tenantName": "${TENANT_NAME}",
"address": "${APPLICATION_PUBLIC_HTTP_ADDRESS}",
"port": "${APPLICATION_PUBLIC_HTTP_PORT}",
"timeout": "${APPLICATION_PUBLIC_HTTP_TIMEOUT}",
"useSsl": "${APPLICATION_PUBLIC_HTTP_TLS_ENABLED}",
"urlSuffix": "",
"authentication": {
"type": "${APPLICATION_AUTHENTICATION_TYPE}",
"settings": {
"domain": "${APPLICATION_AUTHENTICATION_DOMAIN}",
"username": "${APPLICATION_AUTHENTICATION_USERNAME}",
"password": "${APPLICATION_AUTHENTICATION_PASSWORD}",
"clientId": "${SECURITY_PORTAL_CLIENT_ID}",
"accessToken": "${APPLICATION_PAT}",
"openIdConfiguration": "${SECURITY_PORTAL_PUBLIC_URL}/tenant/${TENANT_NAME}/.well-known/openid-configuration"
}
}
},
"isMinimal": true
}
```
The file holds only the `system` section. With `isMinimal` set to `true`, the monitor reads the rest of the configuration from the **Automation Manager** in MES each time it starts. To change the repository, the storage, or the logging, use [[user-guide-automation-manager-configure]]. See [[installation-guide-connectiotautomationmanagerconfig#where-the-configuration-lives]].
## Certificates
To trust a certificate authority that is not in the image, mount its certificate files in the container, for example under `/opt/ca-certificates`, and set `ENTRYPOINT_CUSTOM_CERTIFICATES` to their paths, separated by commas. When the container starts, the entry point adds them to the system certificate bundle in `/opt/ca-certificates/bundle/custom-ca-bundle.crt`, and points `SSL_CERT_FILE` and `NODE_EXTRA_CA_CERTS` to that file.
!!! warning
The image sets `NODE_TLS_REJECT_UNAUTHORIZED=0`. The manager also sets it to `0` when it starts, unless `systemCertificate.rejectUnauthorized` is `true` in its configuration file, and the template of the image has no `systemCertificate` section. As shipped, the processes do not reject an invalid TLS certificate from MES or Security Portal. See [[installation-guide-connectiotautomationmanagerconfig#systemcertificate-structure]].
To turn certificate validation on, mount a configuration file over `/opt/iot/manager/config.manager.json` that has a `systemCertificate` section with `rejectUnauthorized` set to `true`. No environment variable of the image sets this section.
## Examples
The following examples explain what to to under some special scenarios. The command lines provided are to be used as an example only. They must be adapted to match you operating system, directory locations, versions, etc.
### Use a shared directory as directory repository
Assuming the directory to be in `\\10.24.14.17\public\jpsantos\Repository` and it is protected by user/password.
```bash
docker volume create --driver local --opt type=cifs --opt device=//10.24.14.17/public/jpsantos/Repository --opt o=user=cmfsu,domain=cmf.criticalmanufacturing.com,password="ThIsMyPaSsWoRd" repositoryVolume
docker run -it --env-file C:\docker\envVariables.txt --name iot --volume repositoryVolume:/usr/iot/repository criticalmanufacturing.io/criticalmanufacturing/connectiot:
```
The 12.0 image does not read the repository from environment variables. Set the `repository` section of the **Automation Manager** configuration in MES with [[user-guide-automation-manager-configure]]:
```json
"repository": {
"type": "Directory",
"settings": {
"path": "/usr/iot/repository"
}
}
```
### Attach a USB Barcode Reader for KeyboardWedge driver
Assuming the USB reader is connected and detected by the system (used a Raspberry Pi Linux Arm for the example, so Raspbian OS), mounted as `/dev/hidraw0`.
First step, to avoid using docker image in privileged mode, is to allow access to the device by any user.
1. List USB devices
```bash
pi@raspberrypi:~/iot $ lsusb
Bus 002 Device 002: ID 090c:1000 Silicon Motion, Inc. - Taiwan (formerly Feiya Technology Corp.) Flash Drive
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
Bus 001 Device 007: ID ffff:0035
Bus 001 Device 002: ID 2109:3431 VIA Labs, Inc. Hub
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
```
2. Having identified the device (`Bus 001 Device 007: ID ffff:0035`), create a rules file to allow the usage by anyone that has access to the system.
```bash
pi@raspberrypi:~/iot $ sudo nano /etc/udev/rules.d/rfid.rules
SUBSYSTEM=="usb", ATTRS{idVendor}=="ffff", ATTRS{idProduct}=="0035", MODE="0777"
```
3. Reboot the system to apply the rules
The final step is to start the container and forward the access to the device
```bash
docker run -it --device /dev/hidraw0:/dev/hidraw0 --env-file /home/pi/iot/env.txt --name iot criticalmanufacturing.io/criticalmanufacturing/connectiot:
```
`Note`: In the Setup workflow, set the location of the device in the **Equipment Configuration** task to the location mapped in the container. In this example, the device was kept as `/dev/hidraw0`. See [[user-guide-automation-task-core-equipmentconfig]].
### Attach a serial device
Some automations require access to serial devices. As with the previous example, it is necessary to allow access from the container to the physical device, but in the case of the serial, it is not necessary to provide special access rules.
```bash
docker run -it --device /dev/serial0:/dev/serial0 --env-file /home/pi/iot/env.txt --name iot criticalmanufacturing.io/criticalmanufacturing/connectiot:
```
### Use a mounted location to access with a file driver
Assuming the location `/home/pi/iot/device` is pointing out to and external location where a device places files to be processed by Connect IoT.
```bash
docker run -it --volume /home/pi/iot/device:/usr/iot/toolDirectory --env-file /home/pi/iot/env.txt --name iot criticalmanufacturing.io/criticalmanufacturing/connectiot:
```
`Note`: In the Setup workflow, set the location in the **Equipment Configuration** task to the location mapped in the container. In this example, the device was set as `/usr/iot/toolDirectory`.
### Use Raspberry Pi included Bluetooth device
`Note`: This is not yet working 100%, but it already allows to scan the existing devices. Connecting to them sometimes causes an error and needs to retry several times. Until a solution is found, it is not recommended to use the BLE driver inside a container.
```bash
docker run -it --cap-add=SYS_ADMIN --cap-add=NET_ADMIN --net=host --env-file /home/pi/iot/env.txt --name iot --device /dev/ttyAMA0 criticalmanufacturing.io/criticalmanufacturing/connectiot:
```
## Install Docker in Raspberry pi
The following instructions were tested, based on the tutorial from .
```bash
sudo apt-get update && sudo apt-get upgrade
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh
# optional, add user pi into docker group to allow running docker commands without sudo
sudo usermod -aG docker pi
docker version
```