Props to the developer for being this open and letting others learn and discuss the implications of this situation! I rather enjoyed the original discussion as well, even though the situation itself was unfortunate: https://news.ycombinator.com/item?id=27613217

I agree with the other posters, that Docker can cause problems with firewalls, as pointed out both in the article, in the GitHub issue, and in the other thread as well: https://github.com/moby/moby/issues/4737

Furthermore, it also seems to me, that not only Docker should respect the firewall rules (even though it'd confuse another group of people about why their services aren't accessible externally and would necessitate manual firewall rule management, short of some explicit way to do that, such as docker run ... -p 80:3000 --expose-in-firewall 80 ...) and that MongoDB also should have secure defaults, as any other piece of software!

That said, at least to me it appears that Docker Compose, Docker Swarm and other technologies have attempted to introduce a networking abstraction to allow running services (more) securely and privately, by not exposing their ports on the host directly.

For example, see the following example of a Compose file, which would only expose a web server to the world:

version: '3.4'
services:
# you would probably want to run MongoDB not exposed to the outside world at all
# notice that there are no ports exposed here, given that we're using Docker networking
mongodb_container:
image: mongo:bionic
restart: "unless-stopped"
environment:
- MONGO_INITDB_ROOT_USERNAME=lazy_example_of_a_single_file_config
- MONGO_INITDB_ROOT_PASSWORD=but_you_should_be_able_to_store_this_in_secrets
# see docs for MONGO_INITDB_ROOT_PASSWORD_FILE at https://hub.docker.com/_/mongo
deploy:
replicas: 1
placement:
constraints:
- node.hostname == your-mongo-server.com # just an example, probably use labels instead
resources:
limits:
cpus: "4"
memory: "8G"
# your web application wouldn't need to be exposed to the outside world either
# it could just receive the requests from a web server that ensures SSL/TLS
web_application:
image: hello-world # which you would replace with your actual app
restart: "unless-stopped"
environment:
- APP_CONFIG=variables_go_here_or_in_a_config_map
- MONGO_HOST=mongodb_container
- MONGO_PORT=27017
- MONGO_USERNAME=either_the_username_above_or_a_non_root_one
- MONGO_PASSWORD=though_the_non_root_needs_separate_creation
# maybe with a helper container, like some people use dbmate for RDBMS
deploy:
replicas: 4
placement:
constraints:
- node.hostname == your-application-server.com # just an example, probably use labels instead
resources:
limits:
cpus: "2"
memory: "2G"
# finally, the actual web server is the ingress point, which you can self host
# in the case of Kubernetes and other fancy tech you'd be able to use external solutions, probably
web_server:
image: caddy:alpine # or another web server, that would actually be exposed
restart: "unless-stopped"
ports:
- 80:80
- 443:443
# though sometimes you need the long format for the above so client IPs resolve correctly
volumes:
- some_config_directory:/etc/caddy/Caddyfile
- some_other_config_directory:/data
- yet_another_config_directory:/config
deploy:
replicas: 4
placement:
constraints:
- node.hostname == your-ingress-server.com # just an example, probably use labels instead
resources:
limits:
cpus: "2"
memory: "2G"

That's not to say that everyone should use Swarm or other orchestrators, but personally i find it a good approach, which allows defining some of the network topology in the same file as the application deployment, thus making the risk of human error slightly smaller.

Docker even has a page on networking, that provides information about the additional functionality that's available as well: https://docs.docker.com/network/

Of course, that's not to say that defense in depth and external solutions wouldn't perhaps be a better option.