【问题标题】:How to connect app container to Redis container with docker compose如何使用 docker compose 将应用程序容器连接到 Redis 容器
【发布时间】:2022-11-05 17:02:53
【问题描述】:

我正在尝试设置两个 socket.io nodejs 服务器,并且都连接到 Redis 以进行它们之间的通信,所有这些都在 Docker 内部。

我不断收到错误,我认为它与以下内容有关:

const { createClient } = require("redis");
const { createAdapter } = require("@socket.io/redis-adapter");

const pubClient = createClient({ host: "redis", port: 6379 }); // <- this host
const subClient = pubClient.duplicate();

我尝试了很多解决方案,但都不适合我,我是 docker 新手。

我的文件:

Dockerfile:

FROM node:16.8
WORKDIR /home/node/app
COPY app /home/node/app/
RUN npm install
CMD npm run app 
EXPOSE 9999 6379

index.js:

const express = require("express");
const app = express();
const server = require("http").createServer(app);
const bodyParser = require("body-parser");
const appid = process.env.APPID;

app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
const cors = require("cors");
app.use(cors());
app.use(express.json({ limit: "8mb" }));


const { createClient } = require("redis");
const { createAdapter } = require("@socket.io/redis-adapter");

const pubClient = createClient({ host: "redis", port: 6379 });
const subClient = pubClient.duplicate();

const io = require("socket.io")(server, {
  cors: {
    origin: "*",
    methods: ["GET", "POST"],
  },
});

Promise.all([pubClient.connect(), subClient.connect()]).then(() => {
  io.adapter(createAdapter(pubClient, subClient));
});

var allUsers = {};

app.get("/", async (req, res) => {
  res.send(`Hello from server ${appid}`);
});

io.on("connection", (socket) => {
  console.log("User connected: " + socket.id);
  socket.emit("port", appid);

  socket.on("message", (message) => {
    socket.broadcast.emit("new-message", message);
  });

  socket.on("disconnecting", (socket) => {
    console.log("User disconnected: ", socket.id);
  });
});

server.listen(appid, () => console.log(`Server running on port ${appid}`));

haproxy.cfg:

defaults
  mode http
  timeout client          35s
  timeout connect          5s
  timeout server          35s
  timeout tunnel         120s
  timeout http-keep-alive  1s
  timeout http-request    15s
  timeout queue           30s
  timeout tarpit          60s
  timeout http-request   10s

frontend http
    bind *:8080
    timeout client 10s
    use_backend all

backend all
    server s1 nodeapp1:1111
    server s2 nodeapp2:2222

码头工人-compose.yml

version : '3'

services:
    redis:
        image: redis
        ports:
            - "6379:6379"
    lb:
        image: haproxy
        ports:
            - "8080:8080"
        volumes:
            - ./haproxy:/usr/local/etc/haproxy
    nodeapp1:
        image: nodeapp
        environment:
            - APPID=1111
        depends_on:
            - redis lb
    nodeapp2:
        image: nodeapp
        environment:
            - APPID=2222
        depends_on:
            - redis lb

这是我得到的错误,我不太明白,我对错误代码进行了很多搜索,但遗憾的是我没有找到解决方案。

docker-redis-1     | 1:M 13 Apr 2022 03:31:07.857 * Ready to accept connections
docker-nodeapp2-1  | 
docker-nodeapp2-1  | > test-server-for-expo@1.0.0 app
docker-nodeapp2-1  | > node index.js
docker-nodeapp2-1  |
docker-nodeapp1-1  | 
docker-nodeapp1-1  | > test-server-for-expo@1.0.0 app
docker-nodeapp1-1  | > node index.js
docker-nodeapp1-1  |
docker-nodeapp2-1  | Server running on port 2222
docker-nodeapp2-1  | node:internal/process/promises:246
docker-nodeapp2-1  |           triggerUncaughtException(err, true /* fromPromise */);
docker-nodeapp2-1  |           ^
docker-nodeapp2-1  |
docker-nodeapp2-1  | Error: connect ECONNREFUSED 127.0.0.1:6379
docker-nodeapp2-1  |     at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1146:16)
docker-nodeapp2-1  | Emitted 'error' event on Commander instance at:
docker-nodeapp2-1  |     at RedisSocket.<anonymous> (/home/node/app/node_modules/@node-redis/client/dist/lib/client/index.js:339:14)
docker-nodeapp2-1  |     at RedisSocket.emit (node:events:394:28)
docker-nodeapp2-1  |     at RedisSocket._RedisSocket_connect (/home/node/app/node_modules/@node-redis/client/dist/lib/client/socket.js:117:14)
docker-nodeapp2-1  |     at processTicksAndRejections (node:internal/process/task_queues:96:5)       
docker-nodeapp2-1  |     at async Commander.connect (/home/node/app/node_modules/@node-redis/client/dist/lib/client/index.js:162:9)
docker-nodeapp2-1  |     at async Promise.all (index 0) {
docker-nodeapp2-1  |   errno: -111,
docker-nodeapp2-1  |   code: 'ECONNREFUSED',
docker-nodeapp2-1  |   syscall: 'connect',
docker-nodeapp2-1  |   address: '127.0.0.1',
docker-nodeapp2-1  |   port: 6379
docker-nodeapp2-1  | }
docker-nodeapp1-1  | Server running on port 1111
docker-lb-1        | [NOTICE]   (1) : New worker (9) forked
docker-lb-1        | [NOTICE]   (1) : Loading success.
docker-nodeapp1-1  | node:internal/process/promises:246
docker-nodeapp1-1  |           triggerUncaughtException(err, true /* fromPromise */);
docker-nodeapp1-1  |           ^
docker-nodeapp1-1  |
docker-nodeapp1-1  | Error: connect ECONNREFUSED 127.0.0.1:6379
docker-nodeapp1-1  |     at TCPConnectWrap.afterConnect [as oncomplete] (node:net:1146:16)
docker-nodeapp1-1  | Emitted 'error' event on Commander instance at:
docker-nodeapp1-1  |     at RedisSocket.<anonymous> (/home/node/app/node_modules/@node-redis/client/dist/lib/client/index.js:339:14)
docker-nodeapp1-1  |     at RedisSocket.emit (node:events:394:28)
docker-nodeapp1-1  |     at RedisSocket._RedisSocket_connect (/home/node/app/node_modules/@node-redis/client/dist/lib/client/socket.js:117:14)
docker-nodeapp1-1  |     at processTicksAndRejections (node:internal/process/task_queues:96:5)       
docker-nodeapp1-1  |     at async Commander.connect (/home/node/app/node_modules/@node-redis/client/dist/lib/client/index.js:162:9)
docker-nodeapp1-1  |     at async Promise.all (index 0) {
docker-nodeapp1-1  |   errno: -111,
docker-nodeapp1-1  |   code: 'ECONNREFUSED',
docker-nodeapp1-1  |   syscall: 'connect',
docker-nodeapp1-1  |   address: '127.0.0.1',
docker-nodeapp1-1  |   port: 6379
docker-nodeapp1-1  | }
docker-nodeapp2-1 exited with code 1
docker-nodeapp1-1 exited with code 1

我希望有人可以帮助我解决这个问题。 先感谢您。

【问题讨论】:

  • redis 主机名看起来是对的,但似乎没有效果;应用程序容器改为连接到 127.0.0.1(localhost,即应用程序容器本身)。 createClient() 调用的语法是否正确?

标签: node.js docker docker-compose redis socket.io


【解决方案1】:

depends_on 获取当前服务所依赖的服务数组

  • 您将“redis lb”声明为单个服务 尝试这个 :
nodeapp2:
        image: nodeapp
        environment:
            - APPID=2222
        depends_on:
            - redis
            - lb
        restart: always

现在您可以通过它的服务名称作为应用程序代码中的主机名连接到 redis

【讨论】:

  • 我刚刚尝试了你的修复,我仍然得到同样的错误,你的答案。
  • 这在语法上是正确的,但从技术上讲,您不需要 depends_on: 从一个容器连接到另一个容器。
【解决方案2】:

办公文档说https://docs.docker.com/compose/compose-file/compose-file-v3/#depends_on

在启动 web 之前,depends_on 不会等待 db 和 redis “准备好” - 仅在它们启动之前

redis 容器已启动,但尚未准备好连接。

最简单的方法是你可以继续尝试,直到它准备好。

let pubClient;
const pubClient = connectRedis();

function connectRedis() {
  try {
    return createClient({ host: "redis", port: 6379 });
  } catch {
    return connectRedis();
  }
}

【讨论】:

  • 也没有用:(
【解决方案3】:

我面临同样的问题。 我有和你类似的配置

const pubClient = createClient({ host: "redis", port: 6379 });

我有一个远程主机, 但在日志中我看到 pubClient 尝试连接到 localhost。

我将此配置更改为

const pubClient = createClient({url: process.env.REDIS_ENDPOINT});

url 的格式为 redis://{host}:{port}。更详细的可以看官网。

它开始运作良好。

【讨论】:

    猜你喜欢
    • 2017-07-11
    • 2020-12-23
    • 2021-10-31
    • 2016-07-14
    • 2019-07-30
    • 1970-01-01
    • 2021-10-25
    • 1970-01-01
    相关资源
    最近更新 更多