¿Por qué un contenedor Docker que ejecuta un servidor expone el puerto al mundo exterior a pesar de que dicho puerto está bloqueado por iptables?


24

Tengo un problema con MySQL ejecutándose dentro de un contenedor Docker. Mi imagen de prueba está construida a partir del siguiente Dockerfile:

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

FROM ubuntu:12.10
MAINTAINER Joni Kahara <joni.kahara@async.fi> 

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

Después de construir una imagen del archivo anterior, la ejecuto con:

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

Después de lo cual todo está bien y puedo iniciar sesión en esta instancia de MySQL desde la máquina local. Sin embargo, también puedo iniciar sesión desde cualquier otra máquina.

He configurado mi firewall para filtrar todo, excepto el tráfico que ingresa a puertos específicos (SSH "oculto", HTTP, HTTPS), y este filtrado de hecho parece funcionar; si, por ejemplo, ejecuto un servidor de desarrollo Django en el puerto 1234, entonces puedo conectarme desde la máquina local, pero no desde afuera. Entonces, el firewall parece estar filtrando paquetes cuando están destinados a un servidor que se ejecuta como un proceso "simple", pero no cuando el servidor se ejecuta dentro de un contenedor.

iptables -L -v --line-numbers dice lo siguiente:

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

La versión de Docker es:

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

¿Por qué el puerto MySQL está expuesto al mundo exterior?

Respuestas:


28

Gracias a los usuarios del canal #docker IRC Michael Crosby y Paul Czar, ahora puedo responder mi propia pregunta. El problema radica en el hecho de que ejecuté el contenedor de esta manera:

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

Esto publica el puerto del contenedor para todas las interfaces de la máquina host, que definitivamente no es lo que estaba buscando en este momento. Para enlazar solo a localhost, era necesario ejecutar el contenedor de la siguiente manera:

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

Además, la EXPOSElínea en Dockerfile no es necesaria ya que el mecanismo de "exposición" se utiliza para vincular contenedores .

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.