Dalam pengaturan multi-kontainer, layanan yang berjalan di kontainer berkomunikasi satu sama lain melalui jaringan umum. Dalam pengaturan yang sama, beberapa wadah juga berinteraksi dengan dunia luar.
Komunikasi internal dan eksternal ini ditangani masing-masing dengan port yang terbuka dan yang dipublikasikan di Docker.
Dalam tutorial ini, saya akan membahas menangani port di Docker. Saya akan membahas perbedaan antara mengekspos dan memublikasikan port, mengapa port tersebut digunakan dan bagaimana menggunakannya.
Mengekspos vs memublikasikan port di Docker
Ada dua cara untuk menangani port di Docker:mengekspos port dan memublikasikan port.
Mengekspos port berarti memberi tahu orang lain di port mana aplikasi dalam container akan mendengarkan, atau menerima koneksi. Ini untuk berkomunikasi dengan wadah lain, bukan dengan dunia luar.
Menerbitkan port lebih seperti memetakan port wadah dengan port host. Dengan cara ini, wadah dapat berkomunikasi dengan sistem eksternal, dunia nyata, internet.
Grafik ini akan membantu Anda memahami.
Anda lihat, bagaimana port 80 container SERVER dipetakan ke port 80 dari sistem host? Dengan cara ini, wadah dapat berkomunikasi dengan dunia luar menggunakan alamat IP publik dari sistem host.
Port terbuka, di sisi lain, tidak dapat diakses langsung dari luar dunia kontainer.
Untuk diingat:
- Port yang terbuka digunakan untuk komunikasi kontainer internal, di dalam dunia kontainer.
- Port yang dipublikasikan digunakan untuk berkomunikasi dengan sistem di luar dunia container.
Mengekspos port di Docker
Pertama-tama, mengekspos port tidak sepenuhnya diperlukan. Mengapa? Karena sebagian besar gambar buruh pelabuhan yang Anda gunakan dalam pengaturan Anda sudah memiliki port default yang terbuka dalam konfigurasinya.
Misalnya, aplikasi frontend dalam container dapat berkomunikasi dengan database MariaDB hanya dengan menentukan IP container dan port mana pun yang menerima koneksi MariaDB (default 3306).
Mengekspos membantu dalam situasi di mana default tidak digunakan, seperti dalam kasus ini jika MariaDB tidak menerima koneksi pada port 3306, port alternatif harus disebutkan dengan mengeksposnya.
Ada dua cara untuk mengekspos port:
- Menggunakan
EXPOSE
Instruksi Dockerfile. - Menggunakan
--expose
dengan buruh pelabuhan CLI atauexpose
masukkan docker-compose.
Saatnya menyelami keduanya lebih dalam.
Metode 1:Buka port melalui Dockerfile
Anda dapat menambahkan instruksi sederhana di Dockerfile Anda untuk memberi tahu orang lain di port mana aplikasi Anda akan menerima koneksi.
Tentang instruksi ini, yang harus Anda ketahui adalah sebagai berikut:-
EXPOSE
tidak tambahkan lapisan tambahan ke gambar buruh pelabuhan yang dihasilkan. Itu hanya menambahkan metadata.EXPOSE
adalah cara mendokumentasikan port aplikasi Anda. Satu-satunya efek yang dimilikinya adalah dalam hal keterbacaan atau pemahaman aplikasi.
Anda dapat melihat cara kerja eksposur dengan gambar wadah sederhana yang saya buat hanya untuk tujuan ini. Gambar ini tidak melakukan apa-apa .
Tarik gambarnya.
docker pull debdutdeb/expose-demo:v1
Gambar ini memperlihatkan total empat port, daftar gambar menggunakan perintah berikut.
docker image ls --filter=reference=debdutdeb/expose-demo:v1
Perhatikan SIZE
kolom, itu akan mengatakan 0 byte.
➟ docker image ls --filter=reference=debdutdeb/expose-demo:v1
REPOSITORY TAG IMAGE ID CREATED SIZE
debdutdeb/expose-demo v1 ad3d8ffa9bfe N/A 0B
Alasannya sederhana, tidak ada lapisan dalam gambar ini, semua instruksi paparan yang ditambahkan adalah metadata, tidak ada lapisan nyata.
Anda juga bisa mendapatkan jumlah lapisan yang tersedia menggunakan perintah berikut:-
docker image inspect -f '{{len .RootFS.Layers}}' debdutdeb/expose-demo:v1
Anda akan melihat output seperti ini:-
➟ docker image inspect -f '{{len .RootFS.Layers}}' debdutdeb/expose-demo:v1
0
Seperti yang saya katakan sebelumnya, port yang terbuka ditambahkan sebagai metadata gambar, untuk memberi tahu kami port mana yang digunakan aplikasi.
Bagaimana Anda melihat informasi itu tanpa melihat Dockerfile? Anda perlu memeriksa gambar. Untuk lebih spesifik, lihat perintah di bawah ini, Anda dapat menggunakan perintah serupa pada gambar apa pun untuk membuat daftar port yang terbuka.
Saya menggunakan contoh gambar saya untuk demonstrasi.
docker image inspect -f \
'{{range $exposed, $_ := .Config.ExposedPorts}}{{printf "%s\n" $exposed}}{{end}}' \
debdutdeb/expose-demo:v1
Contoh keluaran:
➟ docker image inspect -f '{{range $exposed, $_ := .Config.ExposedPorts}}{{printf "%s\n" $exposed}}{{end}}' debdutdeb/expose-demo:v1
443/tcp
80/tcp
8080/tcp
9090/tcp
Anda juga dapat membandingkan gambar ini, yang memperlihatkan beberapa port, dengan debdutdeb/noexpose-demo:v1
image, yang tidak memperlihatkan port apa pun. Jalankan rangkaian perintah yang sama pada gambar itu juga dan perhatikan perbedaannya.
Metode 2:Mengekspos port melalui CLI atau docker-compose
Terkadang pengembang aplikasi enggan menyertakan EXPOSE
tambahan instruksi di Dockerfile mereka.
Dalam kasus seperti itu untuk memastikan wadah lain (melalui API buruh pelabuhan) dapat mendeteksi port yang digunakan dengan mudah, Anda dapat mengekspos beberapa port pasca-pembuatan, sebagai bagian dari proses penerapan.
Pilih metode imperatif, yaitu CLI, atau metode deklaratif, yaitu menulis file.
metode CLI
Dalam metode ini, saat membuat wadah, yang harus Anda lakukan adalah menggunakan --expose
opsi (sebanyak yang diperlukan) dengan nomor port dan opsional protokol dengan /
. Ini salah satu contohnya:-
docker container run \
--expose 80 \
--expose 90 \
--expose 70/udp \
-d --name port-expose busybox:latest sleep 1d
Saya menggunakan busybox
image yang tidak mengekspos port apa pun secara default.
Metode penulisan file
Jika Anda menggunakan file penulisan, Anda dapat menambahkan array expose
dalam definisi layanan. Anda dapat mengonversi penerapan sebelumnya ke file penulisan seperti:-
version: "3.7"
services:
PortExpose:
image: busybox
command: sleep 1d
container_name: port-expose
expose:
- 80
- 90
- 70/udp
Setelah container berjalan, sama seperti sebelumnya Anda dapat memeriksanya untuk mengetahui port mana yang terbuka. Perintahnya terlihat serupa.
docker container inspect -f \
'{{range $exposed, $_ := .NetworkSettings.Ports}}
{{printf "%s\n" $exposed}}{{end}}' \
port-expose
Contoh keluaran:-
➟ docker container inspect -f '{{range $exposed, $_ := .NetworkSettings.Ports}}{{printf "%s\n" $exposed}}{{end}}' port-expose
70/udp
80/tcp
90/tcp
Menerbitkan port di Docker
Penerbitan port adalah sinonim untuk penerusan port di mana permintaan dari koneksi masuk pada port publik diteruskan ke port kontainer.
Demikian pula, tanggapan yang dikirim dari wadah melalui portnya dikirim ke klien dengan meneruskan lalu lintas ke port yang ditentukan di ruang port host.
Ada dua cara memublikasikan port, satu melalui CLI dan lainnya menggunakan file penulisan. Kedua metode juga memiliki satu sintaksis panjang dan satu sintaksis pendek.
Metode 1:Publikasikan port melalui perintah Docker
Kedua sintaks tersebut adalah sebagai berikut:
-p [optional_host_ip]:[host_port]:[container_port]/[optional_protocol]
--publish target=[container_port],published=[optional_host_ip]:[host_port],protocol=[optional_protocol]
Untuk IP host opsional, Anda dapat menggunakan alamat IP apa pun yang terkait dengan NIC mana pun. Jika IP dihilangkan, buruh pelabuhan akan mengikat port dengan semua alamat IP yang tersedia.
Anda akan menggunakan yang pertama paling banyak. Yang kedua lebih mudah dibaca. Mari kita lihat contoh menggunakan wadah nginx. Jalankan perintah berikut:-
docker container run --rm --name nginx \
--publish target=80,published=127.0.0.1:8081,protocol=tcp \
-d nginx
Dengan perintah ini saya hanya mengikat port 80 penampung ke port 8081 Host saya di localhost. Sekarang jika Anda menuju ke http://localhost:8081 Anda akan melihat nginx berjalan.
Perintah sebelumnya dapat dengan mudah dikonversi ke bentuk yang lebih pendek seperti ini
docker container run --rm --name nginx \
-p 80:127.0.0.1:8081/tcp -d nginx
Meskipun lebih pendek, lebih sulit untuk dibaca.
Anda juga dapat menggunakan -p
atau --publish
beberapa kali untuk memublikasikan beberapa port.
Metode 2:Memublikasikan port melalui file penulisan
Untuk memublikasikan port menggunakan file penulisan, Anda memerlukan array bernama ports
dalam definisi layanan. Array ini dapat berupa daftar string yang terlihat mirip dengan sintaks pendek CLI, atau Anda dapat menggunakan daftar objek yang mirip dengan sintaks panjang.
Jika saya mengonversi penerapan nginx sebelumnya menggunakan file penulisan dengan array string untuk bagian port, itu akan terlihat seperti berikut:-
version: "3.7"
services:
Nginx:
image: nginx
container_name: nginx
ports:
- 80:127.0.0.1:8081/tcp
Izinkan saya juga menunjukkan cara menggunakan sintaks array objek.
version: "3.7"
services:
Nginx:
image: nginx
container_name: nginx
ports:
- target: 80
published: 127.0.0.1:8081
protocol: tcp
Untuk melihat daftar semua port yang dipublikasikan, Anda dapat memeriksa container seperti ini-
docker container inspect -f '{{range $container, $host := .NetworkSettings.Ports}}{{printf "%s -> %s\n" $container $host}}{{end}}' nginx
Jika dijalankan, Anda akan melihat output berikut:-
➟ docker container inspect -f '{{range $container, $host := .NetworkSettings.Ports}}{{printf "%s -> %s\n" $container $host}}{{end}}' nginx
80/tcp -> [{127.0.0.1 8081}]
Ada cara lain yang lebih mudah untuk membuat daftar port yang diterbitkan, menggunakan docker container port
perintah.
docker container port nginx
Contoh keluaran:-
➟ docker container port nginx
80/tcp -> 127.0.0.1:8081
Kapan mengekspos port dan kapan memublikasikannya?
Ini adalah pertanyaan yang adil. Mengekspos dan menerbitkan tidak seharusnya menjadi pesaing. Masing-masing melayani tujuan yang berbeda. Jika Anda adalah pengembang gambar, Anda akan mengekspos port sehingga pengguna dapat lebih yakin di mana mencoba koneksi. Di sisi lain, jika Anda menggunakan gambar dan Anda perlu membuatnya tersedia untuk dunia luar, Anda akan memublikasikan port yang diperlukan.
Saya harap artikel ini bermanfaat bagi Anda. Jika Anda memiliki pertanyaan, beri tahu saya di komentar di bawah.