我有一个简单的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)阅读关于这个主题的几篇文章,但不知道出了什么问题
请帮助!!
答案 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 }
}));
这解决了它。很多,非常感谢这个论坛,我能够迅速解决我的问题。你们真棒!