Just for posterity, I’ll post my resolution here:
I figured it out, partially through using online validators that were changing the second exposed port from 2222:22 into 133342
It didn’t have anything to do with the lack of spaces before the dashes for the array (though I had several people mention that).
Here’s some trivia, that may help if someone else hits this (which is not beyond possibility):
YAML 1.1 defines what they call a “base 60 float” of the form 12:34:56.90 so it’s basically like hours, minutes, seconds, fractional seconds. But it means that if you happen to be using unquoted strings that happen to only have numbers and colons in them… yaml parsers will assume they’re a float, not a string.
So here’s what was happening: the ruby parser sees 80:80 and realizes that :80 cannot be base 60 (only the first number can be over 60) and so then falls back to it being a string. But it sees 2222:22 and says, right, ok, so that’s like 2222 minutes and 22 seconds, and so thinks it’s 2222*60+22 = 133342 seconds, and thus, that’s what it gets converted into. How that causes discourse/docker to think the port is 8000520, I may never know… probably multiple levels of implicit conversions in wacky and weird ways.
But just in case you ever see anyone with unquoted strings listed for their ports… beware if the port on the right is lower than 60, yaml will assume the whole thing is a float.
The reason the Go parser was fine with this is that it specifically does not support base 60 floats, at least in part because they were eliminated in the yaml 1.2 spec.