docker nodejs容器无法连接mysql容器

Posted

技术标签:

【中文标题】docker nodejs容器无法连接mysql容器【英文标题】:docker nodejs container cant connect mysql container 【发布时间】:2017-08-10 06:43:40 【问题描述】:

我在 Digital Ocean 中运行 Docker 服务器。我有两个容器 Nodejs 和 mysql。 Mysql 容器开放了 3306 端口。

当尝试通过 Docker 服务器 ip + 端口通过 nodejs 访问 mysql 时。我收到错误:连接 ETIMEDOUT。

当我在本地计算机上运行相同的 nodejs docker setup 时,它工作正常。有什么我想念的吗?

这里是 nodejs docker-composer.yml:

version: '2'
services:
    test-web-install:
        image: example-nodejs:latest
        working_dir: /home/app
        volumes:
        - ./:/home/app
        command: sh -c 'nodemon'
        environment:
        - NODE_ENV=development
        - DB_HOST=192.168.11.207 #or public ip in internet
        - DB_PORT=3036
        - DB_PASSWORD=root
        - DB_USER=root
        - DB_DATABASE=root
        ports:
        - "3000:3000"

这里是 mysql 的 docker-composer.yml

mysql:
    container_name: flask_mysql
    restart: always
    image: mysql:5.6
    environment:
        MYSQL_ROOT_PASSWORD: 'root' # TODO: Change this
        MYSQL_USER: 'root'
        MYSQL_PASS: 'root'
        MYSQL_DATABASE: 'root'
    volumes:
    - ./data:/var/lib/mysql
    ports:
    - "3036:3306"
    restart: always

【问题讨论】:

您是否尝试在本地计算机上通过localhost:3306 访问mysql 容器?请提供更多信息 - docker files/docker-compose/outputs。到目前为止,我的建议是使用 docker-compose 并使用 docker-compose dns(即mysql:3306)从桥接网络中连接到 mysql 容器,前提是您的设置可以允许 db 仅对您的 node.js 服务器可用。 我也想通过 Sequal Pro 等 Mac 客户端访问数据库。我添加了那些设置文件。感谢您的帮助。 你试过通过域名连接吗?首先需要检查是否有任何监听以及是否有防火墙:sudo netstat -tulpensudo ufw status verbose。如果不是这篇文章可能会有所帮助:digitalocean.com/community/tutorials/… 看起来和docker网络设置有关。一些容器 ip 是 128.0.0.1 而不是主机 ip。是否可以使用主机ip? 我还在 docker 中将它们添加到同一个网络中。即使是 Curl 操作也不起作用。 【参考方案1】:

docker 网络不允许您从容器内部返回到主机 IP 以连接到另一个容器公开的端口。我还没有深入研究这是否是由于 iptables 规则或者可能是 docker-proxy 内部的某些东西。无论哪种方式,它都不值得研究,因为容器到容器网络是 docker 的内置功能。

要使用 docker 的网络,容器需要位于同一个 docker 网络上,并且您可以通过它们在 DNS 中的容器名称来引用它们。使用 docker-compose,通常您可以使用服务名称代替容器名称(例如示例中的 test-web-install 和 mysql),因为 compose 会为这些创建别名。但是,由于您已经覆盖了 mysql 的容器名称,因此请改用您的 flask_mysql 容器名称。

在您的场景中,由于您已将启动与两个单独的 docker-compose.yml 文件分开,因此您将位于由 compose 创建的单独网络上。您有两种选择来解决此问题:

    将两者合并成一个 docker-compose.yml (BlackStork gave an example of this)。 使用您预先创建的外部定义网络。

要执行后者,首先创建您的网络:

docker network create dbnet

然后更新您的 docker-compose.yml 以使应用看起来像:

version: '2'
networks:
    dbnet:
        external: true

services:
    test-web-install:
        image: example-nodejs:latest
        working_dir: /home/app
        volumes:
        - ./:/home/app
        command: sh -c 'nodemon'
        environment:
        - NODE_ENV=development
        - DB_HOST=flask_mysql
        - DB_PORT=3036
        - DB_PASSWORD=root
        - DB_USER=root
        - DB_DATABASE=root
        ports:
        - "3000:3000"
        networks:
        - dbnet

还有用于 mysql 的 docker-compose.yml:

version: '2'

networks:
  dbnet:
    external: true

services:

  mysql:
    container_name: flask_mysql
    restart: always
    image: mysql:5.6
    environment:
        MYSQL_ROOT_PASSWORD: 'root' # TODO: Change this
        MYSQL_USER: 'root'
        MYSQL_PASS: 'root'
        MYSQL_DATABASE: 'root'
    volumes:
    - ./data:/var/lib/mysql
    ports:
    - "3036:3306"
    restart: always
    networks:
    - dbnet

【讨论】:

【参考方案2】:

随着我们的进展,我会修改答案 - 跟随你的 cmets,虽然我无法访问你的环境,但让我们尝试逐步解决这个问题:

    让我们让 db 对 node.js 服务器可见 看看它是如何工作的,然后可能会深入了解 env 网络配置。

正如我所见,有两种方法可以解决第一个问题,也可能是第二个问题,但无法触及您的环境:

第一种方法将确保服务器可以看到数据库,但是如果您无法从外部连接到数据库,似乎存在防火墙/droplet 网络配置问题,您可以尝试第二种方法(不太可能改变,但最好尝试)。这假设您使用相同的 docker compose 和相同的桥接客户网络:

version: '2'
services:
    test-web-install:
        image: example-nodejs:latest
        working_dir: /home/app
        volumes:
        - ./:/home/app
        command: sh -c 'nodemon'
        environment:
        - NODE_ENV=development
        - DB_HOST= mysql 
        - DB_PORT=3036
        - DB_PASSWORD=root
        - DB_USER=root
        - DB_DATABASE=root
        ports:
        - "3000:3000"
    networks:
      inner:
        alias: server
  mysql:
    container_name: flask_mysql
    restart: always
    image: mysql:5.6
    environment:
        MYSQL_ROOT_PASSWORD: 'root' # TODO: Change this
        MYSQL_USER: 'root'
        MYSQL_PASS: 'root'
        MYSQL_DATABASE: 'root'
    volumes:
    - ./data:/var/lib/mysql
    ports:
    - "<externalEnvIp>:3036:3306"
    restart: always
    networks:
      inner:
        alias: mysql
networks:
  inner:
      driver: bridge
      driver_opts:
        com.docker.network.enable_ipv6: "true"
        com.docker.network.bridge.enable_ip_masquerade: "true"
      ipam:
        driver: default
        config:
        - subnet: 172.16.100.0/24
          gateway: 172.16.100.1

选项 2:

version: '2'
services:
    test-web-install:
        image: example-nodejs:latest
        working_dir: /home/app
        volumes:
        - ./:/home/app
        command: sh -c 'nodemon'
        environment:
        - NODE_ENV=development
        - DB_HOST= mysql 
        - DB_PORT=3036
        - DB_PASSWORD=root
        - DB_USER=root
        - DB_DATABASE=root
        ports:
        - "3000:3000"
        network_mode: "host"
  mysql:
    container_name: flask_mysql
    restart: always
    image: mysql:5.6
    environment:
        MYSQL_ROOT_PASSWORD: 'root' # TODO: Change this
        MYSQL_USER: 'root'
        MYSQL_PASS: 'root'
        MYSQL_DATABASE: 'root'
    volumes:
    - ./data:/var/lib/mysql
    ports:
    - "3036:3306"
    restart: always
    network_mode: "host"

更精确的解决方案(找出问题的根源)将涉及深入挖掘您的 env 网络配置、docker 网络设置等,但这些解决方案可能会帮助并暂时解决您的问题。

请尝试后请输出结果。

【讨论】:

解决方案 1 是我们案例的最佳解决方案!谢谢。

以上是关于docker nodejs容器无法连接mysql容器的主要内容,如果未能解决你的问题,请参考以下文章

如何将两个NodeJS docker容器连接在一起?

将 NodeJS Docker 容器连接到 MySQL Docker 容器 - docker-compose 3

无法从 Spring Boot Docker 容器连接 mysql Docker 容器

无法连接在 docker 容器上运行的 mysql 服务器

云原生之使用Docker部署mysql数据库

mysql docker容器 - 无法与Windows连接