SSD Nodes Learn RAM 8GB — $66/tahun
Panduan Matt ConnorOleh Matt Connor · Dikemas kini 2026-08-01

Rangkaian Docker Compose: DNS, Port dan Host Mode

Fahami rangkaian bridge lalai, DNS melalui nama perkhidmatan, masa sesuai menggunakan host mode, perkongsian rangkaian antara projek dan port diterbitkan yang memintas UFW.

Perkara yang dibina oleh Compose sebelum aplikasi anda bermula

Rangkaian Docker Compose bermula dengan satu peraturan: docker compose up mencipta rangkaian persendirian untuk projek, menyambungkan setiap perkhidmatan kepadanya, dan membolehkan perkhidmatan tersebut berhubung antara satu sama lain melalui nama perkhidmatan. Anda tidak perlu menulis satu baris networks: pun untuk mendapatkannya. Kebanyakan kekeliruan tentang rangkaian Compose berlaku kerana pengguna tidak mengetahui bahawa rangkaian lalai memang tersedia.

Berikut ialah fail kecil. Simpan fail ini sebagai compose.yaml dalam direktori bernama shop.

services:
  web:
    image: nginx:1.27
    ports:
      - "8080:80"
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: example

Jalankan projek tersebut dan lihat perkara yang dicipta oleh Docker:

docker compose up -d
docker network ls

Senarai itu kini mengandungi rangkaian bernama shop_default. Compose menamakannya <project>_default, dan nama projek secara lalai ialah nama direktori dalam huruf kecil. Gantikan nama itu dengan docker compose -p myproject up -d atau dengan name: myproject peringkat teratas dalam fail tersebut. Pemacunya ialah bridge, iaitu suis maya di dalam hos. Setiap kontena mendapat alamat pada subnet persendirian, dan trafik keluar diterjemahkan kepada alamat hos semasa keluar.

docker compose down memadamkan rangkaian tersebut. Oleh itu, kontena lama daripada projek terdahulu boleh mengekalkan rangkaian itu: Docker menolak operasi tersebut dengan error while removing network: network shop_default has active endpoints, dan penyelesaiannya ialah menghentikan atau mengalih keluar kontena yang masih disambungkan kepadanya.

Jika Compose masih baharu bagi anda, susun atur fail Compose dan perintah kitar hayat wajar dibaca terlebih dahulu kerana semua perkara di bawah menganggap anda boleh memulakan dan menghentikan projek.

DNS mengikut nama perkhidmatan ialah bahagian yang sering terlepas pandang oleh pemula

Pada mana-mana rangkaian yang ditakrifkan pengguna, Docker menjalankan pelayan DNS terbina dalam yang dilihat oleh setiap kontena di 127.0.0.11. Pelayan ini menyelesaikan nama perkhidmatan kepada alamat kontena semasa. Oleh itu, web mencapai pangkalan data pada nama hos db, melalui port 5432, tanpa sebarang konfigurasi.

docker compose exec web getent hosts db

Perintah itu mencetak baris seperti 172.18.0.2 db. Jika tiada output, kedua-dua perkhidmatan tidak berada pada rangkaian yang sama.

Kesilapan yang hampir semua orang lakukan sekurang-kurangnya sekali ialah menggunakan localhost dalam konfigurasi aplikasi. Di dalam kontena, localhost merujuk kepada kontena itu sendiri, bukan hos dan bukan perkhidmatan lain. Klien Postgres melaporkannya dengan jelas:

could not connect to server: Connection refused
	Is the server running on host "localhost" (127.0.0.1) and accepting
	TCP connections on port 5432?

Rentetan sambungan hendaklah postgresql://postgres:example@db:5432/postgres. Bahagian hos ialah nama perkhidmatan.

Dua perkara ini dapat menjimatkan masa kemudian. Nama diselesaikan kepada apa-apa yang sedang berjalan sekarang. Oleh itu, docker compose up -d --scale web=3 memberikan satu nama dengan tiga alamat. Klien yang menyimpan cache DNS selama-lamanya akan terikat pada kontena yang sudah tidak berfungsi. Selain itu, rangkaian legasi bridge yang digunakan oleh docker run biasa tanpa --network tidak mempunyai resolusi nama langsung. Sebab itu panduan tentang pautan kontena dari 2016 tidak sepadan dengan perkara yang anda lihat.

Anda tidak memerlukan ports: untuk menyambungkan dua perkhidmatan

ports: menerbitkan port kontena pada hos. Ia digunakan untuk trafik yang datang dari luar Docker. Ia tidak berkaitan dengan trafik antara perkhidmatan, yang sememangnya berfungsi merentasi keseluruhan julat port pada rangkaian projek.

Oleh itu, ports: - "5432:5432" yang ditambahkan oleh ramai orang pada perkhidmatan pangkalan data tidak memberikan manfaat dan sebenarnya menimbulkan risiko: arahan itu mendedahkan Postgres pada antara muka awam pelayan. Padamkannya. Jika anda mahu perkhidmatan itu boleh dicapai dari komputer riba untuk melakukan migrasi, ikatkannya pada gelung balik dengan "127.0.0.1:5432:5432" dan capainya melalui terowong SSH. Perbezaan antara soket yang mendengar, port yang diterbitkan dan peraturan tembok api diterangkan dalam cara port dan perkhidmatan yang mendengar berfungsi pada Linux.

expose: hanyalah dokumentasi dalam Compose. Ia tidak membuka apa-apa kerana tiada apa-apa yang ditutup antara kontena pada rangkaian yang sama.

Apabila network_mode host sesuai digunakan dan kosnya

Mod host menggugurkan ruang nama rangkaian container sendiri dan membolehkan proses menggunakan antara muka hos secara terus.

services:
  probe:
    image: alpine:3.20
    network_mode: host
    command: sleep infinity

Terdapat sebab yang munasabah untuk menggunakannya. Proses yang perlu melihat trafik siaran atau multicast pada rangkaian setempat, seperti penemuan peranti untuk pelayan media atau hab automasi rumah, tidak dapat melihatnya dari belakang jambatan kerana jambatan tidak memajukan trafik tersebut kepada container. Ejen pemantauan yang membaca pembilang antara muka hos memerlukan antara muka hos. Anda juga mengelakkan satu lompatan terjemahan alamat, yang penting pada kadar paket yang tinggi.

Kosnya adalah khusus.

ports: tidak lagi berfungsi. Docker memberi amaran bahawa port yang diterbitkan akan diabaikan apabila menggunakan mod rangkaian hos, dan container akan mengikat port yang diikat oleh prosesnya. Dua container mod hos yang memerlukan port 8080 akan bertembung, dan container kedua akan berhenti dengan bind: address already in use.

Penyelesaian nama berdasarkan nama perkhidmatan tidak lagi tersedia dalam kedua-dua arah. Container bukan sebahagian daripada rangkaian projek, jadi ia tidak dapat menyelesaikan db, dan perkhidmatan lain juga tidak dapat menyelesaikan namanya. Container hanya boleh mencapai perkhidmatan tersebut melalui port yang diterbitkan pada hos, biasanya pada 127.0.0.1.

Pengasingan tidak lagi tersedia. Proses yang mengikat 0.0.0.0 di dalam container mod hos akan mendengar pada setiap antara muka pelayan anda, termasuk antara muka awam, sama seperti pakej yang dipasang dengan apt. Terdapat satu kelebihan: trafik ini mengikut laluan input biasa, jadi peraturan UFW terpakai padanya. Perkara ini tidak benar bagi port yang diterbitkan.

Mod hos ialah ciri Linux Docker Engine. Docker Desktop menyokongnya hanya mulai versi 4.34 dan hanya selepas anda mengaktifkannya. Selain itu, container tidak boleh mengikat alamat IP hos dan hanya TCP serta UDP yang dikendalikan. Jika separuh pasukan anda menggunakan pelayan Linux dan separuh lagi menggunakan Docker Desktop, jangkakan fail yang sama berkelakuan secara berbeza.

Gunakan mod hos apabila anda memerlukan antara muka hos. Jangan gunakannya untuk membaiki masalah sambungan kerana biasanya ia menggantikan satu masalah dengan masalah yang lebih sukar.

Sambungkan dua projek Compose dengan rangkaian luaran

Rangkaian yang dicipta oleh satu projek tidak kelihatan kepada projek lain. Oleh itu, proksi songsang dalam proxy/compose.yaml tidak dapat melihat aplikasi dalam app/compose.yaml, walaupun pada pelayan yang sama. Penyelesaiannya ialah rangkaian yang tidak dimiliki oleh mana-mana projek.

Cipta rangkaian itu sekali secara manual:

docker network create edge

Kemudian isytiharkannya sebagai luaran dalam setiap projek. Bahagian proksi:

services:
  proxy:
    image: traefik:v3.1
    ports:
      - "80:80"
      - "443:443"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock:ro
    networks:
      - edge

networks:
  edge:
    name: edge
    external: true

Bahagian aplikasi:

services:
  app:
    image: nginx:1.27
    networks:
      - edge
      - internal
  db:
    image: postgres:16
    environment:
      POSTGRES_PASSWORD: example
    networks:
      - internal

networks:
  edge:
    name: edge
    external: true
  internal:

external: true memberitahu Compose supaya menyambung kepada rangkaian sedia ada dan bukannya mencipta rangkaian baharu, serta membiarkannya kekal pada docker compose down. Kekunci name: yang berasingan lebih penting daripada yang kelihatan: tanpa kekunci ini, Compose mencari rangkaian yang namanya tepat-tepat edge. Dengan kekunci ini, anda boleh menggunakan satu nama untuk rangkaian dalam fail dan nama lain pada hos.

Jika rangkaian itu tidak wujud, Compose enggan bermula dan melaporkan bahawa rangkaian tersebut diisytiharkan sebagai luaran tetapi tidak ditemui. Cipta rangkaian itu terlebih dahulu.

Perhatikan perkara yang dilakukan oleh fail aplikasi terhadap internal. Pangkalan data hanya berada pada rangkaian setempat projek itu, jadi proksi tidak dapat mencapainya dan hanya app boleh berbuat demikian. Menambahkan internal: true di bawah rangkaian menghapuskan terus laluannya ke dunia luar. Ini ialah tetapan lalai yang baik untuk pangkalan data, tetapi terdapat satu kesan yang perlu diketahui sebelum anda menetapkannya: bekas pada rangkaian dalaman tidak dapat memuat turun apa-apa, jadi entrypoint yang menjalankan apt-get update atau pip install semasa permulaan akan tergantung dan kemudian gagal dengan tamat masa.

Untuk persediaan lengkap yang merangkumi peraturan penghalaan dan sijil, lihat menjalankan beberapa aplikasi di belakang satu tika Traefik.

Port yang diterbitkan memintas UFW

Ini ialah bahagian rangkaian Compose yang boleh menjadi insiden keselamatan. Anda menerbitkan port, memastikan UFW aktif dan menolak semua sambungan kecuali SSH, tetapi perkhidmatan itu masih boleh dicapai dari Internet.

sudo ufw status
curl http://203.0.113.10:8080

UFW menyatakan bahawa port itu disekat. curl tetap memulangkan halaman tersebut. Tiada kerosakan berlaku. Docker menulis peraturan terjemahan alamat dan pemajuan sendiri terus ke dalam iptables. Trafik ke port container yang diterbitkan dimajukan ke container, bukannya dihantar kepada host. Oleh itu, trafik tersebut tidak melalui rantaian yang diuruskan UFW untuk trafik yang ditujukan secara setempat. Peraturan Docker juga dipadankan sebelum peraturan UFW.

Penyelesaian ringkas ialah menerbitkan port hanya pada alamat yang diperlukan:

    ports:
      - "127.0.0.1:8080:80"

Ini mengikat bahagian host kepada loopback. Oleh itu, port tersebut boleh dicapai dari pelayan itu sendiri dan melalui terowong SSH, tetapi tidak dari tempat lain. Letakkan titik masuk awam di belakang proksi songsang yang menerbitkan port 80 dan 443 secara sengaja. Penjelasan penuh, termasuk rantaian DOCKER-USER untuk keadaan yang memerlukan anda menapis port yang diterbitkan, terdapat dalam sebab Docker menerbitkan port terus melepasi UFW dan cara membetulkannya.

Cara menyahpepijatnya dengan empat perintah

Mulakan dengan menyemak rangkaian yang sebenarnya digunakan oleh setiap kontena:

docker network inspect shop_default

Blok Containers menyenaraikan setiap kontena yang disambungkan, termasuk alamatnya. Perkhidmatan yang tiada dalam senarai itu berada pada rangkaian lain, menggunakan mod hos, atau tidak sedang berjalan.

Uji resolusi nama daripada kontena sementara yang disambungkan ke rangkaian yang sama. Dengan cara ini, anda tidak memerlukan sebarang alat dalam imej anda sendiri:

docker run --rm --network shop_default busybox nslookup db
docker run --rm --network shop_default busybox nc -zv db 5432

nslookup yang gagal menunjukkan masalah pada resolusi nama atau keahlian rangkaian. Jika nslookup berjaya tetapi nc gagal, ini bermakna perkhidmatan sedang berjalan tetapi tidak mendengar pada port tersebut, atau mendengar pada 127.0.0.1 dalam kontenanya sendiri dan bukannya pada 0.0.0.0. Situasi terakhir ini biasa berlaku pada pelayan pembangunan. Pembetulannya adalah pada alamat bind aplikasi, bukan pada Docker.

Terdapat satu lagi kegagalan yang kelihatan seperti pepijat Docker. Jika kontena boleh berkomunikasi antara satu sama lain tetapi tidak boleh mencapai mesin dalam rangkaian pejabat atau VPN anda, subnet Docker mungkin bertindih dengan rangkaian tersebut. Docker memperuntukkan subnet daripada 172.17.0.0/16 dan seterusnya secara lalai. Alihkan pool itu dalam /etc/docker/daemon.json:

{
  "default-address-pools": [
    { "base": "10.200.0.0/16", "size": 24 }
  ]
}

Kemudian jalankan sudo systemctl restart docker dan cipta semula rangkaian yang terjejas kerana rangkaian sedia ada mengekalkan subnet yang digunakan semasa rangkaian itu dicipta.

FAQ

Mengapa bekas saya tidak dapat berhubung antara satu sama lain menggunakan nama perkhidmatan?

Bekas tersebut tidak berada pada rangkaian yang sama. Compose meletakkan setiap perkhidmatan pada <project>_default secara automatik. Namun, apabila anda menambahkan senarai networks: pada sesuatu perkhidmatan, senarai itu menjadi keseluruhan set rangkaian untuk perkhidmatan tersebut dan rangkaian lalai tidak lagi digunakan secara tersirat. Jalankan docker network inspect <network> dan semak bahawa kedua-dua bekas muncul dalam blok Containers. Semak juga bahawa tiada perkhidmatan menggunakan network_mode: host, kerana bekas dalam mod host tidak berada pada mana-mana rangkaian Docker dan tidak dapat menyelesaikan nama perkhidmatan.

Adakah saya perlu menerbitkan port supaya satu perkhidmatan dapat berhubung dengan perkhidmatan lain?

Tidak. Pada rangkaian Compose, setiap port bagi setiap bekas boleh dicapai oleh bekas lain pada rangkaian tersebut. ports: hanya digunakan untuk mendedahkan bekas kepada trafik dari luar Docker, manakala expose: ialah dokumentasi. Menerbitkan port pangkalan data ialah amalan yang biasa dan berisiko, kerana tindakan itu meletakkan pangkalan data pada antara muka awam pelayan anda.

Apakah perbezaan antara rangkaian bridge dengan rangkaian host?

Bridge memberikan bekas ruang nama rangkaian dan alamatnya sendiri pada suis maya, dengan penyelesaian nama automatik antara bekas serta penterjemahan trafik keluar. Host memberikan bekas akses terus kepada tindanan rangkaian hos: tiada alamat berasingan, tiada penyelesaian nama menggunakan nama perkhidmatan, tiada penerbitan port dan tiada pengasingan daripada pendengar lain pada hos. Bridge ialah tetapan lalai dan pilihan yang sesuai, melainkan proses tersebut memerlukan antara muka hos.

Bagaimanakah saya menyambungkan bekas daripada dua fail Compose yang berbeza?

Cipta rangkaian dikongsi menggunakan docker network create edge. Kemudian, isytiharkan rangkaian itu dalam kedua-dua fail menggunakan external: true dan sambungkan perkhidmatan yang perlu berkomunikasi. Compose tidak akan mencipta atau memadam rangkaian tersebut. Jika anda melangkau langkah penciptaan, Compose enggan bermula dan melaporkan bahawa rangkaian itu diisytiharkan sebagai luaran tetapi tidak ditemui.

Mengapa bekas saya boleh dicapai dari Internet walaupun UFW menyekat port tersebut?

Kerana port yang diterbitkan dikendalikan oleh peraturan pemajuan yang ditambahkan oleh Docker pada iptables. Peraturan tersebut dipadankan sebelum peraturan UFW, dan trafik yang dimajukan juga tidak melalui rantaian yang ditapis oleh UFW. Ikat bahagian hos pada gelung balik menggunakan "127.0.0.1:8080:80" dan letakkan apa-apa yang bersifat awam di belakang proksi songsang pada port 80 dan 443.