Regras iptables corretas para permitir a vinculação de contêineres do Docker

1

Eu tenho dois contêineres do Docker em um nó Debian 8.3. Uma é a imagem oficial do postgres, uma é um aplicativo básico de fênix / elixir. Eu estou ligando ambos com um arquivo de pilha do docker. Mas phoenix não é capaz de se conectar ao postgres, a menos que eu publique a porta. Isso me permite pensar que algo com a rede docker interna está errado e como o nó é uma nova instalação Debian, pode ser o iptables. Também meio que exclui que a senha ou o nome do host esteja errado.

O que estou fazendo errado e qual é a maneira correta de configurar as regras do iptables para permitir que dois contêineres se comuniquem?

Mensagem de erro no aplicativo phoenix:

app-1 | 2016-03-15T16:15:18.019402549Z ** (Mix) The database for App.Repo couldn't be created, reason given: psql: could not connect to server: Connection refused
app-1 | 2016-03-15T16:15:18.019456447Z  Is the server running on host "postgres" (10.7.0.1) and accepting
app-1 | 2016-03-15T16:15:18.019468609Z  TCP/IP connections on port 5432?

Saída do arquivo de log no container postgres

postgres-1 | 2016-03-15T16:46:32.457844697Z LOG:  MultiXact member wraparound protections are now enabled
postgres-1 | 2016-03-15T16:46:32.464806051Z LOG:  database system is ready to accept connections
postgres-1 | 2016-03-15T16:46:32.465087076Z LOG:  autovacuum launcher started

Meu arquivo de pilha do Docker

app:
  image: myrepo/app
  environment:
    POSTGRES_USER: postgres
    POSTGRES_PASSWORD: postgrespassword
    PORT: 4000
  links:
    - postgres
  ports:
    - 80:4000
postgres:
  image: postgres:9.5
  environment:
    POSTGRES_USER: postgres
    POSTGRES_PASSWORD: postgrespassword
  volumes:
    - /var/dbdata:/var/lib/postgresql/data

Configuração do banco de dados no Phoenix App (prod.secret.exs)

config :data_bucket, DataBucket.Repo,
  adapter: Ecto.Adapters.Postgres,
  username: System.get_env("POSTGRES_USER"),
  password: System.get_env("POSTGRES_PASSWORD"),
  database: "app_prod",
  hostname: "postgres",
  pool_size: 20

Resultado de $ sudo iptables -L

Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere
REJECT     all  --  anywhere             loopback/8           reject-with icmp-port-unreachable
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:http
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:https
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:2375
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:6783
ACCEPT     udp  --  anywhere             anywhere             udp dpt:6783
ACCEPT     tcp  --  anywhere             anywhere             state NEW tcp dpt:ssh
ACCEPT     icmp --  anywhere             anywhere             icmp echo-request
LOG        all  --  anywhere             anywhere             limit: avg 5/min burst 5 LOG level debug prefix "iptables denied: "
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable
DROP       tcp  --  anywhere             172.17.0.1           tcp dpt:6783
DROP       udp  --  anywhere             172.17.0.1           udp dpt:6783
DROP       udp  --  anywhere             172.17.0.1           udp dpt:6784
ACCEPT     udp  --  anywhere             anywhere             udp dpt:domain
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:domain

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
DROP       all  --  anywhere             anywhere
DROP       all  --  anywhere             anywhere
DOCKER     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere             ctstate RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     all  --  anywhere             anywhere
REJECT     all  --  anywhere             anywhere             reject-with icmp-port-unreachable
ACCEPT     all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere

Chain DOCKER (1 references)
target     prot opt source               destination

Resultado de $ sudo docker version

Client:
 Version:      1.9.1-cs2
 API version:  1.21
 Go version:   go1.4.3
 Git commit:   4ade326
 Built:        Mon Nov 30 21:56:07 UTC 2015
 OS/Arch:      linux/amd64

Server:
 Version:      1.9.1-cs2
 API version:  1.21
 Go version:   go1.4.3
 Git commit:   4ade326
 Built:        Mon Nov 30 21:56:07 UTC 2015
 OS/Arch:      linux/amd64

Resultado de sudo docker ps :

CONTAINER ID        IMAGE                   COMMAND                  CREATED             STATUS              PORTS                  NAMES
f113435b781b        myrepo/app:latest       "elixir --erl '-smp d"   35 seconds ago      Up 34 seconds       0.0.0.0:80->4000/tcp   app-1.App.15ffa2c2
6e2879fd9f2c        postgres:9.5            "/docker-entrypoint.s"   37 minutes ago      Up 5 minutes        5432/tcp               postgres-1.App.cbe400ac

Para a última saída: A Phoenix App, claro, só começa se eu não executar migrações. Normalmente, isso é no final do meu Dockerfile:

CMD ["elixir", "--erl", "-smp disable", "/usr/local/bin/mix", "do", "compile", ",", "ecto.create", ",", "ecto.migrate", ",", "phoenix.server"]

Que eu mudei para o seguinte para obter este resultado

CMD ["elixir", "--erl", "-smp disable", "/usr/local/bin/mix", "do", "compile", ",", "phoenix.server"]
    
por Øle Bjarnstroem 15.03.2016 / 17:56

1 resposta

0

Eu encontrei a solução: O problema eram as configurações do iptables. Eu tinha uma regra para desistir de todos os encaminhamentos, a menos que definido de outra forma:

-A FORWARD -j REJECT

Livrar-se desta regra foi a solução.

Editar:

Como @Zoredache apontou, apenas excluir a regra é obviamente uma má ideia e eu sou um idiota. A maneira correta é colocá-lo no final da cadeia de regras, após as regras criadas pela janela de encaixe. Então, se você tiver o mesmo problema, isso funciona para mim:

Livrar-se da regra

$ sudo iptables -D FORWARD -j REJECT

Adicione novamente para movê-lo para o final do conjunto

$ sudo iptables -A FORWARD -j REJECT

Verifique se eles estão na ordem correta. Assim, a regra de rejeitar tudo mais deve estar no final.

$ sudo iptables -v -L FORWARD

No Debian, é assim que você pode garantir que as regras ainda se aplicam ao reiniciar o servidor :

Quando estiver satisfeito, salve as novas regras no arquivo mestre do iptables:

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

Para garantir que as regras do iptables sejam iniciadas em uma reinicialização, criaremos um novo arquivo:

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

Adicione estas linhas a ele:

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

O arquivo precisa ser executável, então altere as permissões:

$ sudo chmod +x /etc/network/if-pre-up.d/iptables
    
por 15.03.2016 / 21:11