Search code examples
.netdockerasp.net-coreopc-ua

Connect to OPC-UA server from container-ized client app


I have software I'm trying to write that needs to connect to an OPC-UA server. The software is being hosted inside of a docker container and the OPC-UA server will ultimately be the one embedded in the PLC that my company uses. For now I'm trying to use the Prosys OPC-UA Simulation Server running natively on my Windows PC. I'm using the latest version of Docker Desktop with WSL2 mode turned on (instead of using Hyper-V). This is a .NET application (.NET 6) using the OPCFoundation.NetStandard.Opc.Ua nuget package to handle communication to the UA server. I can also confirm that the XML configuration file that the .NET UA library reads is in the location the software is expecting it to be in (root of the EXE).

Running outside of the docker environment I can connect perfectly fine with the connection string of opc.tcp://<my_windows_ip>:53530/OPCUA/SimulationServer to the Prosys UA server. Once I create a docker image and create a container and try to connect to the server it fails. I've tried

  • host.docker.internal for the hostname
  • The Linux 172.17.0.1 address (that is supposed to be the host PC's address)
  • The Prosys connection string as is
    • opc.tcp://<fully_qualified_computer_name>:53530/OPCUA/SimulationServer
  • 127.0.0.1 (which I expected wouldn't work anyway)
  • Trying different port mappings in the docker-compose.yml file
  • Connecting to an actual PLC that has an embedded UA server

Every attempt has failed. I tried to rule out OPC by writing a really simple TCP listener app that was running natively on my computer and added an ASP.NET route to the app contained in docker that sent a message via TCP to the one not running in docker. I had it listen to 0.0.0.0:13000 and my app hosted by a docker container connected to it fine.

I've been at this for almost a week now and I have no idea what to do next. It surprised me that I couldn't connect to an actual PLC that has its own server in it.


Solution

  • I found out that the client was connecting to the server when trying to create the session. The issue had to do with the Docker image. We're using Linux images for the containers with the compiled program getting copied into the images /app folder. We also add a user within the image. That user didn't have write permissions to the /app folder. That meant the OPCUA API that I'm using was unable to create the folders and write the certificate sent from the server to the file system. A System.IO.IOException was being thrown.

    I changed the ownership of the /app folder to this created user (recursively as well) and made sure that the user had both read and write permissions on the folder. Once I did that everything was working.