The following answer is supposing that you need two separate domains for whatever reason, different smoke resolutions or behaviours, different effectors etc. If you only need two different smoke colors, you can achieve this with one domain, I'll give a simple answer below.
Two domains: Since all spheres are Flow objects, the smoke for all of them gets calculated by both domains. So there are 8 spheres simulated and get a red material, and in the same location the same 8 spheres get simulated and rendered with a blue material - so mixed together the smoke is violet.
To tell the domains which spheres they should simulate and which not, you can use Collections. In the domain settings you can select which collections should be used for Flow and which for Effectors. So the spheres that should emit red smoke have to be in one collection, the spheres for blue smoke in another - and you select them in the domain settings.
And you should specify separate paths for the caches, because otherwise simulating one domain might overwrite the other domain's data.
Another thing I noticed is that in one smoke material you've plugged the Density from the Volume Info into Emission Strength, this creates white emission which also mixes with your smoke color.
One domain: To use different colors on different flow objects, you can set them directly in the Flow Settings under Smoke Color. To get them rendered you can either set the Color Attribute "color" in the Principled Volume with the node's color set to white, or leave the attribute value empty and plug the Color output of the Volume Info node into the Color input of the Principled Volume.
With one domain you have to keep a few things in mind:
- The Smoke Color set in the flow objects will be baked in the simulation and cannot be changed in the material afterwards.
- You can either use the Color Attribute "color" in the Principled Volume node or plug the Color output from the Volume Info node into the Color input of the Principled Volume node. If you are using both, the color input and attribute, this will result in multiplying both colors which might give unwanted color. This doesn't matter much in your case where the RGB channels each have either 0 or 1 as value, but for any other values this will make a difference.
- This multiplying of colors also takes places if you only use the attribute "color" without the Volume Info, in this case the flow object's Smoke Color will be multiplied by the Color in the Principled Volume node - which is why you should set it to full white instead of the default grey, as @vklidu does in his example, or otherwise the smoke color gets darkened (or colored differently if you set other colors than greyscales).
- Since colors can be multiplied, this surely is a way smoke colors can be changed after baking simulation other than stated under 1., but it is limited and always based on the original baked smoke colors.