A Docker footgun led to a vandal deleting NewsBlur's MongoDB database
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: <a href="https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=27613217" rel="nofollow">https:&#x2F;&#x2F;news.ycombinator.com&#x2F;item?id=27613217</a><p>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: <a href="https:&#x2F;&#x2F;github.com&#x2F;moby&#x2F;moby&#x2F;issues&#x2F;4737" rel="nofollow">https:&#x2F;&#x2F;github.com&#x2F;moby&#x2F;moby&#x2F;issues&#x2F;4737</a><p>Furthermore, it also seems to me, that not only Docker should respect the firewall rules (even though it&#x27;d confuse another group of people about why their services aren&#x27;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!<p>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.<p>For example, see the following example of a Compose file, which would only expose a web server to the world:<p><pre><code>  version: &#x27;3.4&#x27;
  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&#x27;re using Docker networking
    mongodb_container:
      image: mongo:bionic
      restart: &quot;unless-stopped&quot;
      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:&#x2F;&#x2F;hub.docker.com&#x2F;_&#x2F;mongo
      deploy:
        replicas: 1
        placement:
          constraints:
            - node.hostname == your-mongo-server.com # just an example, probably use labels instead
        resources:
          limits:
            cpus: &quot;4&quot;
            memory: &quot;8G&quot;
    # your web application wouldn&#x27;t need to be exposed to the outside world either
    # it could just receive the requests from a web server that ensures SSL&#x2F;TLS
    web_application:
      image: hello-world # which you would replace with your actual app
      restart: &quot;unless-stopped&quot;
      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: &quot;2&quot;
            memory: &quot;2G&quot;
    # finally, the actual web server is the ingress point, which you can self host
    # in the case of Kubernetes and other fancy tech you&#x27;d be able to use external solutions, probably
    web_server:
      image: caddy:alpine # or another web server, that would actually be exposed
      restart: &quot;unless-stopped&quot;
      ports:
        - 80:80
        - 443:443
        # though sometimes you need the long format for the above so client IPs resolve correctly
      volumes:
        - some_config_directory:&#x2F;etc&#x2F;caddy&#x2F;Caddyfile
        - some_other_config_directory:&#x2F;data
        - yet_another_config_directory:&#x2F;config
      deploy:
        replicas: 4
        placement:
            constraints:
            - node.hostname == your-ingress-server.com # just an example, probably use labels instead
        resources:
          limits:
            cpus: &quot;2&quot;
            memory: &quot;2G&quot;
</code></pre>
That&#x27;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.<p>Docker even has a page on networking, that provides information about the additional functionality that&#x27;s available as well: <a href="https:&#x2F;&#x2F;docs.docker.com&#x2F;network&#x2F;" rel="nofollow">https:&#x2F;&#x2F;docs.docker.com&#x2F;network&#x2F;</a><p>Of course, that&#x27;s not to say that defense in depth and external solutions wouldn&#x27;t perhaps be a better option.