How Docker maps a containerized port to your local machine?

How Docker maps a containerized port to your local machine?

Docker 是如何将容器端口映射到本地机器的?

When you spin up a database inside a Docker container, you are essentially launching an entirely isolated, lightweight operating system that lives inside your physical machine. This isolated environment has its own file system, its own memory limits, and crucially, its own private network. 当你在一个 Docker 容器中启动数据库时,本质上是在你的物理机内运行了一个完全隔离的轻量级操作系统。这个隔离环境拥有独立的文件系统、内存限制,以及至关重要的私有网络。

By default, a Docker container is completely sealed off from your local machine (which we refer to as the “host”). If a PostgreSQL database is running inside that container, it will listen for connections on its standard default port, which is 5432. However, because the container’s network is private, your local Node.js application—which runs on your host machine—cannot see or communicate with that database. The traffic is trapped behind the container’s network boundary. 默认情况下,Docker 容器与你的本地机器(我们称之为“宿主机”)是完全隔绝的。如果一个 PostgreSQL 数据库在容器内运行,它会监听其标准的默认端口 5432。然而,由于容器的网络是私有的,运行在宿主机上的本地 Node.js 应用程序无法看到或连接到该数据库。流量被困在了容器的网络边界之内。

To allow your Node.js application to talk to the PostgreSQL database, we have to deliberately puncture a hole through that network boundary. We do this through a mechanism called Port Forwarding or Port Mapping. When we configure the container, we define a strict mapping rule that takes the format of Host Port : Container Port. If we map 5432:5432, we are telling Docker: “Listen to port 5432 on my actual physical laptop. Whenever any traffic hits that port, forward it directly into the container’s internal port 5432.” 为了让 Node.js 应用程序能够与 PostgreSQL 数据库通信,我们必须刻意在网络边界上“打个洞”。我们通过一种称为“端口转发”或“端口映射”的机制来实现。在配置容器时,我们会定义一个严格的映射规则,格式为“宿主机端口 : 容器端口”。如果我们映射 5432:5432,就是在告诉 Docker:“监听我物理笔记本上的 5432 端口。每当有流量到达该端口时,直接将其转发到容器内部的 5432 端口。”

Why we map ports instead of just exposing the container directly:

为什么要使用端口映射,而不是直接暴露容器:

Conflict Resolution: Suppose you already have an old version of PostgreSQL installed directly on your laptop for a different project, and it is currently hogging your laptop’s port 5432. If we tried to bind our container to the same port, the startup would crash. Port mapping allows us to map a different host port (like 5433) to the container’s 5432 port. The container remains completely unaware of this; it still thinks it’s communicating on 5432, while your host machine neatly avoids a collision. 冲突解决: 假设你的笔记本上已经为另一个项目安装了旧版本的 PostgreSQL,并且它正占用着 5432 端口。如果我们尝试将容器绑定到同一个端口,启动就会失败。端口映射允许我们将不同的宿主机端口(例如 5433)映射到容器的 5432 端口。容器对此一无所知;它仍然认为自己在 5432 端口上通信,而你的宿主机则巧妙地避免了冲突。

Security and Control: By explicitly declaring which internal ports are mapped to the outside world, we practice the principle of least privilege. Everything else inside the container remains entirely locked down and inaccessible. This isolation is why containerizing software applications is standard practice. We never have to worry about polluting our host machine with background services, left-over configuration files, or competing database versions. When we are done working on the ledger, we simply stop the container, and our machine is perfectly clean. 安全与控制: 通过明确声明哪些内部端口映射到外部世界,我们践行了“最小权限原则”。容器内的其他一切内容都保持完全锁定且不可访问。这种隔离性正是软件容器化成为标准做法的原因。我们无需担心后台服务、残留的配置文件或冲突的数据库版本会污染宿主机。当我们完成工作后,只需停止容器,机器就能保持完全整洁。