Docker can't connect to redis from another service
Asked Answered
T

7

19

I can't figure out how to connect to my redis service from my app service. Using DDocker version 18.03.1-ce, build 9ee9f40ocker for Mac.

I've tried connecting the various ways I've found on similar questions:

const client = redis.createClient({ host: 'localhost', port: 6379});

const client = redis.createClient({ host: 'redis', port: 6379});

const client = redis.createClient('redis://redis:6379');

const client = redis.createClient('redis', 6379); // and reversed args

I always get some form of:

Error: Redis connection to localhost:6379 failed - connect ECONNREFUSED 127.0.0.1:6379

Error: Redis connection to redis:6379 failed - connect ECONNREFUSED 172.20.0.2:6379

Docker containers

$ docker ps
CONTAINER ID        IMAGE                COMMAND                  CREATED              STATUS              PORTS                    NAMES
0fd798d58561        app_app         "pm2-runtime start e…"   2 seconds ago        Up 7 seconds                                 app
65d148e498f7        app_redis       "docker-entrypoint.s…"   About a minute ago   Up 8 seconds        0.0.0.0:6379->6379/tcp   redis

Redis works:

$ docker exec -it redis /bin/bash
root@65d148e498f7:/data# redis-cli ping
PONG

Redis Dockerfile (pretty simple)

FROM redis:4.0.9
COPY redis.conf /usr/local/etc/redis/redis.conf
CMD ["redis-server", "/usr/local/etc/redis/redis.conf"]

app Dockerfile

FROM node:10.3.0-slim
RUN mkdir -p /app
COPY src/* /app/
CMD ["pm2-runtime", "start", "/app/ecosystem.config.js"]

docker-compose.yml

version: "3"
services:
  redis:
    build: ./redis/
    container_name: redis
    restart: unless-stopped
    ports:
      - "6379:6379"
    expose:
      - "6379"
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
    environment:
      - 'API_PORT=6379'
      - 'NODE_ENV=production'
  app:
    depends_on:
      - redis
    build: ./app/
    container_name: app
    restart: unless-stopped
    volumes:
      - /var/run/docker.sock:/var/run/docker.sock
      - /app/node_modules
    environment:
      - 'NODE_ENV=production'
Tijuana answered 12/6, 2018 at 13:13 Comment(13)
Check your host 6379 port. Is anythings used that port ? sudo lsof -i tcp:6379Priorate
@TruongDang it shows no output. I originally used a different port but switched back to 6379 to debug. Both had the same error as noted above.Tijuana
Can you build your image and try replace build: ./redis/ to image: your_image_name_build_from_dockerfile ?Priorate
Seem your Redis not yet start... May you need to check your docker file, and redis configuration...Priorate
@Tijuana can you verify that docker ps lists the redis container?Result
can you share the redis config file?Result
In his case, there is nothing run on 6379 port, that mean there is some problem with his Redis. It can be start and map to host port 6739Priorate
So the error message is Redis connection to redis:6379 failed? Which ip address does it show? Is it the same as docker inspect redis shows?Result
@Result yes both show the same IP 172.20.0.2:6379Tijuana
Please include the error message that doesn't show it connecting to localhost or 127.0.0.1 since that won't work between containers.Fortyfive
Try a docker run --net container:app_app redis redis-cli -h redis pingFortyfive
@Fortyfive same error: Could not connect to Redis at redis:6379: Connection refused, when running docker run --net container:app redis redis-cli -h redis pingTijuana
And now what? Could not connect to Redis at redis:6379: Name or service not knownCurren
F
9

It looks like your redis image is configured to listen on 127.0.0.1 rather than all interfaces. This is not an issue with the default redis images, so either use the official image from docker hub, or correct your configuration to listen on 0.0.0.0.

You'll be able to verify this with netshoot:

docker run --rm --net container:app_redis nicolaka/netshoot netstat -ltn

In the redis conf, listening on all interface is done by commenting out the "bind" line in redis.conf.

Fortyfive answered 12/6, 2018 at 14:13 Comment(4)
Thanks, binding to 0.0.0.0 worked! Isn't FROM redis:4.0.9 a "default redis image"?Tijuana
That's based off of an official image, but it appears that you've extended that image with your own configuration.Fortyfive
@Fortyfive Got this problem as well, although I'm not using docker-compose.yml and just a docker run --name some-redis -p 6379:6379 -d redis command instead. The output from netstat: i.imgur.com/Coq403Q.png And I still can't connect to it via my node appMcelhaney
@Mcelhaney without a docker-compose.yml, your containers are not being started on the same user created network, so you won't have DNS and container to container networking. That's a different question.Fortyfive
P
11

Let me explain it in simple language. When you run docker-compose up it runs redis and app in separate containers. Now your app needs to connect/access the redis container (remember redis is not at your machines localhost, its inside a container and runs inside it at default port 6379). By default Docker will keep app container and redis container in same network and you can access a container by its service name (which in your case is redis and app) so in order to access redis from app container all you need is to use the default port 6379 and host will be the service name (in your case "redis").

For a node application running in a container get access to Redis (which was also running in a container) by

const redis = require("redis");
const client = redis.createClient(6379, "service-name-for-redis-container");
Pieplant answered 16/11, 2019 at 13:46 Comment(0)
F
9

It looks like your redis image is configured to listen on 127.0.0.1 rather than all interfaces. This is not an issue with the default redis images, so either use the official image from docker hub, or correct your configuration to listen on 0.0.0.0.

You'll be able to verify this with netshoot:

docker run --rm --net container:app_redis nicolaka/netshoot netstat -ltn

In the redis conf, listening on all interface is done by commenting out the "bind" line in redis.conf.

Fortyfive answered 12/6, 2018 at 14:13 Comment(4)
Thanks, binding to 0.0.0.0 worked! Isn't FROM redis:4.0.9 a "default redis image"?Tijuana
That's based off of an official image, but it appears that you've extended that image with your own configuration.Fortyfive
@Fortyfive Got this problem as well, although I'm not using docker-compose.yml and just a docker run --name some-redis -p 6379:6379 -d redis command instead. The output from netstat: i.imgur.com/Coq403Q.png And I still can't connect to it via my node appMcelhaney
@Mcelhaney without a docker-compose.yml, your containers are not being started on the same user created network, so you won't have DNS and container to container networking. That's a different question.Fortyfive
C
6

I solve this problem changing the redis host from 'localhost' to 'redis', exemple:

REDIS_HOST=redis

REDIS_PORT=6379

After the change my docker service started to comunicate with redis.

Original forum answer: https://forums.docker.com/t/connecting-redis-from-my-network-in-docker-net-core-application/92405

Cradling answered 1/5, 2021 at 20:58 Comment(0)
B
1

In my case the problem was that I was binding a different port on redis:

redis:
    image: redis
    ports:
        - 49155:6379

And I was trying to connect to port 49155 but I needed to connect through port 6379 since the connection is from another service.

Billhook answered 10/5, 2021 at 16:35 Comment(1)
You saved my life. My node app is from another service but I was trying to connect via 49155. But how can you know that? please tell me how? I was thought 49155 is a port that the reids container talking to the whole world?Unbounded
B
1

both @Hadi Mir and @Anderson Contreira's answer says the same thing and are correct as per my experience. upvote for that.

But i would like to give bit more clarity and detail for a beginner like me. If you are using docker compose and its in a network, other services can access the docker which is in a container using its container name. one approach is using connection string like

redis://[[username][:password]@][host][:port][/db-number]

so, if we are to give container name and lets assume port is 6379 its gonna be like

redis://yourUsername:yourPassword@yourRedisContainerName:6379
Basipetal answered 31/8, 2023 at 14:12 Comment(0)
R
0

localhost from the app container's perspective won't be able to leave the app container. So the best bet is to use redis or the host's ip address.

If you want to reach redis from the app container, you'll need to link them or put them into the same network. Please add a network property to both services, using the same network name. Docker will then provide you with with valid dns lookups for the service names.

See the official docs at https://docs.docker.com/compose/compose-file/#networks (for the service: property) and https://docs.docker.com/compose/compose-file/#network-configuration-reference (for the top-level networks property).

Result answered 12/6, 2018 at 13:33 Comment(4)
That not a problem, i usually use redis in my docker-compose. And it work like normal...Priorate
@TruongDang you're right - the relevant docs are docs.docker.com/compose/networkingResult
Then I'll follow your argument to check whether the Redis process has actually startedResult
@Result thanks I've added a network and still same error. Redis does start up, which I can see in the output.Tijuana
R
0

Try opening the docker log. I found this error in my own Redis docker log:

2023-06-15 04:44:14 1:M 14 Jun 2023 21:44:14.768 # Possible SECURITY ATTACK detected. It looks like somebody is sending POST or Host: commands to Redis. This is likely due to an attacker attempting to use Cross Protocol Scripting to compromise your Redis instance. Connection aborted.
Reaves answered 14/6, 2023 at 21:45 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.