Warum macht ein Docker-Container, auf dem ein Server ausgeführt wird, den Port der Außenwelt zugänglich, obwohl dieser Port von iptables blockiert wird?

24

Ich habe ein Problem mit MySQL, das in einem Docker-Container ausgeführt wird. Mein Test-Image wird aus der folgenden Docker-Datei erstellt:

# 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"]

Nachdem ich ein Bild aus der obigen Datei erstellt habe, starte ich es mit:

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

Danach ist alles in Ordnung und ich kann mich von der lokalen Maschine aus bei dieser Instanz von MySQL anmelden. Ich kann mich aber auch von jedem anderen Rechner aus einloggen.

Ich habe meine Firewall so eingerichtet, dass sie alles filtert, außer den Datenverkehr, der an bestimmten Ports eingeht ("verstecktes" SSH, HTTP, HTTPS), und diese Filterung scheint tatsächlich zu funktionieren. Wenn ich zum Beispiel einen Django-Entwicklungsserver auf Port 1234 betreibe, kann ich eine Verbindung vom lokalen Computer aus herstellen, aber nicht von außerhalb. Die Firewall scheint also Pakete zu filtern, wenn sie für einen Server bestimmt sind, der als "einfacher" Prozess ausgeführt wird, nicht jedoch, wenn der Server in einem Container ausgeführt wird.

iptables -L -v --line-numbers sagt Folgendes:

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-Version ist:

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

Warum ist der MySQL-Port der Außenwelt ausgesetzt?

kahara
quelle

Antworten:

28

Dank der Benutzer von #docker IRC-Kanälen, Michael Crosby und Paul Czar, kann ich jetzt meine eigene Frage beantworten. Das Problem liegt in der Tatsache, dass ich den Container folgendermaßen ausgeführt habe:

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

Dadurch wird der Port des Containers für alle Schnittstellen des Host-Computers veröffentlicht, was zu diesem Zeitpunkt definitiv nicht das ist, wonach ich gesucht habe. Um nur an localhost zu binden, musste der Container wie folgt ausgeführt werden:

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

Auch die EXPOSEZeile in Dockerfile ist nicht erforderlich, da der "Expose" -Mechanismus zum Verknüpfen von Containern verwendet wird .

kahara
quelle