ATS Bus 3.3 enables the deployment of one or more OT, IT, ADOS bus stops, data services, and OPC UA browsing services as Docker containers on the same Linux host. A Docker container is a standardised unit containing all the software modules and configuration files required to run an application or service in an isolated and secure environment.
A Docker image is a read-only layered object containing software and instructions to run the Docker container. The first layer, the base layer, could be an operating system. The second layer a set of tools and the third layer the web service that forms a web service image. Each layer is immutable so it cannot be changed. Changing files results in a new layer. Docker images are provided via registries like Docker Hub, Microsoft Azure or the Microsoft Container Registry (MCR).
A Docker container is a runtime instance of a Docker image. It is first instantiated with a set of parameters that configure the name of the image, the directories it must map, the environment variables and the ports it should expose. Once instantiated, the container is started and the entry point is invoked.
Many applications are provided as Docker images such as RabbitMQ, Microsoft SQL Server, NGinX, Ubuntu, Debian and many more. Some of these images can even be used with ATS Bus, RabbitMQ and Microsoft SQL server can be with ATS Bus transport, and Microsoft SQL Server can also be used with ATS Bus persistence.
This document only contains information relevant to the deployment of bus stop containers. Detailed information about Docker can be found on their website: https://www.docker.com.
Certificates, Docker and Docker Compose and examples are provided in the next paragraphs.
The Docker and Docker Compose tools are required to deploy and manage the Docker container. Installing these tools is beyond the scope of this document.
Please visit the following URLs for a detailed explanation:
Linux: https://docs.docker.com/desktop/install/linux-install/
Windows: https://docs.docker.com/desktop/install/windows-install/
Mac: https://docs.docker.com/desktop/install/mac-install/
A container management tool like Portainer (https://www.portainer.io/) can be used but is not required as the docker and docker-compose tools are enough to manage the bus stop containers.
The ATS Bus bus stop images are provided as Linux and Windows images via Docker Hub. This document is primarily focused on the deployment of Linux images, but Windows deployment examples will be provided too.
Ensure that the following applications are installed and functional before deploying the bus stop containers:
ATS Configuration, Security Manager and License Manager: Visit the ATS Configuration Manager to verify that all components are properly installed and in working order.
ATS Bus 3.1 (Data Service and Cockpit): Copy-paste the following URL in a web browser, it should yield the license and Security Manager endpoints: https://<host>:<port>/api/v1/settings/globalsettings. It must also show that the site is secured. This means that the certificates to encrypt the connection are properly configured.
Applications and services may use certificates to encrypt a connection. These certificates are issued by themselves (self-signed certificates) or by a root certification authority. During data exchange, the client receives a copy of the certificate and tries to validate the certificate chain by ensuring that the issuer of the certificate, the root certificate, is trusted. In other words, the root certificate must be present in the trusted root (Trusted Root Certification Authorities) section of the certificate store.
The trusted root section already contains several well-known root certification authorities, which are provided by the operating system vendor. IT departments may also have copied their root certificates to the same trusted root section as part of their security policies.
When using self-signed certificates, a copy of the same certificate should also be copied to the trusted root section otherwise certificate validation fails.
Docker containers only contain a limited set of root certificates in the trusted root section. Therefore, the bus stop containers provide a volume map (named ca-certificates) where base64 encoded root certificates with the .crt extension can be copied too. The entry point of the bus stop container will copy these certificates to the trusted root section of the certificate store in the container.
One of the services mentioned above is the ATS Bus Data Service. This service requires a certificate to encrypt the data exchange and the issuer’s certificate, the root certificate, should be copied to the trusted root section of certificate store of the container.
For example, on a Windows machine, the issuer’s certificate should be exported as a Base64 encoded file from the Trusted Root Certification Authorities section of the local machine certificate store.
Right click the issuer’s certificate.
Select All Tasks.
Click on Export…
The Certificate export wizard opens.
Press Next.
Select Base-64 encoded X.509 (.CER) and press Next.
Provide a file name and press Next.
The wizard will save the file with the .CER extension.
Read the summary and press Finish.
Change the extension of the exported file to .CRT.
Bus stops may also use a certificate to encrypt the data exchange via its webservice server channels. This certificate, the server certificate, must be provided as a PFX file and protected with a password. Bus stops currently support a single server certificate as all use a single server certificate to encrypt all https endpoints. The name of the PFX certificate is provided via an environment variable and the certificate itself is provided via a directory which is bound to a directory inside the container. The configuration examples will illustrate how to use these certificates.
The easiest way to deploy bus stops is by using Docker Compose which uses a configuration file to deploy a container. The configuration file contains configuration for volumes, networks and services (containers). This paragraph will only highlight the basic Docker Compose commands like run, start and stop.
More Docker Compose information can be found at the Docker Compose website: https://docs.docker.com/compose/.
Older versions of Docker came with Docker Compose which was a separate tool, newer versions of Docker include Compose as an argument of the docker command: ‘docker compose’ just like ‘docker images’ and ‘docker run’.
Docker compose configuration files are formatted in the YAML format. The example below can be used to deploy an ATS Bus OT bus stop:
version: '3.4'
services:
atsbus.otbusstop.svc:
image: atsproducts/ats.atsbus.busstop.ot-linux-x64:latest
container_name: atsbus.otbusstop
ports:
- "8800:8800"
extra_hosts:
- "docker-host-hostname:10.0.0.10"
environment:
- Configuration__BusStopName=OTBusStop
- Configuration__ConfigurationEndpoint=https:// docker-host-hostname:9704
- Configuration__BasePath="/"
- Kestrel__UseHttps=true
- Kestrel__Certificates__Default__Path=/app/certificates/atsbus.pfx
- Kestrel__Certificates__Default__Password=atsbus123
- Kestrel__Certificates__Default__AllowInvalid="true"
- Serilog__WriteTo__1__Args__path=/app/logs/log_.txt
- Serilog__WriteTo__1__Args__restrictedToMinimumLevel=Debug
- Serilog__EventLogManageEventSource=false
volumes:
- <host_volume_mountpoint_for_certificates>:/app/certificates
- <host_volume_mountpoint_for_ca_certificates>:/app/ca-certificates
- <host_volume_mountpoint_for_logging>:/app/logs
- <host_volume_mountpoint_for_programdata>:/usr/share/atsglobal/atsbus/OTBusStop
entrypoint: ["sh", "/app/scripts/entrypoint.sh"]
The configuration above has the following elements:
It uses the latest atsproducts/ats.atsbus.busstop.ot-linux-x64:latest docker image from the docker hub.
The ADOS bus stop image is available as atsproducts/ats.atsbus.busstop.ados-linux-x64:latest.
The container is named atsbus.otbusstop. Docker containers can ping each other by their container name if they are in the same docker network.
The container exposes port 8800 to port 8800 on the Docker host. The alive endpoint of the bus stop can be reached by navigating to the following URL: https://docker-host-hostname:8800. The bus stop may be configured to host multiple webservice server channels (web API’s). Each API binds to a port and these ports should be exposed in the same way.
The configuration also provides an extra-hosts entry. This entry is used by the container if it is unable to resolve certain host names.
Environment variables are used to configure the bus stop service in the container. This list contains a few extra variables that are not provided in the example above:
Variable |
Description |
Configuraion__BusStopName |
The name of the bus stop as configured in the ATS Bus configuration. |
Configuraion__ConfigurationEndpoint |
The URL of the configuration endpoint of the ATS Bus data service (must be HTTPS). The data service uses a certificate to encrypt the endpoint. Make sure that the issued certificate is a public certificate or override the entrypoint property with a script that copies the issued certificate from ‘host_volume_mountpoint_for_ca_certificates’ to copy the CA certificate directory in the docker container. |
Configuration__BasePath |
The base path for the URL. Please click here for further information. |
Kestrel__Certificates__Default__Path |
The path to the default PFX file that is used by all bus stop web API’s like the API exposed on the monitoring port or the WebService server channels. The path must be mapped to a directory on the Docker host, which is how the certificate is made available to the container. The path can be formatted as: |
Kestrel__Certificates__Default__Password |
The password of the PFX file. |
Kestrel__Certificates__Default__Password__AllowInvalid |
Whether or not to allow self-signed certificates |
Kestrel_UseHttps |
When set to false, the bus stop configures an unencrypted HTTP endpoint (http). When set to true, the bus stop configures an encrypted HTTP endpoint (https). The following properties must be configured when ‘Kestrel_UseHttps’ is set to true:
|
Serilog__EventLogManageEventSource |
Setting this value to true configures the Windows event viewer. This should be set to false when using Docker. |
Serilog__WriteTo__1__Args__path |
The location of the logfile. This can be an absolute or relative path. The relative can be formatted as Linux path: ./logs/log_.txt |
Serilog__WriteTo__1__Args__restrictedToMinimumLevel |
The minimum severity to log to file. Setting it to Debug will log debug messages in the log file. Other valid options are:
|
Serilog__WriteTo__0__Args__restrictedToMinimumLevel |
The minimum severity to log to console. |
entrypoint |
The default docker entrypoint starts the bus stop application using: ‘[“dotnet”, “Bus.BusStop.XXXX.dll”]’ but the entrypoint can be overridden by executing a script as shown in the docker-compose example above. This script resides on the docker host and its location is mapped to a directory inside the docker container. |
The volumes section maps directories in the container to directories on the Docker host. The list below shows the most used mapping.
Please note the Docker host directories when running the Docker host on Windows and using WSL to run Linux containers. When using Docker Desktop, the host directories start with ‘C:\’. When using Docker CLI (non Docker Desktop installation), the host directories start with ‘/mnt/c/’. The following docker-compose volumes section shows two entries: the first entry is used with Docker Desktop is used as Docker host and the second entry is used whe Docker CLI is used as Docker host:
volumes:
- C:\Directory\When\Using\DockerDesktop\share1:/usr/local/share1
- /mnt/c/Directory/When/Using/Docker/share1:/usr/local/share1
The above is only valid when using Docker Desktop or Docker CLI on Windows and running Linux containers using WSL.
Docker host |
Container |
Description/purpose |
<host_volume_mountpoint_for _certificates> |
Linux: /app/certificates |
The container directory provided here should be equal to the directory provided with the ‘Kestrel__Certificates__Default__Path’ environment variable. |
<host_volume_mountpoint_for_ca_certificates> |
Linux: /app/ca-certificates |
The directory where the container entry point script reads the issuer/root certificate from. These certificates are added to the root certificate section in the certificate store of the container. |
<host_volume_mountpoint_for _logging> |
Linux: /app/logs |
The container directory provided here should be equal to the directory provided with the ‘Serilog__WriteTo__1__Args__path’ environment variable. |
<host_volume_mountpoint_for _programdata> |
Linux: /usr/share/atsglobal/ atsbus/<BusStopName> |
The container directory is fixed and points to the common application data directory where the bus stop places files that should service a reboot like counter tag values and last read database records. This directory also contains the last configuration obtained from the data service. Note: Mind the whitespace between ‘ATS’ and ‘Global’ and ‘ATS’ and ‘Bus’. The string ‘OTBusStop’ is the name of the bus stop that is also configured in the ‘BusStopName’ environment variable. |
c:\dockervolume\channel |
/usr/share/channel |
File channels require several directories to receive input messages, store output messages, store errors and processed messages and backup incoming messages. These directories should be mapped onto the docker host too. |
The following steps are required to deploy the OT bus stop as a docker container:
Ensure Docker Desktop is installed and running. Docker Desktop should be configured to work with Linux containers.
Ensure that the ATS Bus Data Service is properly installed on the Docker host and that its certificates are properly configured by browsing to the following URL: https://<host>:<port>/api/v1/settings/globalsettings. The browser should show an XML or JSON structure containing the License and Security manager endpoint.
A valid configuration for a bus stop named OTBusStop containing an XML channel for example. Make sure to map the directories of the XML channels to directories on the Docker host.
A base64 encoded file containing the issuer/root certificate of the server certificate used by the ATS Bus Data Service.
A Self signed certificate for the bus stop web API’s. This certificate should contain the docker-host-hostname, fully qualified docker-host-hostname, localhost and the container name as DNS entries. This certificate can be created using the following PowerShell commands:
$cert = New-SelfSignedCertificate -DnsName docker-host-hostname.domain.com, docker-host-hostname, localhost, atsbus.otbusstop -CertStoreLocation "cert:\LocalMachine\My" -NotAfter "2030-01-01" -Subject "CN=AtsBusSelfSignedCert"
$pwd = ConvertTo-SecureString -String "atsbus123" -Force -AsPlainText
Export-PfxCertificate -Cert $cert -FilePath C:\temp\atsbus.pfx -Password $pwd
Change the docker-host-hostname entries by the hostname and fully qualified hostname of the Docker host that also runs the data service and remove the docker-host-hostname entries when the container is able to resolve them via DNS.
A copy of the self-signed certificate created in the previous step should be copied from the Personal folder to the Trusted Root Certification Authorities folder in the local machine certificate store. The New-SelfSignedCertificate command already copies the certificate in the Personal folder of the local machine certificate store.
A yaml file named docker-compose.yml containing:
version: '3.4'
services:
atsbus.otbusstop.svc:
image: atsproducts/ats.atsbus.busstop.ot-linux-x64:latest
container_name: atsbus.otbusstop
ports:
- "8800:8800"
environment:
- BusStopName=OTBusStop
- ConfigurationEndpoint=https://docker-host-hostname:9704
- Kestrel__Certificates__Default__Path=/app/certificates/atsbus.pfx
- Kestrel__Certificates__Default__Password=atsbus123
- Kestrel__Certificates__Default__AllowInvalid="true"
- Serilog__WriteTo__1__Args__path=/app/logs/log_.txt
- Serilog__WriteTo__1__Args__restrictedToMinimumLevel=Debug
- Serilog__EventLogManageEventSource=false
volumes:
- c:\dockervolumes\certificates:/app/certificates
- c:\dockervolumes\ca-certificates:/app/ca-certificates
- c:\dockervolumes\otbusstop\logs:/app/logs
- c:\dockervolumes\otbusstop\programdata:/usr/share/atsglobal/atsbus/OTBusStop
- c:\dockervolumes\xmlchannel:/usr/share/xmlchannel
The certificate exported by the third Powershell script, named atsbus.pfx, should be copied to the directory that is mapped to the container directory that is used by the container’s Kestrel__Certificates__Default__Path environment variable. It should go to c:\dockervolume\bs\certs.
The password of the certificate should be copied to the environment variable named Kestrel__Certificates__Default__Password.
Save the YAML file and execute the following command to bring the OT bus stop container up:
docker-compose -f c:\locationto\docker-compose.yaml up
The ATS Bus configuration plugin requires a web API to configure OPC UA client channels. This web API is provided by the OPC UA Browsing Service and this example shows how to deploy this web API as a docker container.
Ensure Docker Desktop is installed and running. Docker Desktop should be configured to work with Linux containers.
A yaml file named docker-compose.yml containing:
version: '3.4'
services:
ats.bus.opc.ua.browsing.service:
image: atsproducts/ats.shared.opc.ua.browsingservice-linux-x64:latest
container_name: ats.shared.opc.ua.browsingservice
ports:
- '9900:9900'
environment:
- Kestrel__Endpoints__Http__Url=http://*:9900
- Serilog__WriteTo__1__Args__path=/app/logs/log_.txt
- Serilog__WriteTo__1__Args__restrictedToMinimumLevel=Debug
- Serilog__WriteTo__0__Args__restrictedToMinimumLevel=Debug
- Serilog__EventLogEnabled=false
volumes:
- /mnt/c/docker/volumes/atsbus/certificates:/app/certificates
- /mnt/c/docker/volumes/atsbus/ca-certificates:/app/ca-certificates
- /mnt/c/docker/volumes/atsbus/opcuabrowsingservice/logs:/app/logs
- /mnt/c/docker/volumes/atsbus/opcuabrowsingservice/scripts:/app/scripts
Save the YAML file and execute the following command to load the OPC UA Browsing Service container:
docker-compose -f c:\locationto\docker-compose.yaml up
The script below copies the issuer certificates (CA certificates) from the docker host, which is mounted at /app/ca-certificates to /usr/local/share/ca-certificates. Next it updates the ca-certificates and starts the bus stop:
#!/bin/bash
# Copy all ca certificates to from the docker ca certificate mount to /use/local/share/ca-certificates
# Note that self signed certificate can end up here too, these have the .pfx extension
if [ -d "/app/ca-certificates" ] && [ -n "$(ls -A "/app/ca-certificates")" ]; then
cp -dpRv /app/ca-certificates/*.* /usr/local/share/ca-certificates/
update-ca-certificates
fi
dotnet Bus.BusStop.OT.dll
The script below runs the certoc.exe tool on every issued certificate (CA certificate) from the docker host, which is mounted at /app/ca-certificates. This tool installs the certificates in the Trusted Root Certification Authorities store:
@echo off
if exist "C:\app\ca-certificates" (
REM Iterate through the ca-certificates folder and add all .cer files to the Trusted Root Certification Authorities
REM Note that self signed certificate can end up here too, these have the .pfx extension
FOR %%i IN (C:\app\ca-certificates\*.*) DO (certoc.exe -addstore root %%i)
)
dotnet Bus.BusStop.OT.dll
Visit the following URL’s for Docker container management applications:
Docker command line tools and Docker Desktop: https://www.docker.com
Portainer: https://www.portainer.io/
Kubernetes: https://kubernetes.io/
Please provide the following when requesting support from ATS ADOS Support:
A copy of the log files from the log volume.
The Docker Compose that is used to deploy and start the container.
The Console log (the file log does not provide the start-up logging).
The version of the container (the version number, not the latest tag).
Can we improve this topic?