为什么运行服务器的 Docker 容器会将端口暴露给外界,即使该端口已被 iptables 阻止?

为什么运行服务器的 Docker 容器会将端口暴露给外界,即使该端口已被 iptables 阻止?

我在 Docker 容器内运行 MySQL 时遇到问题。我的测试映像是根据以下 Dockerfile 构建的:

# See: https://index.docker.io/u/brice/mysql/

FROM ubuntu:12.10
MAINTAINER Joni Kahara <[email protected]> 

# Because docker replaces /sbin/init: https://github.com/dotcloud/docker/issues/1024
RUN dpkg-divert --local --rename --add /sbin/initctl
RUN ln -s /bin/true /sbin/initctl

RUN apt-get update
RUN apt-get upgrade -y

RUN apt-get -y install mysql-server

RUN sed -i -e"s/^bind-address\s*=\s*127.0.0.1/bind-address = 0.0.0.0/" /etc/mysql/my.cnf

RUN /usr/bin/mysqld_safe & \
    sleep 10s && \
    mysql -e "GRANT ALL ON *.* to 'root'@'%'; FLUSH PRIVILEGES;"

EXPOSE 3306

VOLUME ["/var/lib/mysql", "/var/log/mysql"]

CMD ["mysqld_safe"]

从上面的文件构建图像后,我使用以下命令运行它:

docker run -p 3306:3306 asyncfi/magento-mysql

之后一切顺利,我可以从本地机器登录到这个 MySQL 实例。但是,我也可以从任何其他机器登录。

我已经设置了防火墙来过滤除进入特定端口(“隐藏” SSH、HTTP、HTTPS)的流量之外的所有流量,而且这种过滤似乎确实有效;例如,如果我在端口 1234 上运行 Django 开发服务器,那么我可以从本地计算机连接,但不能从外部连接。因此,当数据包发往以“普通”进程运行的服务器时,防火墙似乎会过滤数据包,但当服务器在容器内运行时,防火墙不会过滤数据包。

iptables -L -v --line-numbers 表示以下内容:

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     2265  107K ACCEPT     all  --  lo     any     anywhere             anywhere
2     240K  319M ACCEPT     all  --  any    any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
3       14  1040 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:<REDACTED>
4       21  1092 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:http
5        6   360 ACCEPT     tcp  --  any    any     anywhere             anywhere             tcp dpt:https
6      538 34656 LOG        all  --  any    any     anywhere             anywhere             limit: avg 5/min burst 5 LOG level debug prefix "iptables DROP: "
7      551 35424 DROP       all  --  any    any     anywhere             anywhere

Chain FORWARD (policy ACCEPT 5 packets, 296 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1        0     0 ACCEPT     all  --  docker0 docker0  anywhere             anywhere
2     6752  396K ACCEPT     all  --  docker0 !docker0  anywhere             anywhere
3     125K  188M ACCEPT     all  --  any    docker0  anywhere             anywhere             ctstate RELATED,ESTABLISHED

Chain OUTPUT (policy ACCEPT 51148 packets, 14M bytes)
num   pkts bytes target     prot opt in     out     source               destination

Docker 版本是:

Client version: 0.7.3
Go version (client): go1.2
Git commit (client): 8502ad4
Server version: 0.7.3
Git commit (server): 8502ad4
Go version (server): go1.2
Last stable version: 0.7.3

MySQL端口为什么要暴露给外界呢?

答案1

感谢 #docker IRC 频道用户 Michael Crosby 和 Paul Czar,我现在可以回答我自己的问题了。问题在于我是这样运行容器的:

docker run -p 3306:3306 asyncfi/magento-mysql

这会将容器的端口发布到所有接口主机,这绝对不是我此时想要的。要仅绑定到本地主机,必须按如下方式运行容器:

docker run -p 127.0.0.1:3306:3306 asyncfi/magento-mysql

此外,EXPOSEDockerfile 中的这一行也是不必要的,因为“expose”机制用于链接容器

相关内容