Meneruskan port host ke wadah buruh pelabuhan

167

Apakah mungkin untuk memiliki port akses wadah Docker dibuka oleh tuan rumah? Secara konkret saya memiliki MongoDB dan RabbitMQ berjalan di host dan saya ingin menjalankan proses dalam wadah Docker untuk mendengarkan antrian dan (opsional) menulis ke database.

Saya tahu saya dapat meneruskan port dari container ke host (melalui opsi -p) dan memiliki koneksi ke dunia luar (yaitu internet) dari dalam container Docker tetapi saya tidak ingin mengekspos port RabbitMQ dan MongoDB dari tuan rumah ke dunia luar.

EDIT: beberapa klarifikasi:

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

Saya harus melakukan trik ini untuk mendapatkan koneksi internet dengan wadah: Firewall saya memblokir koneksi jaringan dari wadah buruh pelabuhan ke luar

EDIT : Akhirnya saya pergi dengan membuat jembatan kustom menggunakan pipa dan meminta layanan mendengarkan pada jembatan IP. Saya menggunakan pendekatan ini daripada meminta MongoDB dan RabbitMQ mendengarkan pada docker bridge karena memberikan lebih banyak fleksibilitas.

JoelKuiper
sumber

Jawaban:

54

Host buruh pelabuhan Anda memaparkan adaptor ke semua wadah. Dengan asumsi Anda berada di ubuntu terbaru, Anda dapat menjalankan

ip addr

Ini akan memberi Anda daftar adapter jaringan, salah satunya akan terlihat seperti

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

Anda harus memberi tahu kelinci / mongo untuk mengikat IP itu (172.17.42.1). Setelah itu, Anda harus dapat membuka koneksi ke 172.17.42.1 dari dalam wadah Anda.

Seldo
sumber
35
Bagaimana wadah mengetahui IP untuk mengirim permintaan? Saya dapat membuat hardcode nilainya (172.17.42.1 di sini dan di rig pengujian saya, tetapi apakah itu selalu benar?), Tetapi itu tampaknya bertentangan dengan prinsip buruh pelabuhan yang bekerja dengan host mana pun!
JP.
2
@Eldo: Apakah antarmuka itu memerlukan konfigurasi untuk muncul? Saya menggunakan buruh pelabuhan 1.7.1, dan saya hanya punya lodan eth0.
mknecht
8
Apakah mungkin untuk melakukan ini entah bagaimana, jika tuan rumah hanya mendengarkan di 127.0.0.1?
HansHarhoff
5
"Anda harus memberi tahu kelinci / mongo untuk mengikat IP itu (172.17.42.1). Setelah itu, Anda harus dapat membuka koneksi ke 172.17.42.1 dari dalam wadah Anda." Akan lebih baik jika Anda menjelaskan bagaimana melakukan itu
Novaterata
1
Seperti yang disebutkan @Novaterata, dapatkah seseorang menjelaskan proses itu?
keskinsaf
122

Cara sederhana namun relatif tidak aman adalah dengan menggunakan --net=hostopsi untuk docker run.

Opsi ini membuatnya agar wadah menggunakan tumpukan jaringan host. Kemudian Anda dapat terhubung ke layanan yang berjalan di host hanya dengan menggunakan "localhost" sebagai nama host.

Ini lebih mudah untuk dikonfigurasikan karena Anda tidak perlu mengonfigurasi layanan untuk menerima koneksi dari alamat IP wadah buruh pelabuhan Anda, dan Anda tidak perlu memberi tahu pekerja pelabuhan tentang alamat IP tertentu atau nama host yang akan disambungkan, cukup sebuah port.

Misalnya, Anda dapat mengujinya dengan menjalankan perintah berikut, yang menganggap gambar Anda dipanggil my_image, gambar Anda menyertakan telnetutilitas, dan layanan yang ingin Anda sambungkan ada di port 25:

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

Jika Anda mempertimbangkan untuk melakukannya dengan cara ini, silakan lihat peringatan tentang keamanan di halaman ini:

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

Ia mengatakan:

--net = host - Memberitahu Docker untuk melewati menempatkan wadah di dalam tumpukan jaringan yang terpisah. Intinya, pilihan ini memberi tahu Docker untuk tidak mengirim kontainer ke jaringan kontainer! Sementara proses penampung masih akan terbatas pada sistem file mereka sendiri dan daftar proses dan batas sumber daya, perintah ip addr cepat akan menunjukkan kepada Anda bahwa, berdasarkan jaringan, mereka hidup "di luar" di host Docker utama dan memiliki akses penuh ke antarmuka jaringannya . Perhatikan bahwa ini tidak membiarkan kontainer mengkonfigurasi ulang tumpukan jaringan host - yang akan membutuhkan --privileged = true - tetapi kontainer memungkinkan proses membuka port bernomor rendah seperti proses root lainnya. Ini juga memungkinkan wadah untuk mengakses layanan jaringan lokal seperti D-bus. Ini dapat menyebabkan proses dalam wadah dapat melakukan hal-hal yang tidak terduga seperti memulai ulang komputer Anda.

David Grayson
sumber
12
Bagi siapa pun yang tidak menggunakan buruh pelabuhan di Linux (misalnya menggunakan beberapa virtualisasi) ini tidak akan berfungsi, karena host akan menjadi VM yang mengandung, bukan OS host yang sebenarnya.
Sebastian Graf
13
Secara khusus, pada MacOS, ini tidak mungkin (tanpa beberapa penyelesaian): docs.docker.com/docker-for-mac/networking/…
pje
15
Pada MacOS, --net=hosttidak berfungsi untuk memungkinkan proses wadah Anda terhubung ke mesin host Anda menggunakan localhost. Sebaliknya, memiliki wadah Anda terhubung ke MacOS khusus hanya hostname docker.for.mac.host.internalbukan localhost. Tidak ada parameter tambahan yang diperlukan agar docker runini berfungsi. Anda dapat meneruskan ini sebagai env var menggunakan -ejika Anda ingin menjaga platform wadah Anda agnostik. Dengan begitu Anda dapat terhubung ke host yang bernama env var dan meneruskan docker.for.mac.host.internaldi MacOS dan localhostdi Linux.
tul
18
nama host terbaru untuk mac adalah host.docker.internal, lihat doc
xysun
Sama untuk Windows docker run --rm -it --net=host postgres bashkemudianpsql -h host.docker.internal -U postgres
Leo Cavalcante
12

Anda juga bisa membuat terowongan 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

Dengan cara elasticsearchini terowongan ke server dengan layanan yang berjalan (Elasticsearch, MongoDB, PostgreSQL) dan memperlihatkan port 9200 dengan layanan itu.

Czerasz
sumber
8
Anda pada dasarnya meletakkan kunci pribadi di gambar Docker. Rahasia tidak boleh masuk ke gambar Docker.
Teoh Han Hui
2
Ini adalah satu-satunya solusi waras yang dapat digunakan sejauh ini.
Helvete
5

Saya memiliki masalah yang sama mengakses LDAP-Server dari wadah buruh pelabuhan. Saya menetapkan IP tetap untuk wadah dan menambahkan aturan 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

aturan iptables:

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

Di dalam akses kontainer dockerhost:portnumberOnHost

Arigion
sumber
3

Jika MongoDB dan RabbitMQ berjalan di Host, maka port seharusnya sudah terbuka karena tidak ada dalam Docker.

Anda tidak perlu -popsi untuk mengekspos port dari wadah ke host. Secara default, semua port terbuka. The -ppilihan memungkinkan Anda untuk mengekspos port dari wadah ke luar dari tuan rumah.

Jadi, tebakan saya adalah bahwa Anda tidak perlu -psama sekali dan itu harus bekerja dengan baik :)

creack
sumber
1
Saya tahu itu, tetapi sepertinya saya kehilangan sedikit informasi: lihat hasil edit baru-baru ini, karena saya tidak dapat mencapai port pada host.
JoelKuiper
2
Anda perlu mengatur rabbitmq dan mongodb untuk juga mendengarkan di jembatan dan tidak hanya pada antarmuka jaringan utama Anda.
Creack
13
@creack, bagaimana Anda mendapatkan rabbitmq dan mongodb untuk mendengarkan di jembatan?
Ryan Walls