Server Node dalam container tidak dapat diakses dengan server.listen(port, '127.0.0.1')

Saya menyiapkan server Node sederhana di Docker.

Dockerfile

FROM node:latest
RUN apt-get -y update
ADD example.js .
EXPOSE 1337   
CMD node example.js

contoh.js

var http = require('http');
http.createServer(function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n'+new Date);
}).listen(1337, '127.0.0.1');
console.log('Server running at http://127.0.0.1:1337/');

Sekarang bangunlah gambarnya

$ docker build -t node_server .

Sekarang jalankan dalam wadah

$ docker run -p 1337:1337 -d node_server  
$ 5909e87302ab7520884060437e19ef543ffafc568419c04630abffe6ff731f70

Verifikasi bahwa kontainer sedang berjalan dan port dipetakan:

$ docker ps  

CONTAINER ID        IMAGE               COMMAND                  CREATED             STATUS              PORTS                    NAMES
5909e87302ab        node_server         "/bin/sh -c 'node exa"   7 seconds ago       Up 6 seconds        0.0.0.0:1337->1337/tcp   grave_goldberg

Sekarang mari lampirkan ke container dan verifikasi server berjalan di dalamnya:

$ docker exec -it 5909e87302ab7520884060437e19ef543ffafc568419c04630abffe6ff731f70 /bin/bash 

Dan di baris perintah container ketik:

root@5909e87302ab:/# curl http://localhost:1337
Hello World
Mon Feb 15 2016 16:28:38 GMT+0000 (UTC)

Terlihat bagus bukan?

Masalahnya

Ketika saya menjalankan perintah curl yang sama pada host (atau menavigasi dengan browser saya ke http://localhost:1337) saya tidak melihat apa pun.

Adakah yang tahu mengapa pemetaan port antara container dan host tidak berfungsi?

Hal-hal yang sudah saya coba:

  • Berjalan dengan bendera --expose 1337

person Assaf Shomer    schedule 15.02.2016    source sumber
comment
Anda tidak menjalankan dengan --expose. Anda membuat image dengan direktif EXPOSE, lalu menjalankannya dengan --publish (atau -p). Lihat jawaban saya di bawah ini.   -  person VonC    schedule 15.02.2016


Jawaban (2)


Port Anda terekspos dengan benar tetapi server Anda mendengarkan koneksi di 127.0.0.1 di dalam penampung Anda:

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n'+new Date);
}).listen(1337, '127.0.0.1');

Anda perlu menjalankan server Anda seperti ini:

http.createServer(function (req, res) {
    res.writeHead(200, {'Content-Type': 'text/plain'});
    res.end('Hello World\n'+new Date);
}).listen(1337, '0.0.0.0');

Catat 0.0.0.0 bukannya 127.0.0.1.

person Chris McKinnel    schedule 15.02.2016
comment
Mendengarkan di 0.0.0.0 terlihat sangat aneh, tidak langsung jelas maksudnya. Tampaknya ini adalah defaultnya, jadi Anda bisa menghilangkan argumen itu dari fungsi listen(), yang menurut saya lebih mudah dipahami nodejs.org/api/ - person Davos; 11.11.2017
comment
Mendengarkan di 0.0.0.0 berarti mendengarkan di semua antarmuka. Hal ini sering kali berlebihan, terkadang menimbulkan masalah keamanan, namun umumnya tidak berbahaya. Masuk akal di dalam wadah Docker. - person Jim Stewart; 22.03.2018
comment
Terima kasih banyak, solusi ini mengatasi masalah dengan semua jenis server yang berjalan di dalam buruh pelabuhan seperti server ekspres Java atau node.js. Antarmuka HARUS dalam hal apa pun: 0.0.0.0, dengan port yang diekspor dengan opsi -P $PORT:$PORT/tcp, jadi biasanya server akan memeriksa export HOST=0.0.0.0 saat runtime. - person loretoparisi; 04.04.2018
comment
Terima kasih banyak untuk ini - saya membutuhkan waktu berjam-jam untuk menyelesaikannya! - person readikus; 13.04.2020
comment
Terima kasih banyak. Saya memiliki masalah yang sama tetapi dengan netty, saya tidak dapat mengaksesnya dari luar wadah. Apakah ada cara yang lebih baik untuk memahami batas wadah antarmuka jaringan mana, sehingga tidak menggunakan 0.0.0.0? - person matio; 22.11.2020
comment
Ini menyelamatkan hariku! Saya baru menyadari jelas tidak ada cara untuk mempublikasikan port antarmuka localhost kontainer. Aturannya adalah --publish [ip:hostPort:containerPort | ip::containerPort | hostPort:containerPort | Pelabuhan kontainer] - person dom free; 22.07.2021

Menambahkan EXPOSE 1337 ke file buruh pelabuhan

EXPOSE wajib jika Anda ingin "mengekspos " port itu ke kontainer lain.

Seperti yang dikomentari BMitch:

Expose tidak diperlukan untuk memublikasikan port atau menghubungkan container ke container melalui jaringan buruh pelabuhan bersama.
Ini adalah metadata untuk memublikasikan semua port dengan -P dan memeriksa image/container.

So:

Berjalan dengan bendera --expose 1337

Tidak juga: Anda perlu docker menjalankan dengan -p 1337:1337

Anda memerlukan:

  • buat gambar dengan arahan EXPOSE di dalamnya (digunakan oleh -P)
  • atau jalankan dengan port yang dipublikasikan di host -p 1337:1337

Pengujian curl http://localhost:1337 dilakukan dari dalam container (tidak perlu EXPOSE atau publikasi).
Jika ingin berfungsi dari host Linux, Anda memerlukan EXPOSE+-P atau Anda memerlukan -p 1337:1337.
Salah satu .

Mendeklarasikan pengungkapannya sendiri adalah hal yang baik untuk mendokumentasikan maksudnya, namun tidak melakukan apa pun sendirian.

Contohnya:

https://i.stack.imgur.com/wmKgd.png

Dalam gambar tersebut, 8080 adalah EXPOSE, dipublikasikan ke host Linux 8888.
Dan jika host Linux tersebut bukan host sebenarnya, port yang sama perlu diteruskan dengan cepat ke host sebenarnya. Lihat "Bagaimana cara mengakses kucing jantan yang berjalan di wadah buruh pelabuhan dari browser?".

Jika localhost tidak berfungsi dari host Linux, coba alamat IP-nya:

CID=$(docker run -p 1337:1337 -d node_server)
CIP=$(docker inspect --format '{{ .NetworkSettings.IPAddress }}' ${CID})
curl http://${CIP}:1337

Atau, seperti disebutkan di atas, buat server Anda mendengarkan koneksi yang berasal dari IP apa pun: 0.0.0.0 yaitu alamat siaran atau nol jaringan.

person VonC    schedule 15.02.2016
comment
Terima kasih atas komentarnya, tetapi seperti yang saya sebutkan di atas saya sudah mencoba menambahkan EXPOSE 1337 dan tidak berhasil juga - person Assaf Shomer; 15.02.2016
comment
@AssafShomer Anda membutuhkan keduanya, itulah inti jawaban saya - person VonC; 15.02.2016
comment
@AssafShomer Saya telah mengedit jawabannya untuk memperjelas hal itu. - person VonC; 15.02.2016
comment
Terima kasih, tentu saja, saya mencobanya dengan keduanya. Yaitu: Build dengan EXPOSE 1337 dan dijalankan dengan -p 1337:1337, masih belum ada. Saya mengubah pertanyaan untuk mencerminkan hal itu. - person Assaf Shomer; 15.02.2016
comment
@AssafShomer Apakah Anda langsung menggunakan Linux, atau menggunakan buruh pelabuhan melalui VM boot2docker di Windows atau Mac? - person VonC; 15.02.2016
comment
Langsung di Linux, tanpa boot2docker, tanpa Windows, dan tanpa VM. Logam telanjang :) (hampir) - person Assaf Shomer; 15.02.2016
comment
@AssafShomer Apakah Anda mencoba dengan IP wadah untuk pengujian? (Saya telah mengedit jawabannya) - person VonC; 15.02.2016
comment
Lalu apa yang dilakukan saklar docker run --expose? Dokumen mengatakan This exposes port ... of the container without publishing the port to the host system’s interfaces yang menyiratkan itu tersedia di antarmuka penampung, jika Anda mengetahui alamat itu docs.docker.com/engine/reference/commandline/run/ Sepertinya hal yang berguna untuk dilakukan jika Anda tidak ingin host Anda membukanya port ke dalam kontainer Anda. - person Davos; 10.11.2017
comment
@Davos Apa yang dilakukan docker run --expose switch? : ini mengekspos pada saat runtime (untuk dilihat oleh container lain) port yang awalnya tidak diekspos di image Dockerfile. - person VonC; 10.11.2017
comment
Eksposur tidak diperlukan untuk menerbitkan port atau menghubungkan kontainer ke kontainer melalui jaringan buruh pelabuhan bersama. Ini metadata untuk menerbitkan semua port dengan -P dan memeriksa gambar/wadah. Tidak ada dampak runtime yang pernah saya lihat. - person BMitch; 11.11.2017
comment
EXPOSE di Dockerfile sama sekali tidak diperlukan. Ini murni sebagai dokumentasi. Merupakan ide bagus untuk menunjukkan niat, namun juga menyesatkan, karena tidak menghasilkan apa-apa. Ini mungkin juga sebuah komentar. - person Jim Stewart; 22.03.2018
comment
@jim saya setuju. Jangan ragu untuk mengedit jawaban ini, dan memperjelas hal itu. - person VonC; 22.03.2018