Docker swarm secret 在 node.js api (mongoDB) 中无法正常工作

Docker swarm secret not working correctly in node.js api (mongoDB)

我正在尝试将我的 mongo_username 和 mongo_password 放入 swarm secret 中,但由于某种原因它们被转换了?我在容器日志中收到此错误

/usr/src/app/node_modules/saslprep/index.js:99
    throw new Error(
    ^

Error: Prohibited character, see https://tools.ietf.org/html/rfc4013#section-2.3
    at saslprep (/usr/src/app/node_modules/saslprep/index.js:99:11)
    at continueScramConversation (/usr/src/app/node_modules/mongodb/lib/core/auth/scram.js:126:36)
    at /usr/src/app/node_modules/mongodb/lib/core/auth/scram.js:111:5
    at MessageStream.messageHandler (/usr/src/app/node_modules/mongodb/lib/cmap/connection.js:277:5)
    at MessageStream.emit (events.js:315:20)
    at processIncomingData (/usr/src/app/node_modules/mongodb/lib/cmap/message_stream.js:144:12)
    at MessageStream._write (/usr/src/app/node_modules/mongodb/lib/cmap/message_stream.js:42:5)
    at writeOrBuffer (_stream_writable.js:353:12)
    at MessageStream.Writable.write (_stream_writable.js:303:12)
    at Socket.ondata (_stream_readable.js:713:22)
    at Socket.emit (events.js:315:20)
    at addChunk (_stream_readable.js:302:12)
    at readableAddChunk (_stream_readable.js:278:9)
    at Socket.Readable.push (_stream_readable.js:217:10)
    at TCP.onStreamRead (internal/stream_base_commons.js:186:23)

我是这样添加的secret

echo admin | docker secret create mongo_username -
echo totallySecurePassword23456789 | docker secret create mongo_password -

当我像这样在我的数据库连接函数中记录这两个秘密时:

const mongoose = require("mongoose"); // For connection to DB

const {
  MONGO_USERNAME,
  MONGO_PASSWORD,
  MONGO_HOSTNAME,
  MONGO_PORT,
  MONGO_DATABASE_NAME,
} = process.env;

console.log(MONGO_USERNAME);
console.log(MONGO_PASSWORD);
console.log(MONGO_HOSTNAME);
console.log(MONGO_PORT);
console.log(MONGO_DATABASE_NAME);

const url = `mongodb://${MONGO_USERNAME}:${MONGO_PASSWORD}@${MONGO_HOSTNAME}:${MONGO_PORT}/${MONGO_DATABASE_NAME}?retryWrites=true$w=majority`;

console.log(url);

const connectDB = async () => {
  const conn = await mongoose.connect(url, {
    useNewUrlParser: true,
    useCreateIndex: true,
    useFindAndModify: false,
    useUnifiedTopology: true,
  });

  console.log(`MongoDB Connected: ${conn.connection.host}`.cyan.underline.bold);
};

module.exports = connectDB;

它们正确显示为:

admin
totallySecurePassword23456789
host.docker.internal
27020
mainDB

然而 url 应该看起来像 mongodb://admin:totallySecurePassword23456789@host.docker.internal:27020/mainDB?retryWrites=true$w=majority

显示为 @host.docker.internal:27020/mainDB?retryWrites=true$w=majority 这当然会使连接失败

主机名、端口和 database_name 工作正常,因为它们被定义为普通环境变量

非常感谢任何帮助,如果需要更多信息,请告诉我!

编辑 1: 这是我用来 运行 docker 堆栈的 docker-compose 文件:

version: "3.8"

services:
  main:
    image: main:5.0.0
    environment:
      - MONGO_USERNAME_FILE=/run/secrets/mongo_username
      - MONGO_PASSWORD_FILE=/run/secrets/mongo_password
      - MONGO_HOSTNAME=host.docker.internal
      - MONGO_PORT=27020
      - MONGO_DATABASE_NAME=mainDB
    secrets:
      - mongo_username
      - mongo_password
    networks:
      - main-net
    ports:
      - "80:3001"
    deploy:
      replicas: 1
      restart_policy:
        condition: on-failure
        delay: 10s
        window: 60s
networks:
  main-net:
    driver: overlay

secrets:
  mongo_username:
    external: true
  mongo_password:
    external: true

编辑 2: 修复了撰写文件缺少用户名和密码后面的 _FILE

经过大量调查后我发现我遇到了这个问题https://github.com/aspnet/Configuration/issues/701, with no good fix found i settled on editing the entrypoint i was using (https://github.com/BretFisher/node-docker-good-defaults/blob/main/docker-entrypoint.sh) 所以它在使用
将其设置为环境变量之前删除了行尾内容 export "$var"="${val//[$'\t\r\n ']}"

我假设你使用 gnu bash。如果您使用不带 -n 选项的 echo shell 内置函数,它会自动向提供的字符串添加新行。

试试这些:

echo -n admin | docker secret create mongo_username -
echo -n totallySecurePassword23456789 | docker secret create mongo_password -

如果你想检查你的秘密值是否包括新行,在你的docker cli所在的机器上执行以下命令:

docker container exec <your_container_name or id> cat -e /run/secrets/<your_secret_name>

如果此命令 returns 您的值后跟 $ 符号,那么我们可以得出结论,在您创建机密时附加了换行符。

注意:我假设您的容器是 linux 容器。此外,请确保您的容器处于 运行 状态,并且其 PATH 环境变量必须包含 cat 二进制文件所在的目录路径。