Moby: mode gerombolan buruh pelabuhan: port pada 127.0.0.1 terkena 0.0.0.0

Dibuat pada 2 Apr 2017  ·  53Komentar  ·  Sumber: moby/moby

Deskripsi

Dalam mode gerombolan buruh pelabuhan, mengikat port ke 127.0.0.1 hasil dengan port terbuka di 0.0.0.0 juga. Ini bisa menjadi masalah keamanan yang parah dan harus dijelaskan dalam dokumentasi.

Langkah-langkah untuk mereproduksi masalah:

  1. Buat layanan, misalnya MongoDB, di file docker-compose.swarm.yml Anda, dan publikasikan port 27017 ke localhost:
  mongodb:
    image: mongo:3.2
    volumes:
      - ./persistent-data/mongodb:/data
      - ./persistent-data/mongodb/db:/data/db
    networks:
      data:
        aliases:
          - mongo.docker
    logging:
      driver: syslog
      options:
        syslog-address: "udp://10.129.26.80:5514"
        tag: "docker[mongodb]"
    ports:
      - "127.0.0.1:27017:27017"
    deploy:
      placement:
        constraints: [node.labels.purpose == main-data]
  1. Sebarkan gerombolan Anda
  2. Periksa apakah port terbuka dari luar gerombolan Anda dengan netcat

Jelaskan hasil yang Anda terima:

nc -vz PUBLIC_NODE_IP 27017
found 0 associations
found 1 connections:
[...]
Connection to PUBLIC_NODE_IP port 27017 [tcp/*] succeeded!

Jelaskan hasil yang Anda harapkan:
Porta hanya tersedia di 127.0.0.1, setidaknya di node swarm yang menjalankan layanan ini.

Informasi tambahan yang Anda anggap penting (misalnya, masalah hanya terjadi sesekali):

Output dari docker version :

Docker version 17.03.1-ce, build c6d412e

Output dari docker info :

info buruh pelabuhan untuk swarm manager:

Containers: 0
 Running: 0
 Paused: 0
 Stopped: 0
Images: 1
Server Version: 17.03.1-ce
Storage Driver: aufs
 Root Dir: /var/lib/docker/aufs
 Backing Filesystem: extfs
 Dirs: 3
 Dirperm1 Supported: true
Logging Driver: json-file
Cgroup Driver: cgroupfs
Plugins: 
 Volume: local
 Network: bridge host macvlan null overlay
Swarm: active
 NodeID: pk7ulemi0z0chgtsg0azfrjz5
 Is Manager: true
 ClusterID: 27etomlyjvtmygrm6rcdgr2ni
 Managers: 1
 Nodes: 6
 Orchestration:
  Task History Retention Limit: 5
 Raft:
  Snapshot Interval: 10000
  Number of Old Snapshots to Retain: 0
  Heartbeat Tick: 1
  Election Tick: 3
 Dispatcher:
  Heartbeat Period: 5 seconds
 CA Configuration:
  Expiry Duration: 3 months
 Node Address: 10.129.26.165
 Manager Addresses:
  10.129.26.165:2377
Runtimes: runc
Default Runtime: runc
Init Binary: docker-init
containerd version: 4ab9917febca54791c5f071a9d1f404867857fcc
runc version: 54296cf40ad8143b62dbcaa1d90e520a2136ddfe
init version: 949e6fa
Security Options:
 apparmor
 seccomp
  Profile: default
Kernel Version: 4.4.0-64-generic
Operating System: Ubuntu 16.04.2 LTS
OSType: linux
Architecture: x86_64
CPUs: 1
Total Memory: 992.4 MiB
Name: <HIDDEN>
ID: IMOK:QIR7:WU5Y:WTPP:EPRQ:F77G:ULGE:WOG4:O7S7:6AFE:V7QG:2XEK
Docker Root Dir: /var/lib/docker
Debug Mode (client): false
Debug Mode (server): false
Username: <HIDDEN>
Registry: https://index.docker.io/v1/
WARNING: No swap limit support
Experimental: false
Insecure Registries:
 127.0.0.0/8
Live Restore Enabled: false

Detail lingkungan tambahan (AWS, VirtualBox, fisik, dll.):
Diuji pada tetesan Digital Ocean.

areswarm kinbug

Komentar yang paling membantu

Sangat kecewa karena hampir dua tahun beberapa pengembang Docker mengabaikan satu kasus penggunaan yang valid dan sangat berguna ketika fungsionalitas itu harus dimiliki: ketika Anda ingin mengikat basis data relasional terkungkung sebagai layanan swarm ke antarmuka lokal untuk mengaksesnya dengan aman melalui terowongan SSH . Saat ini skenario tersebut tidak mungkin dilakukan.

Semua 53 komentar

Ya, ini seharusnya menghasilkan kesalahan; layanan (secara default) "mempublikasikan" menggunakan jaringan "masuk", dan tidak mendukung penetapan alamat IP, karena tidak mungkin untuk memprediksi _node_ tempat mereka berakhir (sehingga tidak diketahui alamat IP apa yang tersedia - meskipun 127.0 .0.1 bisa dimungkinkan). Masalah ini melacak fitur itu https://github.com/docker/docker/issues/26696 (dan "epik" ini melacak opsi lain yang belum (belum) didukung oleh layanan https://github.com/docker/docker/issues / 25303)

Bug di sini adalah buruh pelabuhan harus menghasilkan kesalahan, bukannya diam-diam mengabaikan pilihan; dapat direproduksi menggunakan file docker-compose minimal ini;

version: "3.2"
services:
  mongodb:
    image: nginx:alpine
    ports:
      - "127.0.0.1:27017:80"

ping @dnephin @vdemeester

@ fer2d2 Pada mode swarm, jika Anda menerbitkan sesuatu ( ports untuk stack deploy ), itu diterbitkan pada jaringan ingress , dan dengan demikian publik. Ada beberapa cara untuk menyiasati, tetapi meletakkan kind/bug pada itu karena kita setidaknya harus memperingatkan orang-orang tentang hal itu ketika melakukan stack deploy dengan port yang memiliki notasi ini (yaitu host:port:port ).

Untuk menyiasatinya, ada beberapa cara:

  • pertama, Anda harus menerbitkan mongo port hanya jika Anda ingin menjadi publik , jika tidak, ini tersedia melalui bundel penemuan nama di buruh pelabuhan (wadah / layanan lain di jaringan yang sama akan dapat menjangkau melalui mongo dns nama).
  • Jika Anda ingin mempublikasikannya di host dan bukan di ingress (jadi tidak swarm publik, hanya di host itu berjalan, dengan cara yang sama seperti tanpa mode swarm), Anda perlu menggunakan sintaks port diperluas .
    ports:
      - mode: host
        target: 80
        published: 9005

Ini akan melakukan hal yang sama seperti docker run -p 80:9005 … sehingga akan mengikatnya ke 0.0.0.0 , tetapi terbatas pada host.

Tapi seperti yang dikatakan @thaJeztah , "Bug di sini adalah buruh pelabuhan seharusnya menghasilkan kesalahan, daripada mengabaikan opsi secara diam-diam" 👼

/ cc @mavenugo @aboch untuk melihat apakah ada cara untuk benar-benar dapat mengikatnya ke ip tertentu? (sangat sulit untuk dicapai karena ip node akan berbeda jadi ..)

@ Vdemeester Bisakah saya menentukan localhost sebagai target host menggunakan notasi ini?

    ports:
      - mode: host
        target: 127.0.0.1:80
        published: 9005

Karena ini adalah format diperpanjang untuk konfigurasi port , itu harus berfungsi dengan baik.

Terima kasih sebelumnya

Tampaknya target dan publish sama-sama diberlakukan sebagai tipe integer dalam sintaksis yang panjang

Saya rasa ini bukan perilaku yang diinginkan jika Anda terhubung ke beberapa layanan melalui terowongan SSH. Misalnya, jika Anda ingin server MySQL atau MongoDB di 127.0.0.1 dan terhubung melalui SSH Tunnel, dengan Docker Swarm Anda harus mengekspos port database di 0.0.0.0 atau membuat container database kustom dengan SSH yang berjalan di dalamnya (dan kedua opsi tersebut sangat tidak aman).

Ada banyak klien database yang menggunakan tunnel SSH, seperti SQL Workbench atau Robomongo yang tidak dapat digunakan karena batasan ini (pengikatan antarmuka khusus).

Kami memiliki masalah yang sama di perusahaan kami seperti @ fer2d2 , mencoba menghubungkan Mongobooster dengan kawanan buruh pelabuhan melalui terowongan ssh. Satu-satunya solusi yang kami temukan adalah membuka port 27017 dan melindungi database dengan pengguna dan kata sandi.

Ada berita?

+1

+1

Kasus penggunaan lain untuk mengizinkan alamat ip port untuk pemetaan port bentuk panjang adalah untuk alamat anycast atau alamat lain yang mungkin terkait dengan loopback. Ini akan mirip dengan alamat 127.0.0.1 karena hanya terlihat di jaringan loopback. Sebuah layanan yang dibatasi untuk node dengan properti ini mungkin ingin mengekspos port hanya pada alamat anycast untuk menghindari tabrakan port sambil menghindari aturan iptables untuk terjemahan port.

Mungkinkah itu menjadi opsi ketika Anda menentukan:

placement:
        constraints:
          - node.id ==

Bersulang

+1

+1

+1

untuk diri saya sendiri, saya memecahkan masalah ini jadi:

iptables -I DOCKER-USER -i eth0 -j DROP
iptables -I DOCKER-USER -m state --state RELATED,ESTABLISHED -j ACCEPT

Buruh pelabuhan tidak menyentuh aturan ini. tambahkan saja milik Anda
-A DOCKER-USER -j RETURN
Akibatnya, meskipun port mendengarkan 0.0.0.0 tetapi tidak dapat diakses dari antarmuka eksternal eth0

Perilaku ini melanggar "aman secara default", dan memasukkan catatan di dokumen tidak akan cukup baik. Untuk saat ini seharusnya menyebabkan kesalahan.

Ini juga terkait dengan mode: ingress / host (kedua masalah ini tampaknya membingungkan dalam diskusi). Tidak ada apa pun tentang mode masuk yang harus menghentikan layanan yang terikat ke alamat lokal di semua node, tetapi tidak ke alamat eksternal. Oleh karena itu 127.xxx harus diizinkan. (dalam mode non-swarm (menggunakan docker run) saya mengikat ke 127.0.0.2:80 dan 127.0.0.3:80 dll. Untuk menguji beberapa server secara lokal dalam pengembangan.).

Masalah lainnya adalah mode masuknya default. Ini tidak terduga, dan juga mengarah pada masalah keamanan. Saya baru saja mencoba memulai layanan pada node yang dibatasi menjadi bagian pribadi jaringan, dengan port terikat ke 127.0.0.3:80. Itu kemudian juga terikat ke antarmuka publik dari node publik. (Itu diam-diam mengabaikan alamat IP, dan diam-diam menggunakan mode masuk, dan boom data saya bersifat publik).

Kasus penggunaan

  • Gunakan kasus yang memengaruhi saya (pasti nyata)

    • 1 Bind ke port node tertentu, karena port sedang digunakan di node lain. Anda dapat menggunakan mode host untuk ini, tetapi defaultnya adalah kejutan.

    • 2 Bind ke port node tertentu, karena node lain memiliki antarmuka publik. Anda dapat menggunakan mode host untuk ini, tetapi default-nya melanggar "aman secara default" .

    • 3 Ikat secara lokal karena, Anda tidak ingin itu terlihat, oleh host lain, defaultnya melanggar "aman secara default"

    • 4 Ikat ke 127.0.0.3, karena mesin pengembangan Anda memiliki banyak hal di dalamnya, dan 127.0.0.1 sedang digunakan, oleh port ini. Dan gunakan /etc/hosts , sehingga setiap nama domain dikirim ke penampung yang berbeda. Ini berfungsi dengan docker run , tetapi tidak dengan penulisan.

  • Kasus penggunaan lainnya

    • Ikat ke antarmuka tertentu misalnya 192.168.0.x, karena ini adalah jaringan internal. default melanggar "aman secara default"

    • Ikat ke node spesifik tertentu, tetapi tidak membatasi layanan untuk berjalan di node ini. Ini adalah kasus penggunaan yang mirip dengan 1 atau 2, tetapi tanpa batasan penggunaan. Lalu lintas akan dialihkan melalui gerombolan itu.

Singkatnya

  • Mengabaikan alamat IP dan mengikat ke 0.0.0.0, dan mode masuk default, keduanya melanggar "aman secara default". Kesalahan harus dikeluarkan jika Alamat IP ditentukan, dan dokumen diperbarui. Kesalahan harus dikeluarkan jika mode tidak ditentukan (tidak ada default), dan dokumen diperbarui. (ini memperbaiki masalah mode, dan menghentikan masalah keamanan mendadak.)
  • Dukungan kemudian dapat ditambahkan untuk alamat IP dalam mode host.
  • Dukungan untuk alamat IP dalam mode masuk, yang dibatasi ke alamat lokal 127.xxx, dapat ditambahkan. (alamat lokal yang berbeda misalnya 127.0.0.2 dan 127.0.0.3 harus diperlakukan berbeda (baru saja diteruskan ke OS)).

Izinkan mengikat ke alamat lokal berguna untuk node yang dibatasi. Izinkan pengikatan ke alamat tertentu, akan berfungsi untuk node yang dibatasi, atau dialihkan melalui swarm ke salah satu alamat di salah satu node (mungkin hanya mode masuk). Perutean ini sudah selesai

@ richard-delorenzi Moby bahkan tidak menerima IP host saat ini. Jadi di luar permintaan fitur, ini terdengar seperti masalah sisi klien ... khususnya bagaimana yaml tulis diterjemahkan di The Docker CLI.

Cara kerja ingress didokumentasikan dengan cukup baik, tetapi setujui bahwa ini adalah perilaku yang buruk di CLI.

+1

+1

+1

Saya memiliki jenis solusi yang saya gunakan. Saya menjalankan wadah mandiri dan menghubungkannya ke jaringan bernama 'inti', yang digunakan oleh semua layanan back-end kami (mongo, elasticsearch, influxdb dll) yang berjalan di dalam sekumpulan.

Saya tidak dapat melihat cara melakukan ini dalam file compose, jadi kami hanya menjalankan container mandiri seperti:

docker run --name kibana --rm -d -v /var/lib/kibana:/usr/share/kibana/config -p 127.0.0.1:5601:5601 --network core docker.elastic.co/kibana/kibana:6.1.2

docker run --name chronograf --rm -d -v /var/lib/chronograf:/var/lib/chronograf -p 127.0.0.1:8888:8888 --network core chronograf:1.4 chronograf --influxdb-url=http://influxdb:8086

Setelah memulai ini, pekerja pelabuhan ps menunjukkan kontainer baru sebagai terikat ke 127.0.0.1. Amin. Saya kemudian dapat melakukan tunnel ke host buruh pelabuhan dari stasiun kerja lokal saya untuk akses aman, seperti:

ssh -i my_ssh_key.pem [email protected]  -L 8888:localhost:8888  -L 5601:localhost:5601 -N

Dari browser saya, saya kemudian dapat terhubung ke http: // localhost : 8888 atau http: // localhost : 5601

Bekerja untuk saya.

Jika soket UNIX dapat menggantikan soket TCP / IP 127.0.0.1, solusi yang mungkin telah saya terapkan untuk fluent-bit tersedia di sini

Mungkin menambahkan opsi lain ke mode bisa membantu. Sesuatu seperti local selain host dan ingress .

Hapus kata-kata "Keamanan yang dapat digunakan: Moby memberikan default yang aman tanpa mengorbankan kegunaan." pada file moby readme . Ini jelas iklan palsu, lihat komentar @ richard-delorenzi.

Layanan tidak menerbitkan port secara default, jadi tidak akan dapat diakses kecuali Anda menentukan bahwa mereka harus menerbitkan port. Mengikat ke alamat IP tertentu tidak didukung saat ini; jika layanan Anda tidak dapat diakses, jangan publikasikan port, dan sambungkan ke layanan menggunakan jaringan internal (overlay).

Menambahkan dukungan untuk mengikat ke alamat IP dibahas di https://github.com/moby/moby/issues/26696 , tetapi tidak sepele untuk diterapkan (dengan mempertimbangkan alamat IP non- "localhost")

Peringatan ditambahkan saat menerapkan tumpukan;

docker stack deploy -c- test <<'EOF'
version: '3'
services:
  web:
    image: nginx:alpine
    ports:
      - "127.0.0.1:8080:80"
EOF

WARN[0000] ignoring IP-address (127.0.0.1:8080:80/tcp) service will listen on '0.0.0.0' 
Creating network test_default
Creating service test_web

Dan saat mencoba menerapkan layanan dengan alamat IP yang ditentukan, itu akan gagal untuk diterapkan dengan kesalahan;

docker service create -p 127.0.0.1:9090:80 nginx:alpine
invalid argument "127.0.0.1:9090:80" for "-p, --publish" flag: hostip is not supported
See 'docker service create --help'.

@dalu jika sistem Anda terpapar ke internet dan Anda memberi tahu Docker untuk mengekspos layanan di cluster, saya tidak yakin mengapa ekspektasinya menjadi sesuatu yang lain.

Pastinya, format penulisan yang strattles dev dan penerapan aktual ini memiliki beberapa kompromi besar.

@ cpuguy83

jika sistem Anda terpapar ke internet dan Anda memberi tahu Docker untuk mengekspos layanan di cluster, saya tidak yakin mengapa ekspektasinya menjadi sesuatu yang lain.

Nggak. Mengapa harus dapat diakses publik jika seseorang mengikatnya ke ip non publik seperti 127.0.0.1 atau 10.0.0.0? Sebenarnya itu adalah jawaban yang benar:

Mengikat ke alamat IP tertentu tidak didukung saat ini

@dalu

Tapi itu harus bisa diakses, tidak untuk umum. Dan itulah keseluruhan kesepakatan di sini.
Anda tidak aman secara default dan menghindari perbaikan dengan semantik.
Masalah ini telah terbuka selama hampir 2 tahun sekarang tanpa resolusi yang tepat.

Saya beralih dari swarm ke kubernetes karena swarm tidak bisa digunakan. Saya sangat senang dengan keputusan ini bahkan transisi ini sangat mahal.

@Bessonv Ini secara

Masalahnya adalah format penulisan dirancang untuk dev envs dan telah didorong untuk mendukung penerapan cluster. "tumpukan buruh pelabuhan" seharusnya hanya error, tetapi kemudian orang ingin dapat menggunakan satu file penulisan untuk mengatur semuanya dan jadi ada kekacauan ini.

@ cpuguy83
Saya tidak yakin apakah saya nyaman dengan deskripsi ini. Pada akhirnya, format penulisan hanyalah deskripsi dari keadaan yang diinginkan. Untuk memiliki beberapa perbedaan antara one-machine (compose) dan cluster (swarm) tidak apa-apa. Dari sudut pandang saya, tidak ada gunanya mendukung menulis sama sekali. Terutama karena mengaktifkan mode swarm sangat mudah. Tapi ini membutuhkan perbaikan swarm.

Masalahnya bukan pada kerumunan sama sekali dan 100% dalam format penulisan + implementasinya di cli buruh pelabuhan.
Perhatikan bahwa tumpukan saat ini 100% merupakan implementasi sisi klien.

Kami telah menemukan bahwa di dalam tumpukan Anda tidak perlu secara eksplisit mengekspos port apa pun untuk layanan internal seperti database, redis, dll. Cukup menghilangkan konfigurasi ports dari layanan internal dan merujuk berdasarkan nama sudah cukup .

Contoh layanan db di dalam tumpukan

services:
  db:
    image: postgres:11-alpine
  networks:
    - backend

... dapat dikonsumsi oleh layanan Django app dengan port default seperti ini:

DATABASES = {
    'default': env.db(default='postgres://user:pass<strong i="13">@db</strong>:5432/catalog'),
}

Jadi dalam kasus ini ketika Anda secara eksplisit hanya mengekspos layanan publik, ini terlihat seperti aman-secara default

Masalahnya bukan pada kerumunan sama sekali dan 100% dalam format penulisan + implementasinya di cli buruh pelabuhan.
Perhatikan bahwa tumpukan saat ini 100% merupakan implementasi sisi klien.

Apapun: Saya berhenti menggunakan stack (karena masalah ini), dan tidak lagi peduli. Salahkan perpustakaan, salahkan buruh pelabuhan, salahkan kucingku.

Saya belum melihat masalah ini saat menggunakan buruh pelabuhan secara langsung, atau saat menggunakan penulisan.

Sepertinya pendekatan ini dapat membantu (harus dijalankan pada setiap node di swarm):

  1. meninggalkan gerombolan
  2. hapus jaringan docker_gwbridge
  3. membuat ulang jaringan docker_gwbridge dengan opsi tambahan com.docker.network.bridge.host_binding_ipv4 = IP
  4. bergabung kembali dengan swarm
    Bekerja untuk port yang diterbitkan dalam mode "host". Tanpa mode jaringan masuk "host" digunakan dengan driver lain dan cakupan "swarm".

Solusi yang mengerikan:

$ mv /usr/bin/docker-proxy /usr/bin/docker-proxy-original
$ cat << 'EOF' > /usr/bin/docker-proxy
#!/bin/sh
exec /usr/bin/docker-proxy-original `echo $* | sed s/0.0.0.0/127.0.0.1/g`
EOF
$ chmod 755 /usr/bin/docker-proxy
$ service docker restart

@jsmouret Saya bahkan tidak dapat menemukan docker-proxy pada rilis buruh pelabuhan terbaru. Apakah itu warisan? Atau namanya berbeda?

Sepertinya itu tergantung ...

$ apt-file search docker-proxy
docker-ce: /usr/bin/docker-proxy
docker.io: /usr/sbin/docker-proxy

Perilaku ini harus didokumentasikan dalam dokumentasi .
Saat ini, ia hanya mengabaikan host dari pemetaan port pendek. Dan diam-diam tidak berhasil.

Hal aneh lainnya adalah Anda tidak dapat mengatur host dalam skema sintaks panjang.

Perilaku ini harus didokumentasikan dalam dokumentasi.

Saya setuju; Saya pikir itu disebutkan di suatu tempat di halaman itu, tetapi tidak dapat menemukannya; jangan ragu untuk membuka masalah di repositori dokumen; https://github.com/docker/docker.github.io/issues

Saat ini, ia hanya mengabaikan host dari pemetaan port pendek. Dan diam-diam tidak berhasil.

versi buruh pelabuhan apa yang kamu gunakan? itu harus mencetak peringatan (saat menggunakan docker stack deploy ), atau _error_ (saat menggunakan docker service create ); lihat https://github.com/moby/moby/issues/32299#issuecomment -472793444

versi buruh pelabuhan apa yang kamu gunakan? harus mencetak peringatan (saat menggunakan penerapan tumpukan pekerja pelabuhan), atau kesalahan (saat menggunakan pembuatan layanan buruh pelabuhan);

Ugh, sepertinya itu salahku. Itu benar-benar melakukannya ketika saya mencoba menerapkan tumpukan dari konsol.
Sebelumnya saya melakukannya melalui UI portainer dan tidak menunjukkan kesalahan atau peringatan apa pun.

Sangat kecewa karena hampir dua tahun beberapa pengembang Docker mengabaikan satu kasus penggunaan yang valid dan sangat berguna ketika fungsionalitas itu harus dimiliki: ketika Anda ingin mengikat basis data relasional terkungkung sebagai layanan swarm ke antarmuka lokal untuk mengaksesnya dengan aman melalui terowongan SSH . Saat ini skenario tersebut tidak mungkin dilakukan.

Solusi yang bisa diterapkan dan bersih adalah menjalankan server SSH di penampung kedua yang tersambung ke jaringan buruh pelabuhan yang sama dengan database Anda. Port SSH kemudian dapat dipublikasikan di host (ke port yang berbeda dari 22 tentunya), sehingga Anda dapat meneruskan melalui penampung SSH ke database Anda.

@nartamonov Saya tidak melihat bagaimana ini dapat dilakukan dengan aman dari masuknya kecuali protokol itu sendiri aman.
Cara untuk mengaksesnya dengan aman adalah melalui bidang data terenkripsi ( --opt encrypted untuk jaringan yang berlebihan) dan memutar wadah dengan alat apa pun yang Anda perlukan untuk terhubung ke jaringan itu.

Ini mungkin memiliki efek samping lain yang tidak terkait tetapi pengaturan "iptables": false di /etc/docker/daemon.json melakukan trik sebagai solusi juga. Solusi yang tidak terlalu drastis adalah menambahkan hanya aturan kustom seperti yang disarankan @helldweller .

Bagaimanapun, saya ingin melihat lebih banyak dukungan untuk ini setelah 3 tahun.

Sepertinya pendekatan ini dapat membantu (harus dijalankan pada setiap node di swarm):

1. leave swarm

2. remove network docker_gwbridge

3. recreate network docker_gwbridge with additional option com.docker.network.bridge.host_binding_ipv4=IP

4. join swarm back
   Works for ports published in mode "host". Without mode "host" ingress network is used with other driver and scope "swarm".

@ienyuk
Jika saya tidak salah, ini membuat semua port yang diterbitkan mengikat ke alamat default IP ? Jadi untuk memperjelas, ini bukan solusi yang dapat digunakan jika Anda hanya ingin membatasi antarmuka terikat untuk beberapa port dari beberapa layanan.

Saya ingin melaporkan solusi saya.

Kasus penggunaan:
Beberapa layanan dalam kerumunan perlu mendengarkan di semua antarmuka, atau setidaknya di antarmuka publik - penampung ini dalam contoh saya adalah Proxy Terbalik
Di node swarm itu juga ada instance database di setiap node, yang menggunakan jaringan swarm yang didefinisikan sebagai:

docker network create --scope swarm NETWORK_NAME --attachable -d overlay

Layanan web yang membutuhkan koneksi database harus digabungkan dengan NETWORK_NAME tentunya

Untuk tujuan admin, terkadang perlu terhubung langsung ke database

Larutan:
Hanya layanan yang perlu diekspos di semua jaringan (proxy terbalik dalam contoh saya) yang dapat memiliki ports: ['SOMEPORT:ANOTHERPORT'] dalam definisi layanan mereka

Semua layanan lainnya, harus memiliki kontainer non-swarm buruh pelabuhan yang dipasangkan pada host.
Kontainer non-swarm itu akan menjembatani port yang ada di NETWORK_NAME/nodeXYZ:port menjadi localhost

Contoh dengan mongodb:

docker run --rm -it --net=NETWORK_NAME -d --name expose-mongo -p 127.0.0.1:27017:47017 alpine/socat tcp-listen:47017,fork,reuseaddr tcp-connect:mongo01:27017

Kelemahan: harus ada wadah non-swarm untuk setiap simpul gerombolan, jadi dengan banyak simpul benar-benar membosankan kecuali mengadopsi skrip yang mungkin / berat

Solusi saya untuk masalah "jika Anda terhubung ke beberapa layanan melalui terowongan SSH" yang disebutkan @ fer2d2 adalah menambahkan layanan ssh dengan Dockerfile seperti:

FROM alpine

RUN apk add --no-cache openssh
RUN mkdir ~/.ssh
RUN ssh-keygen -A
RUN echo "root:root" | chpasswd
RUN echo 'PasswordAuthentication no' >> /etc/ssh/sshd_config
RUN echo 'Port 22' >> /etc/ssh/sshd_config
RUN echo -e " \
Match User root \n\
  AllowTcpForwarding yes\n\
  X11Forwarding no\n\
  AllowAgentForwarding no\n\
  ForceCommand /bin/false\n\
" >> /etc/ssh/sshd_config

EXPOSE 22
CMD /usr/sbin/sshd -D -e "$@"

Kemudian di docker-compose.yml:

...
  db:
    image: mysql:5.6
    environment:
      MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?err}
      MYSQL_ROOT_HOST: '%'
    volumes:
      - "./mysql:/var/lib/mysql"
    deploy:
      placement:
        constraints: [node.role == manager]

  sshd:
    image: maxisme/sshd:latest
    volumes:
      - "~/.ssh:/root/.ssh"
    ports:
      - "2223:22"
    deploy:
      placement:
        constraints: [node.role == manager]

yang memungkinkan saya untuk menambahkan kunci_otorisasi saya ke folder ~/.ssh dan kemudian proxy ssh melompati port 2223 ke database saya menggunakan nama host db .

Solusi yang bisa diterapkan dan bersih adalah menjalankan server SSH di penampung kedua yang tersambung ke jaringan buruh pelabuhan yang sama dengan database Anda. Port SSH kemudian dapat dipublikasikan di host (ke port yang berbeda dari 22 tentunya), sehingga Anda dapat meneruskan melalui penampung SSH ke database Anda.

sah

contoh lain mengapa fitur ini penting.
Saya memiliki server dengan plesk terinstal, plesk sudah memiliki konfigurasinya tetapi saya dapat menambahkan konfigurasi lain hanya untuk menunjuk ke layanan buruh pelabuhan. Server plesk ini adalah node swarm.
Saya ingin menggunakan plesk ke proxy_pass ke port. Porta ini harus dipublikasikan karena penampung berada di jaringan hamparan tetapi memerlukan port eksternal untuk berkomunikasi dengan dunia.

Jadi proxypass harus mengarah ke antarmuka lokal seperti 127.0.0.1: someport
dan container di swarm harus mempublikasikan port tersebut hanya ke localhost.

Dengan cara ini, port kontainer hanya dapat diakses oleh proxypass dan bukan dari dunia secara langsung

Saya suka solusi Anda @maxisme , tetapi bagaimana Anda mengelola kepemilikan authorized_keys ? Di OS X ini berfungsi untuk saya (tunggangannya milik root ) tetapi pada mesin Linux produksi saya mendapatkan:

Authentication refused: bad ownership or modes for file /root/.ssh/authorized_keys
Connection closed by authenticating user root 85.145.195.174 port 60535 [preauth]

Volume milik UID pengguna host, yang bukan root dan SSHD menolak untuk bekerja dengannya. Solusi selain solusi Anda 😬 adalah menggunakan configs , seperti ini:

services:
  sshd:
    image: [...]/sshd:${version}
    configs:
      # FIXME: It would be much better to use a bind volume for this, as it
      # would always be in sync with the host configuration. So revoking a key
      # in the host machine would automatically revoke it in the container. But
      # I can't figure out how to give the volume right ownership. It keeps UID
      # from the host which doesn't align with the container user.
      - source: authorized_keys
        target: /root/.ssh/authorized_keys
        mode: 0600

configs:
  authorized_keys:
    file: ~/.ssh/authorized_keys

Saya memahami bahwa karena fakta bahwa Anda tidak tahu host apa yang akan digunakan kontainer, Anda tidak dapat memberi tahu layanan untuk mengikat ke alamat ip host tertentu.

Namun seringkali host memiliki misalnya antarmuka terikat utara dan selatan. Anda mungkin ingin port swarm mengikat hanya ke antarmuka utara pada semua host swarm.

Jika nama antarmuka dari semua antarmuka yang Anda inginkan untuk mengikat layanan adalah sama (misalnya eth0), mungkin ide untuk menawarkan opsi untuk menentukan nama antarmuka untuk mengikat port swarm ke (di bagian port layanan).

    nginx:
      image: nvbeta/swarm_nginx
      networks:
        - demonet1
      ports:
        - "eth0:8088:80"

Ketika eth0 tidak tersedia di swarm node, port yang ditentukan tidak akan terikat ke antarmuka apa pun.

@ tad-lispy Anda harus dapat mengubah uid dan gid pengguna kontainer menjadi sama dengan pemilik volume pada host.
Gambar linuxserver mendukung ini dengan mengatur variabel lingkungan (lihat https://hub.docker.com/r/linuxserver/openssh-server, User / Group Identifiers ),

Apakah halaman ini membantu?
0 / 5 - 0 peringkat