ทำไมคอนเทนเนอร์ Docker ที่ใช้เซิร์ฟเวอร์เปิดเผยพอร์ตสู่โลกภายนอกแม้ว่าจะกล่าวว่าพอร์ตนั้นถูกบล็อกโดย iptables


24

ฉันมีปัญหากับ MySQL ที่ทำงานอยู่ในคอนเทนเนอร์ Docker ภาพทดสอบของฉันสร้างขึ้นจาก 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"]

หลังจากสร้างภาพจากไฟล์ด้านบนแล้วฉันก็รันด้วย:

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

หลังจากนั้นทุกอย่างก็จะบวมและฉันสามารถเข้าสู่อินสแตนซ์ของ MySQL จากเครื่องโลคอล อย่างไรก็ตามฉันสามารถล็อกอินจากเครื่องอื่นได้

ฉันได้ตั้งค่าไฟร์วอลล์เพื่อกรองทุกอย่างยกเว้นทราฟฟิกที่เข้ามาในพอร์ตเฉพาะ ("ซ่อน" SSH, HTTP, HTTPS) และการกรองนี้ใช้งานได้จริง ถ้าฉันรันเซิร์ฟเวอร์การพัฒนา Django บนพอร์ต 1234 จากนั้นฉันสามารถเชื่อมต่อจากเครื่องท้องถิ่น แต่ไม่ใช่จากภายนอก ดังนั้นดูเหมือนว่าไฟร์วอลล์จะกรองแพ็กเก็ตเมื่อเซิร์ฟเวอร์ถูกกำหนดให้ทำงานเป็นกระบวนการ "ธรรมดา" แต่ไม่ใช่เมื่อเซิร์ฟเวอร์ทำงานภายในคอนเทนเนอร์

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

เวอร์ชันของนักเทียบท่าคือ:

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 จึงถูกเปิดเผยกับโลกภายนอก?

คำตอบ:


28

ขอบคุณผู้ใช้งาน #docker IRC channel Michael Crosby และ Paul Czar ตอนนี้ฉันสามารถตอบคำถามของฉันเองได้แล้ว ปัญหาอยู่ที่ข้อเท็จจริงที่ว่าฉันวิ่งไปที่ภาชนะเช่นนี้:

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

สิ่งนี้เผยแพร่พอร์ตของคอนเทนเนอร์ไปยังอินเทอร์เฟซทั้งหมดของเครื่องโฮสต์ซึ่งไม่ใช่สิ่งที่ฉันกำลังมองหาในเวลานี้ ในการผูกกับโลคัลโฮสต์เท่านั้นจำเป็นต้องเรียกใช้คอนเทนเนอร์ดังนี้:

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

นอกจากนี้ยังมีEXPOSEสายใน Dockerfile ไม่จำเป็นต้องเป็น "เผย" กลไกที่ใช้ในการภาชนะบรรจุที่เชื่อมโยง

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.