简体   繁体   English

无法使用 docker 容器连接到 MySQL 数据库

[英]Cannot connect to MySQL db using docker container

I wrote an application in Typescript which use Typeorm to interact with a MySQL database.我在Typescript中编写了一个应用程序,它使用TypeormMySQL数据库进行交互。 When I run the app using npm run dev which is a package.json script, the connection is working fine with these credentials:当我使用npm run dev运行应用程序时,这是一个package.json脚本,使用这些凭据连接工作正常:

"type": "mysql",
"host": "127.0.0.1",
"port": 3306,
"username": "root",
"password": "root",
"database": "mydb",

but when I launch my Docker container I get:但是当我启动我的Docker容器时,我得到:

> Error: connect ECONNREFUSED 127.0.0.1:3306
> errno: -111,
> code: 'ECONNREFUSED',
> syscall: 'connect',
> address: '127.0.0.1',
> port: 3306,
> fatal: true

I cannot figure out of this problem, I also tried to change 127.0.0.1 with localhost but same problem.我无法弄清楚这个问题,我也尝试用localhost更改127.0.0.1但同样的问题。 That's weird 'cause I'm using Dbeaver to connect with my LAMP which is a Docker container container too and I can establish the connection.这很奇怪,因为我正在使用Dbeaver连接我的LAMP ,它也是一个Docker容器容器,我可以建立连接。

Seems a problem related only with the containers connection, maybe the container of the app doesn't know the.network 127.0.0.1 ?似乎只与容器连接有关的问题,也许应用程序的容器不知道 .network 127.0.0.1

This is my image file:这是我的图像文件:

FROM node:stretch-slim

WORKDIR /myapp

COPY package.json ./
COPY ./dist ./dist

RUN npm install

EXPOSE 4000
ENV NODE_ENV development
ENV PORT 4000
ENV URL http://localhost:4000
ENV JWT_SECRET secret

CMD ["npm", "run", "start", "dev"]

and this is my docker-compose.yml :这是我的docker-compose.yml

version: '3'
services:
  app:
    container_name: myapp
    restart: always
    build: .
    ports:
      - '4000:4000'

for compile my containers I did: docker-compose up --build为了编译我的容器,我做了: docker-compose up --build

What is wrong?怎么了? As you can see from my lamp container each port is correctly exposed:正如您从我的lamp容器中看到的那样,每个端口都正确暴露:

在此处输入图像描述

The problem here is that each container use their own network, even though I exposed the mysql container on port 3306 I cannot access to mysql from the myapp container, because myapp container use another network.这里的问题是每个容器都使用自己的网络,即使我在端口3306上暴露了mysql容器,我也无法从myapp容器访问mysql ,因为myapp容器使用另一个网络。

So executing the following command: docker network ls I was able to list all the networks available, and then I did:所以执行以下命令: docker network ls我能够列出所有可用的网络,然后我做了:

docker network inspect bridge

which has returned the following gateway : 172.17.0.1它返回了以下gateway :172.17.0.1

The solution would be to replace localhost with 172.17.0.1 .解决方案是将localhost替换为172.17.0.1 But I don't like the following solution too much, so I rebuilded the myapp image adding previously network_mode inside the docker-compose.yml , so now I have:但是我不太喜欢下面的解决方案,所以我重建了myapp图像,在docker-compose.yml中添加了先前的network_mode ,所以现在我有了:

version: '3'
services:
  app:
    container_name: myapp
    restart: always
    build: .
    ports:
      - '4000:4000'
    network_mode: 'host'

as documentation says:正如文档所说:

If you use the host network mode for a container, that container's network stack is not isolated from the Docker host (the container shares the host's networking namespace), and the container does not get its own IP-address allocated.如果您为容器使用主机网络模式,则该容器的网络堆栈不会与 Docker 主机隔离(容器共享主机的网络命名空间),并且容器不会获得自己的 IP 地址分配。 For instance, if you run a container which binds to port 80 and you use host networking, the container's application is available on port 80 on the host's IP address.例如,如果您运行一个绑定到端口 80 的容器并使用主机网络,则该容器的应用程序在主机的 IP 地址上的端口 80 上可用。

I don't know if there is a better solution out there, I'm a Docker noob so far, so maybe someone more expert on this could propose a better solution to share a container network such as mysql , and then access to that shared network from others containers.我不知道是否有更好的解决方案,到目前为止我是一个Docker ,所以也许这方面的专家可以提出一个更好的解决方案来共享容器网络,例如mysql ,然后访问该共享来自其他容器的网络。

Another solution would be "host": "host.docker.internal"另一种解决方案是"host": "host.docker.internal"

docker-compose

docker-compose isn't limited to just one service, you can have the whole system, which, in your case, means the DB server, your app, and all the other things. docker-compose不仅限于一项服务,您可以拥有整个系统,在您的情况下,这意味着数据库服务器、您的应用程序和所有其他东西。

You can change your docker-compose.yml file to something like below (MySQL bit copied from https://hub.docker.com/_/mysql )您可以将docker-compose.yml文件更改为如下所示(从https://hub.docker.com/_/mysql复制的 MySQL 位)

version: '3'
services:

  db:
    image: mysql
    command: --default-authentication-plugin=mysql_native_password
    restart: always
    environment:
      MYSQL_ROOT_PASSWORD: example

  app:
    container_name: myapp
    restart: always
    build: .
    ports:
      - '4000:4000'

Networking联网

Because your containers are brought up in the same docker-compose , by default they have access to each other by hostname eg app , and db .因为您的容器是在同一个docker-compose中启动的,所以默认情况下,它们可以通过主机名(例如appdb )相互访问。 To try this out, bring them up, docker attach/exec to app , and try a ping db .要尝试这一点,请将它们启动, docker attach/exec to app ,然后尝试ping db

See https://stackoverflow.com/a/30173220/1148483https://stackoverflow.com/a/30173220/1148483

This means that in your app, you can use db as the DB host config.这意味着在您的应用程序中,您可以使用db作为数据库主机配置。

Instead of using localhost , let's replace it with host.docker.internal .我们不使用localhost ,而是将其替换为host.docker.internal This will allow you to connect with your local db这将允许您连接到本地数据库

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM