节点JS在docker上运行时会遇到未定义的会话,但在MAC上运行正常

时间:2016-05-02 21:48:40

标签: session express docker redis

我有一个简单的Node JS Web应用程序服务器,允许用户登录和发布/编辑一个简单的博客。我使用 Redis 作为我的会话商店,使用 CouchDB 作为我的数据库。我在MAC和MAC上运行所有内容(Node app,Redis,Couch DB)。使用我在MAC上运行的浏览器连接到它(https://localhost:3000或localhost:3001)。我可以登录,发布/编辑博客一切正常。

上周我尝试了对我的Node JS应用程序进行docker化。基本上,我的节点应用程序在docker容器上运行,但是我的redis和couchdb继续在主机上运行(即我的MAC)。我已经使用docker-machine对节点应用进行了dockerize。

Docker机器(Docker VM)具有IP: 192.168.99.101
我的MAC IP: 192.168.0.100

我将浏览器连接为( https://192.168.99.101:3000 192.168.99.101:3001 )&我看到了登录页面。然后我输入日志记录凭据。我的浏览器将页面发布到docker上的节点应用程序。节点应用程序从CouchDB(在MAC主机上运行)读取用户passwd并成功验证密码是否正确。但是,节点服务器无法从POST请求对象获取有效会话,因此无法保存会话。我在网上经历了很多关于这个主题的stackoverflow和其他文章,没有人帮助过。

我确保网络不是问题。即,我能够访问redis&来自docker shell的couchdb使用curl命令。

是否将我的浏览器连接到其他物理IP导致问题?我应该切换到域名吗?我想更好地了解这里发生了什么。感谢您的帮助。

初始化:

const express = require('express');
const bodyParser = require('body-parser');

var app = express();
const http = require('http');
const https = require('https');
const mustache = require('mustache');

var cookieParser = require('cookie-parser');
var session = require('express-session');
//var cookieSession = require('cookie-session');
const redis   = require("redis");
const redisStore = require('connect-redis')(session);
const redisClient  = redis.createClient();
:
:
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({extended: false}));
app.use(cookieParser());
app.use(
   session(
   {
    secret: REDIS_SECRET_KEY,
    // create new redis store.
    store: new redisStore({ host: REDIS_SERVER_HOST, port: REDIS_SERVER_PORT, client: redisClient,ttl :  260}),
    // REDIS_SERVER_HOST = 192.168.0.100, REDIS_SERVER_PORT=6379
    saveUninitialized: false,
    resave: false,
    cookie: { expires: false, maxAge: 30 * 24 * 60 * 60 * 1000 }
   }));

 :
 :
 // Logic to setup various routes

 app.get('/', function(req, res)
 {
    var userName = getUserName(req);
    if (userName != "")
      res.redirect('/home');
    else
      res.redirect('/login');
  });

  /** Login page. After login user is redirected to home page */
 app.get('/somepage', function(req, res)
 {
   :
 });
 :
 :

在docker上运行时,登录功能没有看到cookie或会话。它在我的MAC上运行时会看到所有内容。

function login(user, passwd, dbPasswd)
{
    if (dbPasswd == passwd)
    {
       // Store userID in REDIS session!
       if (postReq.cookies)
         console.log("Cookie:  -> ", postReq.cookies); // Cookie is empty when on docker, but is fine when run on my MAC
       postReq.session.key = userName; // BOMBS on docker, works fine when run on my MAC
       postResp.redirect("/home");
    }
    // Logic to handle login failure
}

在docker上运行时,我看到以下错误:

/usr/src/app/mysource.js:760
           postReq.session.key = userName;
                               ^

TypeError: Cannot set property 'key' of undefined
    at IncomingMessage.<anonymous> (/usr/src/app/mysource.js:760:26)
    at emitNone (events.js:72:20)
    at IncomingMessage.emit (events.js:166:7)
    at endReadableNT (_stream_readable.js:913:12)
    at nextTickCallbackWith2Args (node.js:442:9)
    at process._tickCallback (node.js:356:17)

我尽我所能验证了以下内容:
1)节点应用程序在我的MAC上正常运行 2)docker&amp; amp;之间没有网络问题。苹果电脑。我可以从docker shell访问redis,couchDB 3)package.json&amp; MAC和MAC之间的节点模块是相同的。码头工人环境
4)阅读关于这个主题的几篇文章,但不知道出了什么问题

请帮助!!

1 个答案:

答案 0 :(得分:3)

Atlast,我发现了我的代码问题。非常感谢rudeamanuel为redisClient添加事件监听器的非常有用的提示。

当我添加事件监听器时,我的节点应用程序的docker部署继续使用redis吐出连接错误,如下所示:

UNABLE to establish connection with Redis
{ [Error: Redis connection to 127.0.0.1:6379 failed - connect ECONNREFUSED 127.0.0.1:6379]
  code: 'ECONNREFUSED',
  errno: 'ECONNREFUSED',
  syscall: 'connect',
  address: '127.0.0.1',
  port: 6379 }

回想一下,我已经初始化了我的快速会话,如下所示,所以尽管我指定了正确的redis主机,但我还在为什么它会继续连接到localhost。

const redisClient  = redis.createClient();
:
:
app.use(
   session(
   {
    secret: REDIS_SECRET_KEY,
    // create new redis store.
    store: new redisStore({ host: REDIS_SERVER_HOST, port: REDIS_SERVER_PORT, client: redisClient,ttl :  260}),
    // REDIS_SERVER_HOST = 192.168.0.100, REDIS_SERVER_PORT=6379
    saveUninitialized: false,
    resave: false,
    cookie: { expires: false, maxAge: 30 * 24 * 60 * 60 * 1000 }
   }));

以下陈述似乎是问题所在:

new redisStore({ host: REDIS_SERVER_HOST, port: REDIS_SERVER_PORT, client: redisClient,ttl :  260})

当我初始化redisClient时,看起来客户端默认为localhost和6379,随后当我用客户端和主机端口信息初始化redisStore时,redisStore对象忽略主机/端口并获取客户端对象的参数。所以为了解决这个问题,我做了以下几点:

redisClient  = redis.createClient(REDIS_SERVER_PORT, REDIS_SERVER_HOST);
:
:

 app.use(session(
       {
        secret: REDIS_SECRET_KEY,
        // create new redis store.
        store: new redisStore({client: redisClient, ttl:  260}),
        saveUninitialized: false,
        resave: false,
        cookie: { expires: false, maxAge: 30 * 24 * 60 * 60 * 1000 }
       }));

这解决了它。很多,非常感谢这个论坛,我能够迅速解决我的问题。你们真棒!