Docker Compose 中的 Expose 和 Ports 的區別
一、概述
眾所周知,Docker Compose 是一個同時定義和管理多個容器的工具。默認情況下,Docker Compose 為定義的容器設置了一個專用網絡,從而實現它們之間的通信。因此,我們可以使用單個命令使用給定的配置文件創建和運行服務。
在本教程中,我們將看到兩個 YAML 屬性,它們允許我們自定義容器之間的網絡——expose和ports
。我們將詳細描述它們,展示基本用例,並突出它們的主要區別。
2. expose
部分
首先,讓我們看一下expose
配置。此屬性定義 Docker Compose 從容器公開的端口。
這些端口可由連接到同一網絡的其他服務訪問,但不會在主機上發布。
我們可以通過在services
部分指定端口號來公開端口:
services:
myapp1:
...
expose:
- "3000"
- "8000"
myapp2:
...
expose:
- "5000"
如我們所見,我們可以為每個服務指定多個值。我們剛剛暴露了myapp2
容器的3000
和8000
端口以及myapp1
容器的5000
端口。現在,同一網絡中的其他容器可以在這些端口上訪問這些服務。
現在讓我們檢查暴露的端口:
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8673c14f18d1 ... ... ... ... 3000/tcp, 8000/tcp bael_myapp1
bc044e180131 ... ... ... ... 5000/tcp bael_myapp2
在docker ps
命令輸出中,我們可以在PORTS
列中找到暴露的端口。
最後,我們來驗證一下容器之間的通信:
> docker exec -it bc044e180131 /bin/bash
bash-5.1$ nc -vz myapp1 3000
myapp1 (172.18.0.1:3000) open
bash-5.1$ nc -vz myapp1 8000
myapp1 (172.18.0.1:8000) open
我們剛剛連接到myapp2
CLI。使用netcat
命令,我們檢查了從myapp1
公開的兩個端口是否都可以訪問。
3.端口部分
現在讓我們檢查ports
部分。和以前一樣,這個屬性定義了我們想要從容器中公開的端口。但與expose
配置不同的是,這些端口可以在內部訪問並在主機上發布。
和以前一樣,我們可以在專用部分為每個服務定義端口,但配置可能更複雜。首先,我們必須在兩種語法(短和長)之間進行選擇來定義配置。
3.1。短句法
讓我們從分析短的開始。簡短語法是一個以冒號分隔的字符串,用於設置主機 IP 地址、主機端口和容器端口:
[HOST:]CONTAINER[/PROTOCOL]
這裡, HOST
是一個主機端口號或一系列端口號,可以在前面加上一個 IP 地址。如果我們不指定 IP 地址,Docker Compose 會將端口綁定到所有網絡接口。
C ONTAINER
定義一個容器端口號或一系列端口號。
PROTOCOL
將容器端口限制為指定的協議,如果為空,則將它們設置為TCP
。只有CONTAINER
部分是強制性的。
現在我們知道了語法,讓我們在 Docker Compose 文件中定義端口:
services:
myapp1:
...
ports:
- "3000" # container port (3000), assigned to random host port
- "3001-3005" # container port range (3001-3005), assigned to random host ports
- "8000:8000" # container port (8000), assigned to given host port (8000)
- "9090-9091:8080-8081" # container port range (8080-8081), assigned to given host port range (9090-9091)
- "127.0.0.1:8002:8002" # container port (8002), assigned to given host port (8002) and bind to 127.0.0.1
- "6060:6060/udp" # container port (6060) restricted to UDP protocol, assigned to given host (6060)
如上所述,我們還可以一次發布多個容器端口,使用不同的短語法變體並更精確地配置它。 Docker Compose 公開所有指定的容器端口,使它們可以從本地機器內部和外部訪問。
和以前一樣,讓我們使用docker ps
命令檢查暴露的端口:
> docker ps -a
CONTAINER ID ... PORTS NAMES
e8c65b9eec91 ... 0.0.0.0:51060->3000/tcp, 0.0.0.0:51063->3001/tcp, 0.0.0.0:51064->3002/tcp, bael_myapp1
0.0.0.0:51065->3003/tcp, 0.0.0.0:51061->3004/tcp, 0.0.0.0:51062->3005/tcp,
0.0.0.0:8000->8000/tcp, 0.0.0.0:9090->8080/tcp, 0.0.0.0:9091->8081/tcp
127.0.0.1:8002->8002/tcp, 0.0.0.0:6060->6060/udp
再一次,在PORTS
列中,我們可以找到所有暴露的端口。箭頭左側的值顯示了我們可以從外部訪問容器的主機地址。
3.2.長語法
使用長語法,我們可以以相同的方式配置端口。但是,我們不使用冒號分隔的字符串,而是單獨定義每個屬性:
services:
myapp1:
...
ports:
# - "127.0.0.1:6060:6060/udp"
- target: 6060
host_ip: 127.0.0.1
published: 6060
protocol: udp
mode: host
在這裡, target
是強制性的,它指定了將要暴露的容器端口(或端口範圍),相當於簡寫中的CONTAINER
。
host_ip
和published
是HOST
中的一部分,我們可以在其中定義主機的IP 地址和端口。
該protocol,
與縮寫語法中的PROTOCOL
相同,將容器端口限制為指定的協議(如果為空,則為TCP
)。
mode
是具有兩個指定端口發布規則的值的枚舉。我們應該使用host
值在本地發布端口。第二個值—— ingress
——為更複雜的容器環境保留,意味著端口將被負載平衡。
總之,任何短語法字符串都可以很容易地用長結構表示。但是,由於缺少mode
屬性,並非所有長語法配置都可能移至短語法配置。
4。結論
在本文中,我們剛剛介紹了 Docker Compose 中的部分網絡配置。我們使用expose
和ports
部分分析和比較了端口配置。
expose
部分允許我們將容器中的特定端口僅暴露給同一網絡上的其他服務。我們可以簡單地通過指定容器端口來做到這一點。
ports
部分還公開了容器中的指定端口。與前一種不同,
端口不僅對同一網絡上的其他服務開放,而且對主機開放。配置稍微複雜一些,我們可以配置暴露端口、本地綁定地址和受限協議。根據我們的喜好,我們可以在兩種不同的語法之間進行選擇。