Search code examples
postgresqldockerphoenix-frameworkdocker-cloud

Docker: How to connect to Postgresql container without exposing port


I set up an Elixir / Phoenix app in a docker container and a separate container for a Postgresql server. I can only connect to the Postgresql server when I expose the 5432 port. But I don't want the port to be public since this is pretty unsafe. The Postgresql server should only be accessible from the phoenix container.

But if I don't expose the port I just get an "Connection refused" error in the phoenix container.

app-phoenix-1 | 2016-03-15T11:41:32.701295542Z ** (Mix) The database for App.Repo couldn't be created, reason given: psql: could not connect to server: Connection refused
app-phoenix-1 | 2016-03-15T11:41:32.701369511Z  Is the server running on host "POSTGRES" (10.7.0.7) and accepting
app-phoenix-1 | 2016-03-15T11:41:32.701395350Z  TCP/IP connections on port 5432?

I linked the service and don't get, why it isn't working. Postgresql is up and running.

There is nothing in the log files of the Postgres Container.

This is the result of docker ps on my node:

8204a82ca192        myrepo/app       "elixir --erl '-smp d"   37 seconds ago      Up Less than a second   0.0.0.0:80->4000/tcp   app-phoenix-1.585afb94
7a4dded80c36        postgres:latest  "/docker-entrypoint.s"   2 hours ago         Up 10 minutes           5432/tcp               postgres-1.aed0697d

Somehow the Postgres container is blocking all connections from my phoenix container. Any clue how to fix this?


Solution

  • I found the solution: The problem were the iptables settings. I had a rule in there to drop all forwarding unless otherwise defined:

    -A FORWARD -j REJECT
    

    This rule was at the wrong position in the filter chain. The right way is to put it at the very end of the filter chain, after the rules created by docker. So if you have the same problem, this works for me:

    Get rid of the rule

    $ sudo iptables -D FORWARD -j REJECT
    

    Add it again to move it to the end of the set

    $ sudo iptables -A FORWARD -j REJECT
    

    Make sure they are in the right order. So the reject all else rule should be at the very end.

    $ sudo iptables -v -L FORWARD
    

    On Debian this is how you can make sure the rules still apply when restarting the server:

    Once you are happy, save the new rules to the master iptables file:

    $ iptables-save > /etc/iptables.up.rules
    

    To make sure the iptables rules are started on a reboot we'll create a new file:

    $ editor /etc/network/if-pre-up.d/iptables
    

    Add these lines to it:

    #!/bin/sh
    /sbin/iptables-restore < /etc/iptables.up.rules
    

    The file needs to be executable so change the permissions:

    $ sudo chmod +x /etc/network/if-pre-up.d/iptables
    

    Edit: Just removing the rule is a bad idea.