我正在使用 Gatsby 进行开发并使用 Nginx 来提供静态文件的静态网站上。
我还使用 Docker 进行部署以测试和生产,并使用 Traefik 将流量路由到应用程序的Docker容器。
我在应用程序文件中定义了一个环境变量,并且该环境变量是从应用程序的根文件夹中的.env
文件中调用的。
但是,当在应用程序中调用该环境变量时,它将引发错误:
未定义
这是代码:
Dockerfile
# Set base image
FROM node:latest AS builder
# Set working directory
WORKDIR /app
# Copy package.json and install packages
COPY package.json .
RUN npm install
# Copy other project files and build
COPY . ./
RUN npm run build
# Set nginx image
FROM nginx:latest
# Nginx config
RUN rm -rf /etc/nginx/conf.d/default.conf
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
# Static build
COPY --from=builder /app/public /usr/share/nginx/html
# Set working directory
WORKDIR /usr/share/nginx/html
# Start Nginx server
CMD ["/bin/bash", "-c", "nginx -g \"daemon off;\""]
.env
GATSBY_API_URL=https://myapi.mywebsite.com
docker-compose.yml
version: "3"
services:
web:
image: my-website
build:
context: .
dockerfile: Dockerfile
environment:
GATSBY_API_URL: ${GATSBY_API_URL}
expose:
- "80"
labels:
- traefik.enable=true
- traefik.http.routers.my-website.rule=Host(`my-website.com`)
restart: always
volumes:
- .:/app
networks:
default:
external:
name: traefik-proxy
index.js
const onSubmit = async (values) => {
try {
const res = await axios.post(`${process.env.GATSBY_API_URL}/api/EmployeeDetail/verify`, values)
// console.log(res, 'verify endpoint');
if( res.data.requestSuccessful === true ) {
dispatchVerifyData({
type : 'UPDATE_VERIFY_DATA',
verifyData: {
res: res.data.responseData,
loanType: values.loanType
}
})
handleNext()
} else {
setIsSuccessful({
status: false,
message: res.data.message
})
}
} catch (error) {
//error state Unsuccessful
console.log(error, 'error')
setIsSuccessful({
status: false,
})
}
}
.dockerignore
node_modules
npm-debug.log
.DS_Store
.bin
.git
.gitignore
.bundleignore
.bundle
.byebug_history
.rspec
tmp
log
test
config/deploy
public/packs
public/packs-test
yarn-error.log
coverage/
.env
.env.production
Nginx default.conf
server {
listen 80;
add_header Cache-Control no-cache;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
expires -1;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
我似乎仍然无法分辨出什么原因导致了每次调用环境变量时导致应用程序返回 undefined error 的问题。任何形式的帮助将不胜感激。
答案 0 :(得分:2)
经过与同事长时间的调试,我终于找到了答案。
这是我学到的一些东西:
首先,默认情况下,盖茨比支持2种环境:
gatsby develop
,那么您将处于development
环境中。gatsby build
或gatsby serve
,那么您将处于production
环境中。但是,如果您注意到,我们正在npm run build
中运行Dockerfile
,相当于gatsby build
,因此这通知应用程序我们正在production
中运行。环境。
其次,为客户端JavaScript定义环境变量
对于要在客户端浏览器JavaScript中访问的Project Env Vars,可以在根文件夹中定义环境配置文件.env.development
和/或.env.production
。根据您的活动环境,将找到正确的环境并将其值作为环境变量嵌入到浏览器JavaScript中。
换句话说,我们需要将环境配置文件从.env
重命名为.env.production
,以使Gatsby应用程序可以在我们的production
环境中识别它。
第三,使用前缀定义环境变量
除了.env.*
文件中定义的这些项目环境变量之外,您还可以定义OS Env Vars。带有GATSBY_
前缀的OS Env Vars将在浏览器JavaScript中可用。
如果您记得很好,我们已经在.env
配置文件中将其定义为-GATSBY_API_URL=https://myapi.mywebsite.com
,因此我们对此没有任何疑问。
第四,删除环境。 .dockerignore
中的配置文件如果我们清楚地观察到环境变量的值是如何嵌入到客户端JavaScript的浏览器Javascript中的,您将看到它是在构建时而不是运行时完成的。
因此,我们需要从.env.*
删除.dockerignore
配置文件,还需要删除environment
文件中的docker-compose.yml
选项,因为我们不再需要它了在运行时不会嵌入环境变量的值。
所以我们的代码现在看起来像这样:
Dockerfile
# Set base image
FROM node:latest AS builder
# Set working directory
WORKDIR /app
# Copy package.json and install packages
COPY package.json .
RUN npm install
# Copy other project files and build
COPY . ./
RUN npm run build
# Set nginx image
FROM nginx:latest
# Nginx config
RUN rm -rf /etc/nginx/conf.d/default.conf
COPY ./nginx/default.conf /etc/nginx/conf.d/default.conf
# Static build
COPY --from=builder /app/public /usr/share/nginx/html
# Set working directory
WORKDIR /usr/share/nginx/html
# Start Nginx server
CMD ["/bin/bash", "-c", "nginx -g \"daemon off;\""]
.env.production
GATSBY_API_URL=https://myapi.mywebsite.com
docker-compose.yml
version: "3"
services:
web:
image: my-website
build:
context: .
dockerfile: Dockerfile
expose:
- "80"
labels:
- traefik.enable=true
- traefik.http.routers.my-website.rule=Host(`my-website.com`)
restart: always
volumes:
- .:/app
networks:
default:
external:
name: traefik-proxy
index.js
const onSubmit = async (values) => {
try {
const res = await axios.post(`${process.env.GATSBY_API_URL}/api/EmployeeDetail/verify`, values)
// console.log(res, 'verify endpoint');
if( res.data.requestSuccessful === true ) {
dispatchVerifyData({
type : 'UPDATE_VERIFY_DATA',
verifyData: {
res: res.data.responseData,
loanType: values.loanType
}
})
handleNext()
} else {
setIsSuccessful({
status: false,
message: res.data.message
})
}
} catch (error) {
//error state Unsuccessful
console.log(error, 'error')
setIsSuccessful({
status: false,
})
}
}
.dockerignore
node_modules
npm-debug.log
.DS_Store
.bin
.git
.gitignore
.bundleignore
.bundle
.byebug_history
.rspec
tmp
log
test
config/deploy
public/packs
public/packs-test
yarn-error.log
coverage/
Nginx default.conf
server {
listen 80;
add_header Cache-Control no-cache;
location / {
root /usr/share/nginx/html;
index index.html index.htm;
try_files $uri $uri/ /index.html;
expires -1;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /usr/share/nginx/html;
}
}
仅此而已。
我希望这会有所帮助