如何使用远程配置 运行 Docker 和 node.js

How to run Docker and node.js with remote configurations

我想为开源应用程序提供一个简单易用的 Docker 容器,该应用程序将配置文件的 URL 作为参数并使用该文件。

Docker文件非常简单:

FROM phusion/baseimage
# Use baseimage-docker's init system.
CMD ["/sbin/my_init"]

RUN curl -sL https://deb.nodesource.com/setup_4.x | sudo -E bash -
RUN apt-get update
RUN apt-get install -y nodejs git
ADD     . /src
RUN     cd /src; npm install; npm update
ENV NODE_ENV production
CMD     ["/usr/bin/node", "/src/gitevents.js"]

我发现无法在容器运行时添加文件(使用 ADD 或 ENTRYPOINT),所以我试图在 node.js:

中解决这个问题
docker run -e "CONFIG_URL=https://gist.githubusercontent.com/PatrickHeneise/c97ba221495df0cd9a3b/raw/fda1b8cd53874735349c6310a6643e6fc589a404/gitevents_config.js" gitevents

这会将 CONFIG_URL 设置为我可以在节点中使用的环境变量。但是,我需要下载一个文件,它是异步的,这在当前设置中不起作用。

if (process.env.NODE_ENV === 'production') {
  var exists = fs.accessSync(path.join(__dirname, 'common', 'production.js'), fs.R_OK);
  if (exists) {
    config = require('./production');
  } else {
    // https download, but then `config` is undefined when running the app the first time.
  }
}

node.js 中没有同步下载,有什么解决办法的建议吗?

我很想 Docker 使用 ADDCMD 进行 curl 下载,但我不确定它是如何工作的?

我设法重写了我的配置脚本以异步工作,在我看来仍然不是最好的解决方案。

var config = {};
var https = require('https');
var fs = require('fs');
var path = require('path');

config.load = function(fn) {
  if (process.env.NODE_ENV === 'production') {
    fs.access(path.join(__dirname, 'production.js'), fs.R_OK, function(error, exists) {
      if (exists) {
        config = require('./production');
      } else {
        var file = fs.createWriteStream(path.join(__dirname, 'production.js'));
        var url = process.env.CONFIG_URL;

        if (!url) {
          process.exit(-1);
        } else {
          https.get(url, function(response) {
            response.pipe(file);
            file.on('finish', function() {
              file.close(function() {
                return fn(require('./production'));
              });
            });
          });
        }
      }
    });
  } else if (process.env.NODE_ENV === 'test') {
    return fn(require('./test'));
  } else {
    return fn(require('./development'));
  }
};

module.exports = exports = config;

ENTRYPOINT 和环境变量的组合怎么样?您可以将 Dockerfile 中的 ENTRYPOINT 设置为 shell 脚本,该脚本将下载环境变量中指定的配置文件,然后启动应用程序。 由于入口点脚本将接收 CMD 中的任何内容作为参数,因此应用程序启动步骤可以通过类似

的方式完成
# Execute CMD.
eval "$@"

另一件事是考虑您的 "config file" 不是文件而只是文本,并在 运行 时将内容传递给容器。

CONFIG="$(curl -sL https://gist.githubusercontent.com/PatrickHeneise/c97ba221495df0cd9a3b/raw/fda1b8cd53874735349c6310a6643e6fc589a404/gitevents_config.js)"

docker 运行 -e "CONFIG_URL=${CONFIG}" gitevents