# Docker PLC Dev Simulation

**URL:** <https://forum.inductiveautomation.com/t/docker-plc-dev-simulation/35459>\
**Category:** Ignition\
**Tags:** ignition80\
**Created:** [June 9, 2020, 3:27pm UTC](https://forum.inductiveautomation.com/t/docker-plc-dev-simulation/35459 "2020-06-09T15:27:19Z")\
**Posts on this page:** 2\
**Page:** 1

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [June 9, 2020, 3:27pm UTC](https://forum.inductiveautomation.com/t/docker-plc-dev-simulation/35459/1 "2020-06-09T15:27:19Z")

</div>

To my Docker/Kubernetes users out there, I am recently grasping a better understanding of docker-compose and how simple it is to rapidly recreate entire projects locally with multiple gateways, all connected, databases, DNS, AD, etc. However the one item that I am still missing is PLC comms.

I am the least PLC informed Ignition guy you will ever meet, my focus is much more on the app side of things, I can barely spell PLC 😉. However if I need to spin up rapid quick dev mockups of OPC connections through a container what have you guys used before?

I have essentially glanced at the [Microsoft IoT Edge OPC UA PLC image](https://hub.docker.com/_/microsoft-iotedge-opc-plc) and am thinking that is my best bet, but I am curious on other peoples experiences.

@Kevin.Collins? @paul-griffith?

---

<div class="post-metadata">

**Author:** ![kgamble](https://sea1.discourse-cdn.com/inductiveautomation/user_avatar/forum.inductiveautomation.com/kgamble/32/8019_2.png) [@kgamble](https://forum.inductiveautomation.com/u/kgamble)\
**Post date:** [June 12, 2020, 4:03am UTC](https://forum.inductiveautomation.com/t/docker-plc-dev-simulation/35459/2 "2020-06-12T04:03:40Z")

</div>

As an update if anyones curious,

I did end up using the [Microsoft IoT Edge OPC UA PLC image](https://hub.docker.com/_/microsoft-iotedge-opc-plc) that I mentioned before, and it works fairly well. For rapid reuse I find it best to provide it a server certificate instead of letting it generate one so that you dont have to go back and re-trust it on your gateway every time you recreate the container from a backup. I also planned on making an adjustment to kcollins’ ignition dockerfile to automatically put the certificate you give the OPC server into the `\Ignition\data\opcua\client\security\pki\trusted\certs` folder

I also created a script that will go through any of your tags and accordingly change them to point to the default fake simulated tags

```auto
import random

ints = ["ns=2;s=PositiveTrendData", "ns=2;s=NegativeTrendData", "ns=2;s=SpikeData", "ns=2;s=StepUp", "ns=2;s=DipData"]
bools = ["ns=2;s=AlternatingBoolean"]

def updateConfig(udtPath, config):
	for item in config['tags']:
		try:
			if str(item["tagType"]) in ["UdtType", "Folder", "UdtInstance"]:
				updateConfig(udtPath + "/" + str(item["path"]), item)
			else:
				itemPath = udtPath + "/" + str(item["path"])
				if str(item["valueSource"]) == "opc":
					dataType = str(system.tag.read(itemPath + ".dataType").value)
					if dataType in ["Int2", "Int4", "Int6"]:
						demoPath = ints[random.randint(0,len(ints) - 1)]
					elif dataType in ["Boolean"]:
						demoPath = ints[random.randint(0,len(ints) - 1)]
					else:
						demoPath = ints[random.randint(0,len(ints) - 1)]
	
					system.tag.write(itemPath + ".OpcItemPath", demoPath)
					system.tag.write(itemPath + ".OpcServer", "OPC_Demo")
		except:
			nil = 1
		
defaultPath = "[default]_types_"
config = system.tag.getConfiguration(defaultPath, True)[0]
updateConfig(defaultPath, config)

```

But in the future I think it would be better if I could write a script to not only iterate through all of my OPC tags, but define a json document like the following that will allow me to simulate all of the OPC tags with the same OpcItemPaths that they are in the production environment. If I can determine where tags are stored in the gateway backups, then I could probably create these tags on startup for the OPC server dockerfile and provide it a copy of the gateway backup as a source.

```auto
{
  "Folder": "MyOpcFolder",
  "NodeList": [
    {
      "NodeId": 1023,
      "Name": "ActualSpeed",
      "Description": "Rotational speed"
    },
    {
      "NodeId": "aRMS"
    },
    {
      "NodeId": "1025",
      "Name": "DKW",
      "DataType": "Float",
      "ValueRank": -1,
      "AccessLevel": "CurrentReadOrWrite",
      "Description": "Diagnostic characteristic value"
    }
  ]
}

```

This is definitely some big-nerd stuff, but I can see it making it much simpler to create a digital twin of your production environment for development purposes.
