1. Overview
1.概述
As we know, Docker Compose is a tool for defining and managing multiple containers at once. By default, Docker Compose sets up a dedicated network for the defined containers, enabling communication between them. As a result, we can create and run services with a given configuration file using a single command.
正如我们所知,Docker Compose是一个用于一次性定义和管理多个容器的工具。默认情况下,Docker Compose为所定义的容器设置了一个专用网络,使它们之间能够进行通信。因此,我们可以使用一个命令来创建和运行具有给定配置文件的服务。
In this tutorial, we’ll focus on two YAML properties that allow us to customize networking between containers, expose and ports. We’ll describe them in detail, explore the basic use cases, and highlight their key differences.
在本教程中,我们将关注两个YAML属性,它们允许我们自定义容器之间的网络,即expose和ports。我们将详细描述它们,探讨基本用例,并强调它们的主要区别。
2. expose Section
2.曝光部分
First, let’s look at the expose configuration. This property defines the ports that Docker Compose exposes from the container.
首先,让我们看一下expose配置。这个属性定义了Docker Compose从容器中暴露的端口。
These ports will be accessible by other services connected to the same network, but won’t be published on the host machine.
这些端口将被连接到同一网络的其他服务访问,但不会在主机上发布。
We can expose a port by specifying its number in the services section:
我们可以通过在services部分指定一个端口的编号来暴露一个端口。
services:
myapp1:
...
expose:
- "3000"
- "8000"
myapp2:
...
expose:
- "5000"
As we can see, we can specify multiple values for each service. We just exposed the ports 3000 and 8000 from the myapp1 container, and the port 5000 from the myapp2 container. The services are now accessible on these ports for other containers in the same network.
正如我们所见,我们可以为每个服务指定多个值。我们刚刚暴露了3000和8000端口,来自myapp1容器,以及myapp2容器的5000端口。现在,同一网络中的其他容器可以通过这些端口访问这些服务。
Now let’s check exposed ports:
现在让我们检查一下暴露的端口。
> docker ps
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
8673c14f18d1 ... ... ... ... 3000/tcp, 8000/tcp bael_myapp1
bc044e180131 ... ... ... ... 5000/tcp bael_myapp2
In the docker ps command output, we can find the exposed ports in the PORTS column.
在docker ps命令输出中,我们可以在PORTS列中找到暴露的端口。
Finally, let’s verify the communication between the containers:
最后,让我们验证一下容器之间的通信。
> 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
We just connected to the myapp2 CLI. Using the netcat command, we checked that both the ports exposed from myapp1 were reachable.
我们刚刚连接到myapp2CLI。使用netcat命令,我们检查了从myapp1暴露的两个端口都可以到达。
3. ports Section
3.港口部分
Now let’s check the ports section. As with expose, this property defines the ports that we want to expose from the container. But unlike with the expose configuration, these ports will be accessible internally and published on the host machine.
现在让我们检查一下ports部分。与expose一样,这个属性定义了我们想从容器中暴露的端口。但与expose配置不同,这些端口将被内部访问并在主机上发布。
Again, as before, we can define ports for each service in the dedicated section, but the configuration might be more complex. First, we have to choose between two syntaxes (short and long) to define the configuration.
同样,和以前一样,我们可以在专用部分为每个服务定义端口,但配置可能更复杂。首先,我们必须选择两种语法(短和长)来定义配置。
3.1. Short Syntax
3.1.短句法
Let’s start by analyzing the short one. The short syntax is a colon-separated string to set the host IP address, host port, and container port:
我们先来分析一下短的。短的语法是用冒号分隔的字符串来设置主机IP地址、主机端口和容器端口。
[HOST:]CONTAINER[/PROTOCOL]
Here, HOST is a host port number or range of port numbers that can be preceded by an IP address. If we don’t specify the IP address, Docker Compose binds the port to all the network interfaces.
这里,HOST是一个主机端口号或端口号范围,前面可以加上一个IP地址。如果我们不指定IP地址,Docker Compose会将端口绑定到所有的网络接口上。
CONTAINER defines a container port number or range of port numbers.
CONTAINER定义了一个容器端口号或端口号范围。
PROTOCOL restricts container ports to the specified protocol or sets them to TCP if empty. Only the CONTAINER part is mandatory.
PROTOCOL将容器端口限制为指定的协议,如果为空,则将其设置为TCP。只有CONTAINER部分是强制性的。
Now that we know the syntax, let’s define the ports in our Docker Compose file:
现在我们知道了这个语法,让我们在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)
As presented above, we can also publish multiple container ports at once using different variants of the short syntax and configuring it more precisely. Docker Compose exposes all specified container ports, making them reachable internally and externally from the local machine.
如上所述,我们还可以使用短语法的不同变体,更精确地配置它,一次发布多个容器端口。Docker Compose会公开所有指定的容器端口,使它们可以从本地机器的内部和外部到达。
As before, let’s check the exposed ports with the docker ps command:
像以前一样,让我们用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
Once again, in the PORTS column, we can find all the exposed ports. The value to the left of the arrow shows the host address where we can reach the container externally.
再一次,在PORTS列中,我们可以找到所有暴露的端口。箭头左边的值显示了我们可以从外部到达容器的主机地址。
3.2. Long Syntax
3.2.长句法
Using the long syntax, we can configure the ports in the same way. However, instead of using a colon-separated string, we’ll define each property individually:
使用长的语法,我们可以用同样的方式配置端口。然而,我们不是使用冒号分隔的字符串,而是单独定义每个属性。
services:
myapp1:
...
ports:
# - "127.0.0.1:6060:6060/udp"
- target: 6060
host_ip: 127.0.0.1
published: 6060
protocol: udp
mode: host
Here, the target is mandatory and specifies the container port (or range of ports) that will be exposed, which is equivalent to the CONTAINER in the short syntax.
这里,target是强制性的,它指定了将被暴露的容器端口(或端口范围),这相当于短语法中的CONTAINER。
The host_ip and published are parts of HOST in the short one, where we can define the host’s IP address and port.
host_ip和published是短篇中HOST的一部分,在这里我们可以定义主机的IP地址和端口。
The protocol, the same as PROTOCOL in the short syntax, restricts the container port to the specified protocol (or TCP if empty).
protocol,与短语法中的PROTOCOL相同,将容器端口限制为指定的协议(如果为空,则为TCP)。
The mode is the enum with two values that specifies port publishing rules. We should use the host value to publish a port locally. The second value, ingress, is reserved for more complex container environments, and means the port will be load balanced.
mode是一个有两个值的枚举,指定了端口发布规则。我们应该使用host值来在本地发布一个端口。第二个值,ingress,是为更复杂的容器环境保留的,它意味着端口将被负载平衡。
In conclusion, any short syntax string can easily be represented by a long structure. However, not all long syntax configurations can be moved to the short one due to the lack of a mode property.
总之,任何短语法字符串都可以很容易地由长结构来表示。然而,由于缺乏mode属性,并不是所有的长语法配置都可以移到短语法配置中。
4. Conclusion
4.总结
In this article, we covered part of the networking configurations in the Docker Compose. We analyzed and compared port configuration using the expose and ports sections.
在这篇文章中,我们介绍了Docker Compose中的部分网络配置。我们使用expose和ports部分分析和比较了端口配置。
The expose section allows us to expose specific ports from our container only to other services on the same network. We can do this simply by specifying the container ports.
expose部分允许我们将我们的容器的特定端口只暴露给同一网络上的其他服务。我们可以简单地通过指定容器的端口来做到这一点。
The ports section also exposes specified ports from containers. Unlike the previous section, ports are open not only for other services on the same network, but also to the host. The configuration is a bit more complex, where we can configure the exposed port, local binding address, and restricted protocol. Finally, depending on our preferences, we can choose between the two different syntaxes.
ports部分也从容器中暴露了指定的端口。与上一节不同的是,端口不仅对同一网络上的其他服务开放,而且对主机开放。这个配置有点复杂,我们可以配置暴露的端口、本地绑定地址和受限协议。最后,根据我们的喜好,我们可以选择两种不同的语法。