Inoltra la porta host al contenitore della finestra mobile


167

È possibile avere porte di accesso al contenitore Docker aperte dall'host? Concretamente ho MongoDB e RabbitMQ in esecuzione sull'host e mi piacerebbe eseguire un processo in un contenitore Docker per ascoltare la coda e (facoltativamente) scrivere sul database.

So di poter inoltrare una porta dal container all'host (tramite l'opzione -p) e avere una connessione al mondo esterno (cioè internet) dall'interno del container Docker ma mi piacerebbe non esporre le porte RabbitMQ e MongoDB dall'host al mondo esterno.

EDIT: alcuni chiarimenti:

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

joelkuiper@vps20528 ~ % docker run -i -t base /bin/bash
root@f043b4b235a7:/# apt-get install nmap
root@f043b4b235a7:/# 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

Ho dovuto fare questo trucco per ottenere qualsiasi connessione Internet all'interno del contenitore: il mio firewall sta bloccando le connessioni di rete dal contenitore docker all'esterno

EDIT : Alla fine sono andato con la creazione di un bridge personalizzato usando pipework e facendo in modo che i servizi fossero in ascolto sugli IP del bridge. Ho seguito questo approccio invece di far ascoltare MongoDB e RabbitMQ sul bridge docker perché offre maggiore flessibilità.

Risposte:


54

L'host docker espone un adattatore a tutti i contenitori. Supponendo che tu sia su Ubuntu recente, puoi eseguire

ip addr

Questo ti darà un elenco di adattatori di rete, uno dei quali avrà un aspetto simile

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

Dovrai dire a coniglio / mongo di legarsi a quell'IP (172.17.42.1). Successivamente, dovresti essere in grado di aprire le connessioni a 172.17.42.1 dall'interno dei tuoi contenitori.


35
Come fa il container a sapere a quale IP inviare le richieste? Posso codificare il valore (172.17.42.1 qui e sul mio banco di prova, ma è sempre vero?), Ma questo sembra andare contro i principi docker di lavorare con qualsiasi host!
JP.

2
@Seldo: l'interfaccia deve essere configurata per essere visualizzata? Sto usando la finestra mobile 1.7.1, e ho solo loe eth0.
mknecht,

8
È possibile farlo in qualche modo, se l'host è in ascolto solo su 127.0.0.1?
HansHarhoff,

5
"Dovrai dire a rabbit / mongo di legarsi a quell'IP (172.17.42.1). Successivamente, dovresti essere in grado di aprire le connessioni a 172.17.42.1 dai tuoi contenitori." Sarebbe bello se mi spiegassi come farlo
Novaterata

1
Come menzionato @Novaterata, qualcuno può spiegare questo processo?
keskinsaf,

122

Un modo semplice ma relativamente insicuro sarebbe usare l' --net=hostopzione per docker run.

Questa opzione consente al contenitore di utilizzare lo stack di rete dell'host. Quindi è possibile connettersi ai servizi in esecuzione sull'host semplicemente usando "localhost" come nome host.

È più facile da configurare perché non sarà necessario configurare il servizio per accettare connessioni dall'indirizzo IP del contenitore docker e non sarà necessario comunicare al contenitore docker un indirizzo IP o un nome host specifico a cui connettersi, solo un porto.

Ad esempio, è possibile provarlo eseguendo il comando seguente, che presuppone che l'immagine venga chiamata my_image, l'immagine include l' telnetutilità e il servizio a cui si desidera connettersi si trova sulla porta 25:

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

Se consideri di farlo in questo modo, consulta le precauzioni sulla sicurezza in questa pagina:

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

Dice:

--net = host - Indica a Docker di saltare il posizionamento del contenitore all'interno di uno stack di rete separato. In sostanza, questa scelta dice a Docker di non containerizzare le reti del container! Mentre i processi container saranno ancora limitati al proprio filesystem, alla lista processi e ai limiti delle risorse, un rapido comando ip addr ti mostrerà che, per quanto riguarda la rete, vivono "all'esterno" nell'host Docker principale e hanno pieno accesso alle sue interfacce di rete . Si noti che ciò non consente al contenitore di riconfigurare lo stack della rete host - ciò richiederebbe --privileged = true - ma consente ai processi contenitore di aprire porte a basso numero come qualsiasi altro processo root. Inoltre, consente al contenitore di accedere ai servizi di rete locale come D-bus. Questo può portare a processi nel contenitore in grado di fare cose inaspettate come riavviare il computer.


12
Per chiunque non utilizzi la finestra mobile su Linux (ad es. Utilizzando un po 'di virtualizzazione) questo non funzionerà, poiché l'host sarà la VM contenente, non il sistema operativo host effettivo.
Sebastian Graf,

13
In particolare, su MacOS, ciò non è possibile (senza alcune soluzioni alternative): docs.docker.com/docker-for-mac/networking/…
pje

15
Su MacOS, --net=hostnon funziona per consentire al processo contenitore di connettersi al computer host tramite localhost. Invece, fai connettere il tuo contenitore allo speciale nome host MacOS docker.for.mac.host.internalinvece di localhost. Non sono necessari parametri aggiuntivi docker runper farlo funzionare. Puoi inviarlo come un var env usando -ese vuoi mantenere agnostica la tua piattaforma container. In questo modo è possibile connettersi all'host indicato in env var e passare docker.for.mac.host.internalsu MacOS e localhostsu Linux.
Tul

18
l'ultimo hostname per mac è host.docker.internal, vedi doc
xysun

Lo stesso per Windows docker run --rm -it --net=host postgres bashallorapsql -h host.docker.internal -U postgres
Leo Cavalcante

12

Puoi anche creare un tunnel 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

In questo modo elasticsearchha un tunnel al server con il servizio in esecuzione (Elasticsearch, MongoDB, PostgreSQL) ed espone la porta 9200 con quel servizio.


8
In pratica stai inserendo la chiave privata nell'immagine Docker. I segreti non dovrebbero mai entrare in un'immagine Docker.
Teoh Han Hui,

2
Questa è l'unica soluzione utilizzabile finora.
elvete,

5

Ho avuto un problema simile accedendo a un server LDAP da un contenitore docker. Ho impostato un IP fisso per il contenitore e ho aggiunto una regola firewall.

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

regola iptables:

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

All'interno dell'accesso al container dockerhost:portnumberOnHost


3

Se MongoDB e RabbitMQ sono in esecuzione sull'host, la porta dovrebbe già essere esposta in quanto non si trova all'interno di Docker.

Non è necessaria l' -popzione per esporre le porte dal contenitore all'host. Per impostazione predefinita, tutte le porte sono esposte. L' -popzione consente di esporre una porta dal contenitore all'esterno dell'host.

Quindi, suppongo che non sia necessario -pe dovrebbe funzionare bene :)


1
Lo sapevo, ma sembra che mi manchino un po 'di informazioni: vedi la modifica recente, poiché non riesco a raggiungere le porte sull'host.
JoelKuiper,

2
Devi installare rabbitmq e mongodb per ascoltare anche sul bridge e non solo sulla tua interfaccia di rete principale.
scricchiolio

13
@creack come si fa ad ascoltare rabbitmq e mongodb sul bridge?
Ryan Walls,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.