【问题标题】:Database connection from php container with host name "localhost" instead of container name来自主机名“localhost”而不是容器名的php容器的数据库连接
【发布时间】:2019-11-21 14:02:12
【问题描述】:

我们的网站框架设计用于 xampp 和 docker 环境。我们通过主机名/IP 地址(dev、test、staging、live env)识别我们的数据库主机。使用 xampp 的人使用的是https://localhost,因此他们获得了名为Development 的环境变量。使用 docker 的人使用https://docker 作为他们的主机。他们得到名为Development/Docker 的环境变量。我们需要这种差异化,因为在 php 应用程序中,我们的 xampp 用户使用主机 localhost 连接到他们的 mysql 服务。 Docker 用户必须通过名为 mysql 的主机进行连接(这是 mysql-service 的容器名称)。

由于最近发生的问题(此处不相关),我们希望为两个用户组在数据库连接方面提供独特的解决方案:Docker 用户应该能够使用主机localhost 连接到他们的 mysql 服务。

docker-compose.yaml(为了更好的概览而缩短):

version: '2'
services:
  #######################################
  # PHP application Docker container
  #######################################
  app:
    build:
      context: .
      dockerfile: Dockerfile.development
    links:
      - mail
      - mysql
      - redis
    ports:
      - "80:80"
      - "443:443"
      - "10022:22"
      - "3307:3306"
    volumes:
      - ./app/:/app/
      - ./:/docker/
    cap_add:
      - SYS_PTRACE
    env_file:
      - etc/environment.yml
      - etc/environment.development.yml
    environment:
      - POSTFIX_RELAYHOST=[mail]:1025

  #######################################
  # MySQL server
  #######################################
  mysql:
    build:
      context: docker/mysql/
      dockerfile: MariaDB-10.Dockerfile
    ports:
      - "3306"
    volumes:
      - mysql:/var/lib/mysql
    env_file:
      - etc/environment.yml
      - etc/environment.development.yml

  #######################################
  # phpMyAdmin
  #######################################
  # /// #

  #######################################
  # Mail
  #######################################
  # /// #

  #######################################
  # Redis
  #######################################
  # /// #

# Volumes
volumes:
  mysql:
  phpmyadmin:
  redis:

我尝试了很多并使用 docker-compose,但几周都没有找到解决方案。尝试使用链接、网络等。我想我的 docker 技能现在已经用尽了......

我也加了mysql.conf

bind-address = 0.0.0.0

有什么想法吗?

【问题讨论】:

  • 假设您能够以localhost 的身份访问mysql 服务,那么您将如何访问app 呢?所以一种在你当前的 docker 镜像中安装 mysql 的方法。
  • 您不能使用localhost 作为主机名的任意占位符。在 Docker 上下文中,它几乎总是意味着“这个容器”,仅此而已。与配置远程 SMTP 服务器的方式相同,您应该为数据库服务器的位置添加配置。 (想象一下使用像 Amazon 的 RDS 这样的托管数据库解决方案:在那种环境中,您永远不会期望数据库主机名是 localhost,您需要一些方法来配置它。)
  • app 侦听端口80/443,可以通过浏览器通过127.0.0.1(或在主机文件中注册的任何其他域)访问。我也有同样的想法,唯一合乎逻辑的结论是可以通过端口3306和主机“localhost”访问mysql服务。但根据我的研究,两者都是封装服务,只能通过容器名称相互通信。这能回答你的问题吗?

标签: php mysql docker


【解决方案1】:

这是因为docker的网络结构。

docker 创建 3 个基本接口。 docker0hostnone

每个容器默认使用 docker0。那么每个容器都会有一个虚拟网络接口用于容器之间的通信。这样您就可以将您的数据库与mysql 地址一起使用。

如果你想连接到地址为localhost的数据库,你应该配置docker使用host网络模式(你可以通过在docker compose文件中添加一行来定义你的应用服务)。它将能够连接到您系统上运行的每个应用程序。顺便说一句,你会通过他们的名字与其他容器失去联系。也许你失去了与你的 redis 的连接(与redis 地址连接)

在这种网络模式下,每个依赖项都应该被部署或暴露给你的本地主机。

【讨论】:

  • 你是说这个docs.docker.com/compose/networking吗?
  • 我的意思是将network_mode: host 添加到您的 docker compose 应用服务中
  • 我在 webserver 和 mysql-server 的 build 上下文中添加了 network_mode: hostnetwork: host。运行 docker ps 时这些服务列表没有 IP(对我来说似乎是正确的)。通过在 webserver 容器中键入 hostname -i 检查 IP - 尝试在浏览器中打开此 IP 并通过控制台 ping,但没有得到响应...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2023-04-07
  • 2019-06-11
  • 1970-01-01
  • 1970-01-01
  • 2017-01-28
  • 2016-03-13
相关资源
最近更新 更多