更正 iptables 规则以允许链接 docker 容器

更正 iptables 规则以允许链接 docker 容器

我在 Debian 8.3 节点上有两个 Docker 容器。一个是官方的 postgres 镜像,一个是基本的 phoenix / elixir 应用程序。我用 docker 堆栈文件链接了这两个容器。但是,除非我发布端口,否则 phoenix 无法连接到 postgres。这让我认为内部 docker 网络出了问题,而且由于该节点是全新安装的 Debian,所以可能是 iptables 出了问题。这也排除了密码或主机名错误的可能性。

我做错了什么?设置 iptables 规则以允许两个容器进行通信的正确方法是什么?

凤凰应用程序中的错误信息:

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?

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

我的 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

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

的结果$ 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

的结果$ 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

的结果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

对于最后一个输出:Phoenix App 当然只有在我不运行迁移时才会启动。通常这在我的 Dockerfile 的末尾:

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

我将其更改为以下内容以获得此输出

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

答案1

我找到了解决方案:问题出在 iptables 设置上。我在其中设置了一条规则,除非另有定义,否则将放弃所有转发:

-A FORWARD -j REJECT

解决方案就是废除这条规则。

编辑:

正如 @Zoredache 指出的那样,直接删除规则显然是个坏主意,我是个白痴。正确的方法是将其放在规则链的最末端,在 docker 创建的规则之后。所以如果你有同样的问题,这对我来说是有效的:

摆脱规则

$ sudo iptables -D FORWARD -j REJECT

再次添加以将其移动到集合末尾

$ sudo iptables -A FORWARD -j REJECT

确保它们的顺序正确。因此,拒绝所有其他规则应该放在最后。

$ sudo iptables -v -L FORWARD

在 Debian 上,你可以这样确保规则在重启服务器时仍然适用

一旦您满意,将新规则保存到主 iptables 文件中:

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

为了确保 iptables 规则在重启时启动,我们将创建一个新文件:

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

添加以下几行:

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

该文件需要可执行,因此请更改权限:

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

相关内容