Node.js 使用2个基本映像时,在Dockerfile中传递环境变量不起作用
简而言之,我想在docker中构建一个带有web项目的容器,该项目的配置可以根据稍后在docker中运行映像时传递给它的参数进行修改 此项目尝试读取具有自定义属性的文件调用“environment.json” 我的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
# 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参数值 建造 跑 ;太长,读不下去了 您的请求是在运行时指定配置,此问题有两种解决方案:
解决方案是将运行时可修改的所有内容放入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;'