Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/multithreading/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Node.js 使用2个基本映像时,在Dockerfile中传递环境变量不起作用_Node.js_Docker_Dockerfile - Fatal编程技术网

Node.js 使用2个基本映像时,在Dockerfile中传递环境变量不起作用

Node.js 使用2个基本映像时,在Dockerfile中传递环境变量不起作用,node.js,docker,dockerfile,Node.js,Docker,Dockerfile,简而言之,我想在docker中构建一个带有web项目的容器,该项目的配置可以根据稍后在docker中运行映像时传递给它的参数进行修改 此项目尝试读取具有自定义属性的文件调用“environment.json” 我的Dockerfile是: # NodeJS FROM node:13.12.0-alpine as build WORKDIR /app ENV PATH /app/node_modules/.bin:$PATH COPY dist /app/dist COPY define-e

简而言之,我想在docker中构建一个带有web项目的容器,该项目的配置可以根据稍后在docker中运行映像时传递给它的参数进行修改

此项目尝试读取具有自定义属性的文件调用“environment.json”

我的Dockerfile是:

# NodeJS
FROM node:13.12.0-alpine as build

WORKDIR /app

ENV PATH /app/node_modules/.bin:$PATH

COPY dist /app/dist
COPY define-env.js /app
COPY environments.json /app

# I have changed this with a lot of possible solutions 
# that I have found in Internet, I tried everything.
# ARG APP_ENV
# ENV ENVIRONMENT $APP_ENV
RUN node define-env.js ${APP_ENV}

# NGINX
FROM nginx:stable-alpine
COPY --from=build /app/dist /usr/share/nginx/html
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
我所做的是复制这两个:构建的基本web项目、负责编写正确环境的节点脚本和包含所有可能配置环境的JSON文件

节点脚本如下所示:

#!/usr/bin/env node

// we will need file system module to write the values
var fs = require("fs");
// this script is going to receive one parameter (see DockerFile)
var option = process.argv[2];
// taking all the possible configurations
var json = require("./environments.json");
// taking the chosen option (by default dev)
var environmentCfg = json[option] || json.dev;

// writing... It is important to do this task sync,
// because we need to be sure is finished before any step
fs.writeFileSync("./dist/environment.json", JSON.stringify(environmentCfg));
environments.json是这样的:

{
  "dev": {
    "title": "This is the dev environment",
    "anotherAttribute": "Hello dev, I was configured with Docker!"
  },
  "uat": {
    "title": "This is the uat environment",
    "anotherAttribute": "Hello uat, I was configured with Docker!"
  },
  "prod": {
    "title": "This is the prod environment",
    "anotherAttribute": "Hello prod, I was configured with Docker!"
  }
}
# I am taking a base image with NodeJS and Nginx
FROM hoosin/alpine-nginx-nodejs:latest
# Telling Docker I like to work in the app workdir
WORKDIR /app
# Copying all files I need
COPY dist /app/dist
COPY define-env.js /app
COPY environments.json /app

# My environment variable for runtime purposes (dev by devfault)
ENV APP_ENV dev

# Setup Nginx server
EXPOSE 80
CMD node define-env && mv ./dist/* /usr/share/nginx/html && nginx -g 'daemon off;'
我不知道在运行Docker映像时如何传递变量,我正在尝试以下操作:

docker build . -t docker-env
然后,创建映像后,我尝试使用以下命令运行它:

docker run -e APP_ENV=uat -it --rm -p 1337:80 docker-env
当我转到时,我总是看到“dev”配置

我已经检查过从DockerFile中删除NGINX配置,当我输入参数时,我可以看到它工作正常

我认为当我将baseImage从Node更改为Nginx时,会发生一些奇怪的事情(或者我不知道)

编辑:正如@babakabadkheir在评论中所建议的,我尝试了以下方法,但仍然失败:

FROM hoosin/alpine-nginx-nodejs:latest
WORKDIR /app

ENV PATH /app/node_modules/.bin:$PATH

COPY dist /app/dist
COPY define-env.js /app
COPY environments.json /app

RUN node define-env.js ${APP_ENV}
RUN mv ./dist/* /usr/share/nginx/html

EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
如果我看一看挂载的图像外壳,我可以看到它也放置了environment.json:

编辑2:

我已经像这样修改了Dockerfile,但它仍然不起作用:

# I am taking a base image with NodeJS and Nginx
FROM hoosin/alpine-nginx-nodejs:latest
# Telling Docker I like to work in the app workdir
WORKDIR /app
# Copying all files I need
COPY dist /app/dist
COPY define-env.js /app
COPY environments.json /app

# My environment variable for runtime purposes (dev by devfault)
ENV APP_ENV dev
# This instruction I think is failing, but when I swap it with
# CMD instead RUN and put a console.log works without troubles
RUN node define-env.js 

# Once I have all the files I move it to the Nginx workspace
RUN mv ./dist /usr/share/nginx/html

# Setup Nginx server
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
现在,我的节点脚本如下所示:

#!/usr/bin/env node

var fs = require("fs");
// NOTE: this line is already taken via environment 
var option = process.env.APP_ENV;

var json = require("./environments.json");
var environmentCfg = json[option] || json.dev;
fs.writeFileSync("./dist/environment.json", JSON.stringify(environmentCfg));
最后一次编辑! 终于有了

在CMD Docker说明中列出了我所有需要的解决方案:

CMD node define-env && mv ./dist/* /usr/share/nginx/html && nginx -g 'daemon off;'

您犯了两个错误:ENV与ARGS混合和语法错误

定义参数时,可以在生成图像时传递值,如果未指定,则使用默认值;然后读取Dockerfile上不带大括号的值: (注意:我使用了稍微不同的docker图像)

Dockerfile 现在,对于生成映像,必须指定APP_ENV参数值

建造 跑 ;太长,读不下去了 您的请求是在运行时指定配置,此问题有两种解决方案:

  • 运行容器时使用ENVvar

  • 构建容器时使用ARGS

  • 第一种解决方案有一个安全性的缺点,但其优点是分发一个映像:将整个文件从主机复制到容器,并在运行容器时传递正确的ENV值

    第二个解决方案稍微复杂一些,不存在安全问题,但必须为每个配置构建单独的映像

    第二个解决方案是已经编写好的答案,对于第一个解决方案,您必须在运行时简单地读取env变量

    Dockerfile 建造 跑 代码 工具书类



    解决方案是将运行时可修改的所有内容放入CMD指令中

    正如我所经历的,RUN只在构建时第一次起作用,而CMD不起作用

    因此,我在我的DockerFile中添加了:

    CMD node define-env && mv ./dist/* /usr/share/nginx/html && nginx -g 'daemon off;'
    
    我运行脚本,移动所有文件,然后为我的应用程序提供服务

    我希望能在这方面帮助其他开发者,因为这对我来说是一种痛苦

    TL;DR

    总之,Dockerfile应该是这样的:

    {
      "dev": {
        "title": "This is the dev environment",
        "anotherAttribute": "Hello dev, I was configured with Docker!"
      },
      "uat": {
        "title": "This is the uat environment",
        "anotherAttribute": "Hello uat, I was configured with Docker!"
      },
      "prod": {
        "title": "This is the prod environment",
        "anotherAttribute": "Hello prod, I was configured with Docker!"
      }
    }
    
    # I am taking a base image with NodeJS and Nginx
    FROM hoosin/alpine-nginx-nodejs:latest
    # Telling Docker I like to work in the app workdir
    WORKDIR /app
    # Copying all files I need
    COPY dist /app/dist
    COPY define-env.js /app
    COPY environments.json /app
    
    # My environment variable for runtime purposes (dev by devfault)
    ENV APP_ENV dev
    
    # Setup Nginx server
    EXPOSE 80
    CMD node define-env && mv ./dist/* /usr/share/nginx/html && nginx -g 'daemon off;'
    

    检查此项:谢谢@Bababadkheir,但这不是我要找的。您正在尝试在图像中创建动态环境,然后您希望基于环境运行图像?没错,但您传递给我的内容我认为与此无关@Bababadkheiruse一个图像仅nginx。在dockerfile中手动安装nodejs并运行env脚本。这可能会有所不同,但这不是必须的
    当您定义参数时,您必须在生成映像时传递值
    。您可以使用默认值。您是对的,我更新了答案。@Max我对您的答案投了更高的票,因为您很好地解释了ARG和ENV之间的差异,但您的解决方案不适合我(请看我开发的edit 2解决方案)
    
    docker build -t docker-generic .
    
    docker run -d -p 8888:80 -e APP_ENV=uat docker-generic
    
    # On your nodejs code you simply read the ENV value
    // ....
    var env = process.env.APP_ENV
    
    
    CMD node define-env && mv ./dist/* /usr/share/nginx/html && nginx -g 'daemon off;'
    
    # I am taking a base image with NodeJS and Nginx
    FROM hoosin/alpine-nginx-nodejs:latest
    # Telling Docker I like to work in the app workdir
    WORKDIR /app
    # Copying all files I need
    COPY dist /app/dist
    COPY define-env.js /app
    COPY environments.json /app
    
    # My environment variable for runtime purposes (dev by devfault)
    ENV APP_ENV dev
    
    # Setup Nginx server
    EXPOSE 80
    CMD node define-env && mv ./dist/* /usr/share/nginx/html && nginx -g 'daemon off;'