SSF0SSF0
首页
前端
  • Node
  • Go
  • C#
  • MySql
  • Bash
  • Git
  • Docker
  • VuePress
  • CI/CD
  • 服务器
  • 网站
  • 学习资料
  • 软件
Timeline
Github
标签
分类
首页
前端
  • Node
  • Go
  • C#
  • MySql
  • Bash
  • Git
  • Docker
  • VuePress
  • CI/CD
  • 服务器
  • 网站
  • 学习资料
  • 软件
Timeline
Github
标签
分类
  • Bash

    • Bash 获取路径在不同类型电脑的区别
  • Git

    • Git 使用 ssh 与 https 的区别
    • Git 回滚、重置与变基
    • 文件名大小写发生变化的坑
    • Git 提交信息规范解读与实践指南
    • Git 历史邮箱统一 + 推送 GitHub 后的远程分支处理指南
  • Docker

    • Docker 命令大全
    • nginx 镜像部署静态文件
    • Docker 运行命令说明
    • 使用 node 镜像运行本地项目
    • 挂载和卷的区别
    • Docker 打包多平台镜像
    • Docker 使用 mysql
    • Docker 容器网络访问问题总结
  • VuePress

    • 使用 VuePress 搭建个人博客概括
  • CI/CD

    • blog 使用 Github-Actions 部署 docker 服务器
  • 服务器

    • 腾讯云使用 ssh 连接服务器(Linux 实例)
    • ssl 证书安装到 docker 服务器
    • 操作系统与架构
    • ssh 连接时长问题
  • 掌握 hosts 文件:本地开发、域名重定向与回调处理完全指南
  • Cloudflare DNS与代理:完全指南

Docker 容器网络访问问题总结

在使用 Docker 部署 Node 或其他服务时,常常会遇到 “在容器内使用 localhost/127.0.0.1 无法被宿主机访问” 的问题。本文将基于一系列讨论,总结容器网络相关的概念与常见解决方案。


1. 基础概念

  1. 容器网络隔离

    Docker 会为每个容器分配独立的网络命名空间,相当于一个虚拟网络。容器中使用的 localhost(或 127.0.0.1)仅表示该容器的环回地址,并不与宿主机共用。

  2. 端口映射 (Port Mapping)

    通过命令行参数 -p 或 --publish,Docker 可以将容器内的端口映射到宿主机端口。宿主机通过访问自己的端口,再由 Docker 转发到容器内服务所监听的端口。

  3. 绑定地址 (Binding Address)

    • 127.0.0.1 或 localhost:仅在容器内部有效,只能被容器自身访问。

    • 0.0.0.0:表示监听所有网络接口,既可被容器自身访问,也可借由端口映射被宿主机访问。


2. 为什么不能在容器中只绑定 localhost/127.0.0.1?

  1. 只监听容器内部接口

    当服务只监听 127.0.0.1 或 localhost 时,Docker 的端口映射机制无法将外部请求(来自宿主机)转发到容器内服务,因为它只侦听本地环回接口。

  2. 访问失败的典型场景

    例如,假设容器运行命令:

    docker run -p 8080:8080 my-app

    如果服务代码中只绑定到 localhost:8080,则在宿主机上访问 http://localhost:8080 会失败,因为外部请求无法穿透到容器内的环回地址。


3. 三种常见地址的区别

当我们在容器或宿主机环境下讨论访问地址时,常见会出现以下三种方式:

  1. 127.0.0.1 / localhost

    • 这两个都指向同一个环回地址(Loopback Interface),只能在当前机器(或当前容器)的网络命名空间内进行访问。容器内若只监听 127.0.0.1,则无法被宿主机访问。
  2. 0.0.0.0

    • 表示监听所有可用的网络接口。若容器内服务绑定到 0.0.0.0 并通过端口映射(如 -p 8080:8080)暴露端口,则宿主机可以使用 http://localhost:8080 或其他 IP 地址访问。
  3. 容器专用 IP(例如 172.17.0.x)

    • Docker 默认桥接网络下会给每个容器分配一个独立 IP,用于容器间通信或宿主机在特定网络配置下直接访问容器。但这个 IP 通常是动态分配,且需要正确的路由或端口映射才能从宿主机访问。

因此,若希望从宿主机访问容器中的服务,最常见做法就是在容器中绑定 0.0.0.0,配合 -p 参数完成端口映射,随后使用主机的 localhost(配合映射端口)即可访问。


4. 解决方案

  1. 在容器内服务绑定 0.0.0.0

    • 修改项目的配置,将 host 设置为 0.0.0.0,表示监听所有接口。

    • 通过 docker run -p 8080:8080 my-app 进行端口映射后,即可在宿主机上通过 http://localhost:8080 访问容器内服务。

  2. 使用 --network="host" 模式

    • 如果无法修改服务绑定地址,可在启动容器时使用 --network="host" 选项。此模式会让容器与宿主机共享网络栈。

    • 这样,即使容器内服务只绑定 127.0.0.1:8080,宿主机也能直接访问。

    • 但这会破坏容器的网络隔离,带来一定安全风险,一般不建议在生产环境使用。


5. Docker 默认桥接网络下的访问示例

  1. 主机访问容器

    通常只需在容器中将服务绑定到 0.0.0.0:9090,并使用 -p 9090:9090 或者 -p 9090:9090/udp(如果是 UDP 流量)映射端口。

    然后宿主机就可以使用 http://localhost:9090 或者主机 IP 来访问该容器内的服务。

  2. 容器显示的 Network 地址

    容器可能会显示 Network: http://172.17.0.X:9090 这样的内部地址,这是 Docker 默认桥接网络中分配给容器的 IP。

    这类 IP 可以用于容器间通信或调试,但并不一定稳定。宿主机通常更建议通过端口映射或自定义网络来访问容器。


6. 常见疑问解答

  1. 为什么另一个项目启动时,看到本地和网络两种地址?

    • 本地地址 (Local) 如 http://localhost:9090:对应端口映射后,宿主机通过 localhost 访问。

    • 网络地址 (Network) 如 http://172.17.0.5:9090:容器在默认桥接网络中的 IP,其他容器或宿主机(在特定设置下)可直接访问。

  2. 为什么容器只能用 0.0.0.0 才能被正常访问?

    • 使用 127.0.0.1 或 localhost 只监听容器内部的环回接口,端口映射不生效。

    • 使用 0.0.0.0 监听所有接口,端口映射才能正常将流量转发给服务。

  3. 如何固定容器地址?

    • 可以使用 Docker 自定义网络并指定固定 IP(不常用)。

    • 或者通过 Docker Compose、Kubernetes 等编排工具来使用服务名访问容器。


7. 总结

  • 关键点:在 Docker 容器中,127.0.0.1 和 localhost 指向容器内部的环回地址,只有 0.0.0.0 才能使宿主机端口映射生效。

  • 最佳实践:服务监听 0.0.0.0,配合 Docker 的端口映射,在宿主机侧使用 -p <宿主机端口>:<容器端口> 的方式即可访问。

  • 其他选择:若必须在容器内使用 localhost,可考虑 --network="host" 方式,但需注意其安全风险和网络冲突问题。

通过以上概念与配置参数的掌握,就能清晰地理解为什么容器内的服务默认无法用 localhost:端口 暴露给宿主机,以及如何正确让宿主机访问容器内的服务。

最后更新时间:
贡献者: 何风顺
上一页
Docker 使用 mysql