2

I wrote an application in Typescript which use Typeorm to interact with a MySQL database. When I run the app using npm run dev which is a package.json script, the connection is working fine with these credentials:

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

but when I launch my Docker container I get:

> 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. 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.

Seems a problem related only with the containers connection, maybe the container of the app doesn't know the 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:

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

for compile my containers I did: docker-compose up --build

What is wrong? As you can see from my lamp container each port is correctly exposed:

enter image description here

Andrei Mustata
  • 1,013
  • 1
  • 9
  • 21
sfarzoso
  • 1,356
  • 2
  • 24
  • 65
  • `lamp_db_1` is the DB hostname, use that instead of localhost or 127.0.0.1 – abestrad Jul 05 '20 at 11:42
  • @abestrad if I do so I get: getaddrinfo ENOTFOUND lamp_db_1 – sfarzoso Jul 05 '20 at 11:44
  • Assuming they're in the same `docker-compose.yml` file (those container names suggest they are) the Compose service block name `db` will also work as a host name. `localhost` in Docker is almost always "this container" and not another container or the host. – David Maze Jul 05 '20 at 11:45
  • @DavidMaze mysql is running on another container – sfarzoso Jul 05 '20 at 12:34
  • @abestrad its working if I specify as `host: 172.17.0.1`, but it is possible share the network of mysql container? – sfarzoso Jul 05 '20 at 14:15
  • 1
    How are you declaring your networks in compose? By default it sets up a single network for your apps. Each service should join the default network and will be reachable by others on that network. and **discoverable** using the hostname (container name) – abestrad Jul 05 '20 at 14:34
  • @abestrad I didn't, could you suggest some useful resource for doing so? Or maybe could you write an answer to use mysql network from other container? Thanks – sfarzoso Jul 05 '20 at 14:35
  • 1
    [Networking in Compose](https://docs.docker.com/compose/networking/) is useful background material; it describes what setup Compose does for you automatically, and what host names will be reachable by default. – David Maze Jul 05 '20 at 15:38

3 Answers3

3

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.

So executing the following command: docker network ls I was able to list all the networks available, and then I did:

docker network inspect bridge

which has returned the following gateway: 172.17.0.1

The solution would be to replace localhost with 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:

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. 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.

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.

Another solution would be "host": "host.docker.internal"

sfarzoso
  • 1,356
  • 2
  • 24
  • 65
2

Instead of using localhost, let's replace it with host.docker.internal. This will allow you to connect with your local db

0

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.

You can change your docker-compose.yml file to something like below (MySQL bit copied from https://hub.docker.com/_/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 e.g. app, and db. To try this out, bring them up, docker attach/exec to app, and try a ping db.

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

This means that in your app, you can use db as the DB host config.

Andrei Mustata
  • 1,013
  • 1
  • 9
  • 21