Bagaimana cara menetapkan pemetaan port ke wadah Docker yang ada?

436

Saya tidak yakin apakah saya salah mengerti sesuatu di sini, tetapi sepertinya hanya mungkin untuk mengatur pemetaan port dengan membuat wadah baru dari sebuah gambar. Apakah ada cara untuk menetapkan pemetaan port ke wadah Docker yang ada?

terima kasih
sumber
3
Menggunakan iptables dapat berfungsi seperti jawaban ini. Mengekspos Port di Kontainer Docker Langsung
Choldrim
2
Saya menduga ini adalah desain. Docker mencoba untuk memaksa Anda untuk "berulang" dan wadah adalah jenis "sistem catatan." Apa pun yang Anda lakukan sebagai langkah yang tidak memengaruhi wadah akan menjadi langkah manual yang mudah hilang. Mengatakan dengan cara lain: Anda ingin wadah Anda mewakili semua konfigurasi yang diperlukan untuk beroperasi. Jadi jika Anda ingin membuka port baru, maka Anda perlu membuat wadah baru.
Lance Kind
2
Pertanyaan lama dan saya tidak menjawabnya, tetapi saya ingin mengatakan bahwa mungkin Anda dan orang-orang yang mengajukan pertanyaan dan jawaban ini mungkin benar-benar salah memahami konsep buruh pelabuhan. Docker adalah untuk aplikasi stateless, yang dapat meningkatkan atau menurunkan berkali-kali. Anda tidak boleh bertahan sesuatu di dalam wadah untuk lingkungan produksi yang tidak dapat diciptakan kembali, jika Anda perlu bertahan, petakan direktori. Docker bukan sesuatu seperti "light vm", mungkin yang Anda cari adalah linuxcontainers.org, lxd didasarkan pada konsep docker tetapi dengan "light vm" dalam pikiran.
Edgar Carvalho
kalau-kalau ini bisa membantu, dimungkinkan untuk menggunakan alat "Kitematic" untuk menambahkan pemetaan port ke wadah yang sudah berjalan. Ini harus menyiratkan bahwa harus ada perintah buruh pelabuhan untuk melakukan hal yang persis sama tetapi dengan sedikit googling :) Semoga Sukses
Yaffah

Jawaban:

298

Anda dapat mengubah pemetaan port dengan langsung mengedit hostconfig.jsonfile di /var/lib/docker/containers/[hash_of_the_container]/hostconfig.json

Anda dapat menentukan [hash_of_the_container] melalui docker inspect <container_name>perintah dan nilai bidang "Id" adalah hash.

1) stop the container 
2) stop docker service (per Tacsiazuma's comment)
3) change the file
4) restart your docker engine (to flush/clear config caches)
5) start the container

Jadi Anda tidak perlu membuat gambar dengan pendekatan ini. Anda juga dapat mengubah bendera mulai ulang di sini.

PS Anda dapat mengunjungi https://docs.docker.com/engine/admin/ untuk mempelajari cara memulai ulang mesin docker dengan benar sesuai mesin host Anda. Saya digunakan sudo systemctl restart dockeruntuk me-restart mesin buruh pelabuhan saya yang berjalan di Ubuntu 16.04

holdfenytolvaj
sumber
17
Ketika buruh pelabuhan berhenti, tampaknya menimpa perubahan Anda, jadi 2. berhenti buruh pelabuhan, 3. ganti file, 4. mulai mesin buruh pelabuhan
Tacsiazuma
5
Saya sudah mencoba yang di atas dan berhasil. Untuk lebih jelasnya lihat: mybrainimage.wordpress.com/2017/02/05/…
rohitmohta
11
Sangat penting untuk menghentikan kontainer, menghentikan mesin buruh pelabuhan dan mengubah keduanya hostconfig.jsondan config.v2.jsonuntuk membuat ini bekerja. Gunakan tautan yang disediakan oleh @rohitmohta untuk melihat detailnya.
Kalpak Gadre
5
bekerja untuk saya, hanya satu hal jika menggunakan aplikasi buruh pelabuhan di mac, ikuti instruksi di sini untuk mendapatkan ke / var / lib / buruh pelabuhan / folder kontainer: stackoverflow.com/a/41226917/2048266 , pada dasarnya jalankan screen ~/Library/Containers/com.docker.docker/Data/com.docker.driver.amd64-linux/ttySetelah Anda mendapatkan tty berjalan Anda bisa arahkan ke / var / lib / docker
nommer
14
untuk windows, dapatkah ada yang berbagi lokasi folder conatiners kepada saya?
Vijay
463

Saya juga tertarik dengan masalah ini.

Seperti yang disebutkan @Thasmo , penerusan port dapat ditentukan HANYA dengan perintah docker run(dan docker create).
Perintah lain, docker starttidak memiliki -popsi dan docker porthanya menampilkan penerusan saat ini.

Untuk menambahkan penerusan porta, saya selalu mengikuti langkah-langkah ini,

  1. berhenti menjalankan wadah

    docker stop test01
    
  2. komit wadah

    docker commit test01 test02
    

    CATATAN: Di atas, test02adalah gambar baru yang saya buat dari test01wadah.

  3. jalankan kembali dari gambar yang dikomit

    docker run -p 8080:8080 -td test02
    

Dimana 8080 pertama adalah port lokal dan 8080 kedua adalah port container.

Fujimoto Youichi
sumber
15
Bagaimana jika saya ingin menyimpan nama test01?
user69715
12
Adakah yang tahu jika ada masalah terbuka dengan Docker untuk mengizinkan spesifikasi port (--publish) dengan docker start?
Elijah Lynn
8
Dan apa yang terjadi dengan volume dalam skenario ini?
Andrew Savinykh
78
Ini adalah solusi yang mengerikan, saya tidak tahu bagaimana ia berhasil mendapatkan 250 upvotes. Mungkin mereka yang ter-upgrade tidak tahu kekacauan macam apa yang disebabkan oleh solusi ini. Ya, itu mengerikan, dan itu sama dengan memulai wadah baru yang berjalan di pelabuhan yang berbeda.
Arrrr
25
@ Arrrr Mungkin Anda ingin memberikan jawaban yang lebih baik? Saya yakin kita semua akan menghargai jika Anda memberi tahu kami cara yang lebih baik untuk melakukan ini.
crockeea
40

Jika dengan "yang ada" yang Anda maksudkan "berjalan", maka (saat ini) tidak mungkin untuk menambahkan pemetaan port.

Anda dapat, bagaimanapun, secara dinamis menambahkan antarmuka jaringan baru dengan misalnya Pipework , jika Anda perlu mengekspos layanan dalam wadah yang sedang berjalan tanpa menghentikan / memulai kembali.

jpetazzo
sumber
4
Ini harus menjadi jawaban teratas. Singkat dan ini menjawab pertanyaan OP yang tidak dilakukan oleh yang lain! Terkadang hasil negatif adalah hasil!
Sebagian Mendung
19

Tidak yakin apakah Anda bisa menerapkan pemetaan port wadah yang berjalan. Anda dapat menerapkan penerusan porta saat menjalankan wadah yang berbeda dari membuat wadah baru.

$ docker run -p <public_port>:<private_port> -d <image>  

akan mulai menjalankan wadah. Tutorial ini menjelaskan pengalihan pelabuhan.

rajalokan
sumber
2
Ya, jadi sepertinya hanya mungkin untuk mengatur opsi seperti pemetaan port pada pembuatan kontainer.
thasmo
20
FYI jawaban ini tidak sepenuhnya benar. docker runmembuat dan memulai wadah baru. Ini setara dengan melakukan docker creatediikuti oleh docker start.
Trevor Sullivan
19

Mengedit hostconfig.json tampaknya tidak berfungsi sekarang. Itu hanya berakhir dengan port yang terbuka tetapi tidak dipublikasikan untuk menjadi tuan rumah. Berkomitmen dan menciptakan kembali wadah bukanlah pendekatan terbaik bagi saya. Tidak ada yang disebutkan docker network?

Solusi terbaik akan menggunakan proxy terbalik dalam jaringan yang sama

  1. Buat jaringan baru jika wadah Anda sebelumnya tidak dalam yang bernama.

    docker network create my_network

  2. Bergabunglah dengan wadah Anda saat ini ke jaringan yang dibuat

    docker network connect my_network my_existing_container

  3. Mulai layanan proxy yang dibalik (mis. Nginx) menerbitkan port yang Anda butuhkan, bergabung dengan jaringan yang sama

    docker run -d --name nginx --network my_network -p 9000:9000 nginx

    Secara opsional hapus default.conf di nginx

    docker exec nginx rm /etc/nginx/conf.d/default.conf

  4. Buat konfigurasi nginx baru

    server
    {
        listen 9000;
    
        location / {
            proxy_pass http://my_existing_container:9000;
            proxy_http_version 1.1;
            proxy_set_header Upgrade $http_upgrade;
            proxy_set_header Connection 'upgrade';
            proxy_set_header Host $host;
            proxy_cache_bypass $http_upgrade;
        }
    }
    

    Salin konfigurasi ke wadah nginx.

    docker cp ./my_conf.conf nginx:/etc/nginx/conf.d/my_conf.conf

  5. Mulai ulang nginx

    docker restart nginx

Keuntungan : Untuk mempublikasikan port baru, Anda dapat menghentikan / memperbarui / membuat ulang wadah nginx dengan aman sesuai keinginan tanpa menyentuh wadah bisnis. Jika Anda membutuhkan nol waktu turun untuk nginx, dimungkinkan untuk menambahkan lebih banyak layanan proxy yang dibalik yang bergabung dalam jaringan yang sama. Selain itu, sebuah wadah dapat bergabung dengan lebih dari satu jaringan.

Edit:

Untuk membalikkan layanan proxy non-http, file konfigurasi sedikit berbeda. Ini adalah contoh sederhana:

upstream my_service {
    server my_existing_container:9000;
}

server {
    listen 9000;
    proxy_pass my_service;
}
Sean C.
sumber
1
Ini luar biasa dan praktis, tetapi untuk sistem perusahaan, pendekatan ini tampaknya membingungkan. Jauh lebih baik membiarkan satu sistem mengontrol alur kerja.
Afshin
1
@Afshin Nah untuk sistem atau proyek perusahaan, saya pikir solusi ini lebih baik daripada menciptakan kembali (menyebabkan down time) atau meretas file hostconfig.json (setidaknya tidak secara resmi diperkenalkan). Kontainer tambahan hanya mengekspos port internal wadah bisnis Anda, daripada membuat perubahan apa pun padanya.
Sean C.
1
Pendekatan yang luar biasa. Saya perlu mengkonfigurasi nginx secara berbeda agar wadah saya berfungsi di belakang proxy, tetapi sepertinya cara yang benar untuk melakukan sesuatu. Bekerja untuk penyebaran biru-hijau juga.
Brooks DuBois
18

Dalam contoh Fujimoto Youichi test01adalah wadah, sedangkan test02gambar.

Sebelum melakukan, docker runAnda dapat menghapus wadah asli dan kemudian menetapkan wadah nama yang sama lagi:

$ docker stop container01
$ docker commit container01 image01
$ docker rm container01
$ docker run -d -P --name container01 image01

(Menggunakan -Puntuk mengekspos port ke port acak daripada menetapkan secara manual).

Luca
sumber
12
Mohon berhati-hati. Anda akan KALAH semua data Anda, tergantung pada aplikasi di dalamnya.
Barry
14

Jika Anda menjalankannya docker run <NAME>akan muncul gambar baru, yang kemungkinan besar bukan yang Anda inginkan.

Jika Anda ingin mengubah gambar saat ini lakukan hal berikut:

docker ps -a

Ambil id wadah target Anda dan buka:

cd /var/lib/docker/containers/<conainerID><and then some:)>

Hentikan wadah:

docker stop <NAME>

Ubah file

vi config.v2.json

"Config": {
    ....
    "ExposedPorts": {
        "80/tcp": {},
        "8888/tcp": {}
    },
    ....
},
"NetworkSettings": {
....
"Ports": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],

Dan ganti file

vi hostconfig.json

"PortBindings": {
     "80/tcp": [
         {
             "HostIp": "",
             "HostPort": "80"
         }
     ],
     "8888/tcp": [
         {
             "HostIp": "",
             "HostPort": "8888"
         } 
     ]
 }

Mulai ulang buruh pelabuhan Anda dan itu akan berhasil.

buruh pelabuhan-noob
sumber
2
Ini tidak berfungsi untuk saya di Docker versi 17.09.0-ce. Setelah saya mulai file konfigurasi kontainer ditimpa kembali ke nilai lama.
thegeko
3
restart layanan buruh pelabuhan di sistem host @thegeko
yurenchen
1
ini bekerja! tks! 1. stop kontainer, 2.change file, 3. restart buruh pelabuhan, 4. mulai kembali kontainer
datdinhquoc
12

Cara lain di sekitar Anda jika Anda tidak nyaman dengan konfigurasi Docker depth IPtables akan menjadi teman Anda.

iptables -t nat -A DOCKER -p tcp --dport ${YOURPORT} -j DNAT --to-destination ${CONTAINERIP}:${YOURPORT}

iptables -t nat -A POSTROUTING -j MASQUERADE -p tcp --source ${CONTAINERIP} --destination ${CONTAINERIP} --dport ${YOURPORT}

iptables -A DOCKER -j ACCEPT -p tcp --destination ${CONTAINERIP} --dport ${YOURPORT}

Ini hanya tipuan bukan cara yang disarankan ini bekerja dengan skenario saya karena saya tidak bisa berhenti wadah saya harap akan membantu Anda juga.

Mansur Ali
sumber
ini jawaban yang bagus! Terima kasih! Jika saya ingin peta DOCKER_PORTuntuk MACHINE_PORT, bagian mana yang harus diubah?
Ciprian Tomoiagă
Catatan buruh pelabuhan tidak akan tahu tentang penambahan manual ini. Entri SO tidak dihapus ketika nanti Anda me-restart layanan dengan buruh pelabuhan mengekspos port dengan benar. Jadi ketika ada perubahan, pastikan untuk memeriksa iptables dengan sangat hati-hati. Terutama mencari entri duplikat!
anthony
8

kami menggunakan alat praktis seperti ssh untuk melakukannya dengan mudah.

Saya menggunakan host ubuntu dan gambar buruh pelabuhan berbasis ubuntu.

  1. Di dalam docker telah diinstal openssh-client.
  2. Docker luar (host) telah menginstal server openssh-server.

ketika port baru perlu dipetakan,

di dalam buruh pelabuhan jalankan perintah berikut

ssh -R8888:localhost:8888 <username>@172.17.0.1

172.17.0.1 adalah ip dari antarmuka docker (Anda bisa mendapatkannya dengan menjalankannya ifconfig docker0 | grep "inet addr" | cut -f2 -d":" | cut -f1 -d" "di host).

di sini saya memiliki port 8888 lokal yang dipetakan kembali ke host 8888. Anda dapat mengubah port sesuai kebutuhan.

jika Anda memerlukan satu port lagi, Anda dapat mematikan ssh dan menambahkan satu baris lagi -R ke port baru tersebut.

Saya telah menguji ini dengan netcat.

melchi
sumber
2
  1. Hentikan mesin buruh pelabuhan dan wadah itu.
  2. Buka /var/lib/docker/containers/${container_id}direktori dan edithostconfig.json
  3. Edit PortBindings.HostPortyang Anda inginkan perubahannya.
  4. Mulai mesin docker dan wadah.
ezileli
sumber
-1

Untuk Pengguna Windows & Mac, ada cara lain yang cukup mudah dan ramah untuk mengubah port pemetaan:

  1. unduh kitematic

  2. pergi ke halaman pengaturan wadah, pada tab port, Anda dapat langsung memodifikasi port yang diterbitkan di sana.

  3. mulai wadah lagi

john
sumber
2
Saya mencoba pendekatan ini. Kinematic menerapkan pemetaan port, memang. Namun untuk menerapkannya, itu menciptakan kembali wadah saya dari gambar asli. Jadi, jika Anda takut kehilangan perubahan yang dibuat dalam wadah itu sendiri, jangan gunakan metode ini.
VeganHunter
1
Saya lebih suka ini, saya mengerti bahwa itu tidak menjawab pertanyaan, dan itu menciptakan wadah baru. Tapi setidaknya itu berfungsi, dan hasil SO ini muncul selama pencarian saya. +1
2b77bee6-5445-4c77-b1eb-4df3e5
-7

Jawaban Singkat: Anda tidak dapat menetapkan pemetaan port ke wadah Docker yang ada

Anda membutuhkan wadah baru ... menanganinya.

stephen
sumber
4
Tidak perlu sikap. Juga jawaban ini benar-benar kurang detail.
lovefaithswing
1
Tidak perlu detail. Nada sangat penting untuk menyampaikan jawaban hemat waktu ini dan sifat wadah yang fana.
stephen
-11

Jika Anda hanya ingin mengubah port wadah yang sedang berjalan, Anda harus:

  1. hentikan wadah yang ada

    sudo docker menghentikan NAME

  2. sekarang restart dengan pemetaan port baru

    sudo docker run -d -p 81:80 NAME

dimana sebagai:

"-d" untuk latar belakang / deamon buruh pelabuhan

"-p" aktifkan pemetaan port

Port "81" eksternal (terbuka) yang Anda gunakan untuk mengakses dengan browser Anda

"80" port docker container internal dengarkan port

Vlad Gulin
sumber
4
Ini salah. Dalam docker runperintah, NAMEadalah nama dari gambar untuk menjalankan wadah dari, sedangkan di docker stopdalam NAMEmengacu pada nama wadah untuk berhenti.
jonatan
1
"buruh pelabuhan menjalankan" akan membuat wadah baru. Itu tidak dapat menggunakan nama wadah yang sama dengan yang dihentikan karena Anda hanya dapat memiliki satu wadah dengan nama itu. Jadi yang perlu Anda lakukan: "buruh pelabuhan berhenti NAMA", wadah buruh pelabuhan rm NAME, lalu "buruh pelabuhan jalankan -d -p 81:80 NAME" seperti yang Anda tulis.
Lance Kind