Docker 的 -p 8080:80 是最容易让人困惑的参数之一。
()
| 283 | # ============================================================ |
| 284 | |
| 285 | def lesson_4_port_mapping(): |
| 286 | """ |
| 287 | Docker 的 -p 8080:80 是最容易让人困惑的参数之一。 |
| 288 | """ |
| 289 | print("\n" + "=" * 60) |
| 290 | print("第四课: 端口映射") |
| 291 | print("=" * 60) |
| 292 | |
| 293 | print(""" |
| 294 | 场景: 你在 Docker 里运行了一个网站,它监听 80 端口。 |
| 295 | 但容器有自己的网络命名空间——外面看不到容器里的 80 端口。 |
| 296 | |
| 297 | docker run -p 8080:80 nginx |
| 298 | ↑ ↑ |
| 299 | │ └── 容器内部的端口 (nginx 监听 80) |
| 300 | └─────── 宿主机暴露的端口 (你用 8080 访问) |
| 301 | |
| 302 | 这就是"端口映射"——在两个隔离的网络之间开一个"传送门"。 |
| 303 | |
| 304 | ┌──────────────────────────────────────────────┐ |
| 305 | │ 宿主机 │ |
| 306 | │ │ |
| 307 | │ 浏览器 ──→ localhost:8080 ──┐ │ |
| 308 | │ │ 端口映射 │ |
| 309 | │ ┌──────────────────────┐ │ │ |
| 310 | │ │ Docker 容器 │ │ │ |
| 311 | │ │ (独立网络命名空间) │ │ │ |
| 312 | │ │ │ │ │ |
| 313 | │ │ nginx ←── :80 ◄─────┘ │ |
| 314 | │ │ │ │ |
| 315 | │ │ 内部 IP: 172.17.0.2 │ │ |
| 316 | │ └──────────────────────┘ │ |
| 317 | └──────────────────────────────────────────────┘ |
| 318 | |
| 319 | 访问 localhost:8080 → Docker 把流量转发到容器的 80 → nginx 响应 |
| 320 | """) |
| 321 | |
| 322 | # 用 Python 模拟端口转发 |
| 323 | print(" 用 Python 模拟端口转发的工作原理:") |
| 324 | print(" (不需要 Docker,纯 Python 演示)") |
| 325 | |
| 326 | # "容器内部"的服务器 |
| 327 | internal_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 328 | internal_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
| 329 | internal_server.bind(("127.0.0.1", 0)) |
| 330 | internal_port = internal_server.getsockname()[1] |
| 331 | internal_server.listen(1) |
| 332 | internal_server.settimeout(3) |
| 333 | |
| 334 | # 端口转发器(模拟 Docker 的端口映射) |
| 335 | proxy_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) |
| 336 | proxy_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) |
| 337 | proxy_server.bind(("127.0.0.1", 0)) |
| 338 | external_port = proxy_server.getsockname()[1] |
| 339 | proxy_server.listen(1) |
| 340 | proxy_server.settimeout(3) |
| 341 | |
| 342 | print(f" '容器内' 服务监听: 127.0.0.1:{internal_port}") |
no outgoing calls
no test coverage detected