2013-07-21 50 views
92

Có thể có các cổng truy cập vùng chứa Docker được máy chủ lưu trữ không? Cụ thể là tôi có MongoDB và RabbitMQ chạy trên máy chủ và tôi muốn chạy một tiến trình trong một thùng chứa Docker để nghe hàng đợi và (tùy chọn) ghi vào cơ sở dữ liệu.Chuyển tiếp cổng máy chủ đến bộ chứa docker

Tôi biết rằng tôi có thể chuyển tiếp từ vùng chứa đến máy chủ (thông qua tùy chọn -p) và tôi có kết nối với thế giới bên ngoài (ví dụ: internet) từ trong vùng chứa Docker nhưng tôi không muốn để lộ Các cảng RabbitMQ và MongoDB từ máy chủ đến thế giới bên ngoài.

EDIT: một số giải thích:

Starting Nmap 5.21 (http://nmap.org) at 2013-07-22 22:39 CEST 
Nmap scan report for localhost (127.0.0.1) 
Host is up (0.00027s latency). 
PORT  STATE SERVICE 
6311/tcp open unknown 

[email protected] ~ % docker run -i -t base /bin/bash 
[email protected]:/# apt-get install nmap 
[email protected]:/# nmap 172.16.42.1 -p 6311 # IP found via docker inspect -> gateway 

Starting Nmap 6.00 (http://nmap.org) at 2013-07-22 20:43 UTC 
Nmap scan report for 172.16.42.1 
Host is up (0.000060s latency). 
PORT  STATE SERVICE 
6311/tcp filtered unknown 
MAC Address: E2:69:9C:11:42:65 (Unknown) 

Nmap done: 1 IP address (1 host up) scanned in 13.31 seconds 

tôi phải làm thủ thuật này để có được bất kỳ kết nối internet withing container: My firewall is blocking network connections from the docker container to outside

EDIT: Cuối cùng tôi đã đi với việc tạo ra một cây cầu tùy chỉnh sử dụng pipework và có các dịch vụ nghe trên IP của cầu. Tôi đã đi với phương pháp này thay vì có MongoDB và RabbitMQ lắng nghe trên cầu docker bởi vì nó cho phép linh hoạt hơn.

Trả lời

35

chủ Docker của bạn cho thấy một bộ chuyển đổi cho tất cả các container. Giả sử bạn đang ở trên ubuntu gần đây, bạn có thể chạy

ip addr 

này sẽ cung cấp cho bạn một danh sách các adapter mạng, một trong số đó sẽ giống như thế

3: docker0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP 
link/ether 22:23:6b:28:6b:e0 brd ff:ff:ff:ff:ff:ff 
inet 172.17.42.1/16 scope global docker0 
inet6 fe80::a402:65ff:fe86:bba6/64 scope link 
    valid_lft forever preferred_lft forever 

Bạn sẽ cần phải nói với thỏ/Mongo để liên kết với IP đó (172.17.42.1). Sau đó, bạn sẽ có thể mở các kết nối đến 172.17.42.1 từ bên trong các thùng chứa của bạn.

+22

Làm cách nào để vùng chứa biết IP cần gửi yêu cầu? Tôi có thể hardcode giá trị (172.17.42.1 ở đây và trên giàn khoan thử nghiệm của tôi, nhưng đó là luôn luôn đúng?), Nhưng điều đó dường như đi ngược lại các nguyên tắc docker làm việc với bất kỳ máy chủ! –

+0

một tùy chọn khác là liên kết dịch vụ máy chủ của bạn (ví dụ mongodb) để nghe trên tất cả các giao diện mạng (ví dụ 0.0.0.0), cấu hình tường lửa của bạn để chỉ các máy trong mạng nội bộ của bạn mới có thể kết nối với các cổng tương ứng và sau đó kết nối với máy chủ địa chỉ IP mạng của máy từ bên trong vùng chứa. – Josh

+1

@Seldo: Giao diện đó có cần cấu hình để hiển thị không? Tôi đang sử dụng docker 1.7.1, và tôi chỉ có 'lo' và' eth0'. – mknecht

4

Nếu MongoDB và RabbitMQ đang chạy trên Máy chủ, thì cổng phải được hiển thị vì nó không nằm trong Docker.

Bạn không cần tùy chọn '-p' để hiển thị các cổng từ vùng chứa đến máy chủ lưu trữ. Theo mặc định, tất cả các cổng được tiếp xúc. Tùy chọn '-p' cho phép bạn hiển thị cổng từ vùng chứa đến bên ngoài máy chủ.

Vì vậy, tôi đoán là bạn không cần phải '-p' chút nào và nó nên được làm việc tốt :)

+0

tôi biết rằng, nhưng có vẻ như tôi là thiếu một chút thông tin: xem chỉnh sửa gần đây, vì tôi không thể tiếp cận các cổng trên máy chủ lưu trữ. – JoelKuiper

+1

Bạn cần thiết lập rabbitmq và mongodb để nghe trên cầu và không chỉ trên giao diện mạng chính của bạn. – creack

+7

@creack làm thế nào để bạn có được thỏmq và mongodb để nghe trên cây cầu? –

66

Cách đơn giản nhưng không an toàn sẽ là sử dụng tùy chọn --net=host để docker run.

Tùy chọn này làm cho nó sao cho vùng chứa sử dụng chồng nối mạng của máy chủ. Sau đó, bạn có thể kết nối với các dịch vụ đang chạy trên máy chủ đơn giản bằng cách sử dụng "localhost" làm tên máy chủ. Điều này dễ cấu hình hơn vì bạn sẽ không phải định cấu hình dịch vụ để chấp nhận các kết nối từ địa chỉ IP của vùng chứa docker của bạn và bạn sẽ không phải thông báo cho bộ chứa docker một địa chỉ IP hoặc tên máy chủ cụ thể kết nối với, chỉ một cổng.

Ví dụ, bạn có thể kiểm tra nó ra bằng cách chạy lệnh sau đây, mà giả hình ảnh của bạn được gọi là my_image, hình ảnh của bạn bao gồm các tiện ích telnet, và các dịch vụ mà bạn muốn kết nối đến là trên cổng 25:

docker run --rm -i -t --net=host my_image telnet localhost 25 

Nếu bạn xem xét làm nó theo cách này, vui lòng xem thận trọng về an ninh trên trang này:

https://docs.docker.com/articles/networking/

nó nói:

--net = host - Yêu cầu Docker bỏ qua việc đặt vùng chứa bên trong ngăn xếp mạng riêng biệt. Về bản chất, sự lựa chọn này cho Docker không chứa mạng của container! Trong khi các quá trình container vẫn sẽ bị giới hạn trong hệ thống tập tin của riêng chúng và danh sách xử lý và giới hạn tài nguyên, một lệnh ip addr nhanh sẽ cho bạn thấy, mạng lưới, họ sống “bên ngoài” trong máy chủ Docker chính và có quyền truy cập đầy đủ vào các giao diện mạng của nó. . Lưu ý rằng điều này không cho phép thùng chứa cấu hình lại ngăn xếp mạng máy chủ - điều đó sẽ yêu cầu --privileged = true - nhưng nó cho phép các quá trình container mở các cổng số thấp giống như bất kỳ quá trình gốc nào khác. Nó cũng cho phép container truy cập các dịch vụ mạng nội bộ như D-bus. Điều này có thể dẫn đến các quy trình trong vùng chứa có thể thực hiện những việc không mong muốn như khởi động lại máy tính của bạn. Bạn nên sử dụng tùy chọn này một cách thận trọng.

+7

Đối với bất kỳ ai không sử dụng docker trên Linux (ví dụ: sử dụng một số ảo hóa) điều này sẽ không hoạt động, vì máy chủ sẽ là máy ảo chứa, chứ không phải là hệ điều hành máy chủ thực. –

+3

Đặc biệt, trên MacOS, điều này ** là không thể ** (không có một số cách giải quyết): https://docs.docker.com/docker-for-mac/networking/#i-want-to-connect-from- a-container-to-a-dịch vụ-trên-máy chủ lưu trữ – pje

4

Bạn cũng có thể tạo đường hầm ssh.

docker-compose.yml:

--- 

version: '2' 

services: 
    kibana: 
    image: "kibana:4.5.1" 
    links: 
     - elasticsearch 
    volumes: 
     - ./config/kibana:/opt/kibana/config:ro 

    elasticsearch: 
    build: 
     context: . 
     dockerfile: ./docker/Dockerfile.tunnel 
    entrypoint: ssh 
    command: "-N elasticsearch -L 0.0.0.0:9200:localhost:9200" 

docker/Dockerfile.tunnel:

FROM buildpack-deps:jessie 

RUN apt-get update && \ 
    DEBIAN_FRONTEND=noninteractive \ 
    apt-get -y install ssh && \ 
    apt-get clean && \ 
    rm -rf /var/lib/apt/lists/* 

COPY ./config/ssh/id_rsa /root/.ssh/id_rsa 
COPY ./config/ssh/config /root/.ssh/config 
COPY ./config/ssh/known_hosts /root/.ssh/known_hosts 
RUN chmod 600 /root/.ssh/id_rsa && \ 
    chmod 600 /root/.ssh/config && \ 
    chown $USER:$USER -R /root/.ssh 

config/ssh/config:

# Elasticsearch Server 
Host elasticsearch 
    HostName jump.host.czerasz.com 
    User czerasz 
    ForwardAgent yes 
    IdentityFile ~/.ssh/id_rsa 

Bằng cách này, elasticsearch có một đường hầm đến máy chủ với các dịch vụ đang chạy (Elasticsearch, MongoDB, PostgreSQL) và phơi bày po rt 9200 với dịch vụ đó.

+0

Về cơ bản, bạn đang đặt khóa cá nhân trong hình ảnh Docker. Bí mật không bao giờ nên vào hình ảnh Docker. –

1

Tôi đã gặp phải sự cố tương tự khi truy cập Máy chủ LDAP từ vùng chứa docker. Tôi đặt IP cố định cho vùng chứa và thêm quy tắc tường lửa.

docker-compose.yml:

version: '2' 
services: 
    containerName: 
    image: dockerImageName:latest 
    extra_hosts: 
     - "dockerhost:192.168.50.1" 
    networks: 
     my_net: 
     ipv4_address: 192.168.50.2 
networks: 
    my_net: 
    ipam: 
     config: 
     - subnet: 192.168.50.0/24 

iptables quy tắc:

iptables -A INPUT -j ACCEPT -p tcp -s 192.168.50.2 -d $192.168.50.1 --dport portnumberOnHost

Bên trong truy cập chứa dockerhost:portnumberOnHost

Các vấn đề liên quan