Saya mencoba membuat wadah Docker yang bertindak seperti mesin virtual lengkap. Saya tahu saya dapat menggunakan instruksi EXPOSE di dalam Dockerfile untuk mengekspos port, dan saya dapat menggunakan -p
flag dengan docker run
untuk menetapkan port, tetapi begitu sebuah kontainer benar-benar berjalan, apakah ada perintah untuk membuka / memetakan port tambahan secara langsung?
Sebagai contoh, katakanlah saya memiliki wadah Docker yang menjalankan sshd. Orang lain menggunakan wadah ssh dan menginstal httpd. Apakah ada cara untuk mengekspos port 80 pada kontainer dan memetakannya ke port 8080 pada host, sehingga orang dapat mengunjungi server web yang berjalan dalam wadah, tanpa memulai ulang?
Jawaban:
Anda tidak dapat melakukan ini melalui Docker, tetapi Anda dapat mengakses port yang tidak terpapar kontainer dari mesin host.
jika Anda memiliki wadah yang menjalankan sesuatu di port 8000, Anda dapat menjalankannya
Untuk mendapatkan alamat ip kontainer, jalankan 2 perintah:
Secara internal, Docker keluar untuk memanggil iptables ketika Anda menjalankan gambar, jadi mungkin beberapa variasi pada ini akan berfungsi.
untuk mengekspos port 8000 kontainer di port host lokal Anda 8001:
Salah satu cara Anda dapat mengatasi hal ini, adalah dengan menyiapkan wadah lain dengan pemetaan port yang Anda inginkan, dan membandingkan output dari perintah iptables-save (walaupun, saya harus menghapus beberapa opsi lain yang memaksa lalu lintas untuk pergi melalui buruh pelabuhan proksi).
CATATAN: ini adalah merubuhkan buruh pelabuhan, jadi harus dilakukan dengan kesadaran bahwa itu dapat menciptakan asap biru
ATAU
Alternatif lain, adalah dengan melihat opsi -P (baru? Posting 0.6.6?) - yang akan menggunakan port host acak, dan kemudian menghubungkannya.
ATAU
dengan 0.6.5, Anda dapat menggunakan fitur LINK untuk memunculkan wadah baru yang berbicara dengan yang sudah ada, dengan beberapa tambahan merelay ke bendera -p wadah itu? (Saya belum menggunakan LINK)
ATAU
dengan buruh pelabuhan 0,11? Anda dapat menggunakan
docker run --net host ..
untuk melampirkan wadah Anda langsung ke antarmuka jaringan host (yaitu, net tidak spasi-nama) dan dengan demikian semua port yang Anda buka di wadah terbuka.sumber
CONTAINER_IP=$(docker inspect container_name | jq .[0].NetworkSettings.IPAddress | sed -r 's/\"([^\"]+)\"/\1/''])'); iptables -t nat -A DOCKER -p tcp --dport 8001 -j DNAT --to-destination ${CONTAINER_IP}:8000
jq
dansed
Anda dapat menggunakan-f
opsidocker inspect
:CONTAINER_IP=$(docker inspect -f '{{ .NetworkSettings.IPAddress }}' container_name)
jshon -e 0 -e NetworkSettings -e Networks -e bridge -e IPAddress -u
Inilah yang akan saya lakukan:
sumber
sudo docker
dan tidak adildocker
?docker commit
saya siap untuk menguji aplikasi lagi daripada menghabiskan berjam-jam untuk menginstal ulang semuanya.Meskipun Anda tidak dapat mengekspos port baru wadah yang ada , Anda dapat memulai wadah baru di jaringan Docker yang sama dan membuatnya meneruskan lalu lintas ke wadah asli.
Contoh yang berhasil
Meluncurkan web-layanan yang mendengarkan pada port 80, tapi jangan tidak mengekspos pelabuhan internal 80 (oops!):
Temukan IP jaringan Docker-nya:
Luncurkan
verb/socat
dengan port 8080 terbuka, dan dapatkan untuk meneruskan lalu lintas TCP ke port 80 itu:Anda sekarang dapat mengakses pastebin di http: // localhost: 8080 / , dan permintaan Anda mengarah ke
socat:1234
mana itu diteruskanpastebin:80
, dan responsnya menempuh jalur yang sama secara terbalik.sumber
verb/socat:alpine
, karena gambarnya memiliki 5% dari jejak (kecuali jika Anda mengalami libc atau DNS tidak kompatibel ).alpine/socat
--net myfoldername_default
sayaverb/socat
sejak saya memulai wadah yang tidak terpapar dalam komposisi buruh pelabuhan yang menciptakan jaringan.Peretasan IPtables tidak berfungsi, setidaknya di Docker 1.4.1.
Cara terbaik adalah menjalankan wadah lain dengan port terbuka dan relay dengan socat. Inilah yang saya lakukan untuk (sementara) terhubung ke database dengan SQLPlus:
Dockerfile:
sumber
FROM
gambar dasar yang sama dengan wadah DB Anda, untuk penggunaan sumber daya yang efisien.Ini ide lain. Gunakan SSH untuk melakukan penerusan port; ini bermanfaat juga bekerja di OS X (dan mungkin Windows) ketika host Docker Anda adalah VM.
sumber
Saya harus berurusan dengan masalah yang sama dan dapat menyelesaikannya tanpa menghentikan salah satu kontainer saya yang sedang berjalan. Ini adalah solusi terkini pada Februari 2016, menggunakan Docker 1.9.1. Bagaimanapun, jawaban ini adalah versi rinci dari jawaban @ ricardo-branco, tetapi lebih mendalam untuk pengguna baru.
Dalam skenario saya, saya ingin untuk sementara waktu menyambung ke MySQL yang berjalan dalam sebuah wadah, dan karena wadah aplikasi lain terhubung dengannya, menghentikan, mengkonfigurasi ulang, dan menjalankan kembali wadah basis data adalah non-starter.
Karena saya ingin mengakses database MySQL secara eksternal (dari Sequel Pro melalui tunneling SSH), saya akan menggunakan port
33306
pada mesin host. (Tidak3306
, kalau-kalau ada contoh MySQL luar berjalan.)Sekitar satu jam tweaker iptables terbukti tidak membuahkan hasil, meskipun:
Langkah demi langkah, inilah yang saya lakukan:
Edit
dockerfile
, tempatkan ini di dalam:Kemudian buat gambar:
Kemudian jalankan, menghubungkan ke wadah Anda yang sedang berjalan. (Gunakan
-d
alih-alih-rm
menyimpannya di latar belakang sampai berhenti dan dihapus secara eksplisit. Saya hanya ingin itu berjalan sementara dalam kasus ini.)sumber
Untuk menambah solusi jawaban yang diterima
iptables
, saya harus menjalankan dua perintah lagi di host untuk membukanya ke dunia luar.Catatan: Saya membuka port https (443), IP internal buruh pelabuhan saya adalah
172.17.0.2
Catatan 2: Aturan-aturan ini sementara dan hanya akan bertahan sampai wadah dimulai kembali
sumber
Anda dapat menggunakan SSH untuk membuat terowongan dan mengekspos wadah Anda di host Anda.
Anda dapat melakukannya dengan dua cara, dari wadah ke host dan dari host ke wadah. Tetapi Anda membutuhkan alat SSH seperti OpenSSH di keduanya (klien dalam satu dan server di yang lain).
Misalnya, dalam wadah, Anda bisa melakukannya
Anda dapat menemukan alamat IP kontainer dari baris ini (dalam wadah):
Kemudian di host, Anda bisa melakukan:
sumber
Jika tidak ada jawaban yang berfungsi untuk seseorang - periksa apakah kontainer target Anda sudah berjalan di jaringan buruh pelabuhan:
Simpan untuk nanti di variabel
$NET_NAME
:Jika ya, Anda harus menjalankan wadah proxy di jaringan yang sama.
Selanjutnya cari alias untuk wadah:
Simpan untuk nanti di variabel
$ALIAS
:Sekarang jalankan
socat
dalam wadah di jaringan$NET_NAME
untuk menjembatani ke$ALIAS
port yang terbuka (tetapi tidak dipublikasikan) ed kontainer:sumber
Anda dapat menggunakan jaringan overlay seperti Weave Net , yang akan menetapkan alamat IP unik untuk setiap kontainer dan secara implisit memaparkan semua port ke setiap bagian kontainer dari jaringan.
Weave juga menyediakan integrasi jaringan host . Ini dinonaktifkan secara default tetapi, jika Anda juga ingin mengakses alamat IP kontainer (dan semua port-nya) dari host, Anda dapat menjalankan jalankan saja
weave expose
.Pengungkapan penuh: Saya bekerja di Weaveworks.
sumber
Ada bungkus HAProxy yang berguna.
Ini menciptakan HAProxy ke wadah target. Peasy mudah.
sumber
Berikut ini beberapa solusinya:
https://forums.docker.com/t/how-to-expose-port-on-running-container/3252/12
sumber
Baca tanggapan Ricardo terlebih dahulu. Ini berhasil untuk saya.
Namun, ada skenario di mana ini tidak akan berfungsi jika kontainer berjalan ditendang menggunakan menggunakan buruh pelabuhan. Ini karena docker-compose (Saya menjalankan buruh pelabuhan 1,17) membuat jaringan baru. Cara mengatasi skenario ini adalah
docker network ls
Kemudian tambahkan yang berikut ini
docker run -d --name sqlplus --link db:db -p 1521:1521 sqlplus --net network_name
sumber
Tidak mungkin untuk melakukan pemetaan port langsung, tetapi ada beberapa cara Anda bisa memberikan wadah Docker berapa jumlah antarmuka nyata seperti mesin virtual.
Antarmuka Macvlan
Docker sekarang termasuk driver jaringan Macvlan . Ini melampirkan jaringan Docker ke antarmuka "dunia nyata" dan memungkinkan Anda untuk menetapkan alamat jaringan itu langsung ke wadah (seperti mode virtual yang dijembatani mesin virtual).
pipework
juga dapat memetakan antarmuka nyata ke dalam wadah atau mengatur sub antarmuka dalam versi Docker yang lebih lama.Routing IP
Jika Anda memiliki kendali atas jaringan Anda dapat merutekan jaringan tambahan ke host Docker Anda untuk digunakan dalam wadah.
Kemudian Anda menetapkan jaringan itu ke wadah dan mengatur host Docker Anda untuk merutekan paket melalui jaringan docker.
Antarmuka host bersama
The
--net host
pilihan memungkinkan antarmuka host untuk dibagikan ke dalam wadah tapi ini mungkin tidak setup yang baik untuk menjalankan beberapa kontainer pada satu host karena sifat bersama.sumber