Гэтсби: переменные среды .env возвращают undefined

Я работаю над статическим веб-сайтом, используя Gatsby для разработки и Nginx для обслуживания статических файлов.

Я также использую Docker для развертывания для тестирования и производства и Traefik для маршрутизации трафика в контейнер докеров приложения.

У меня есть переменная среды, которую я определил в файле приложения, и эта переменная среды вызывается из файла .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;
  }
}

Я все еще не могу сказать, в чем причина проблемы, из-за которой приложение возвращает неопределенную ошибку при каждом вызове переменной среды. Мы будем очень благодарны за любую помощь.


person Promise Preston    schedule 03.07.2020    source источник


Ответы (1)


Я наконец понял это после нескольких часов отладки с моими коллегами.

Вот несколько вещей, которые я узнал:

Во-первых, по умолчанию Gatsby поддерживает 2 среды:

  1. Разработка. Если вы запустите gatsby develop, вы попадете в среду development.
  2. Производство. Если вы запустите gatsby build или gatsby serve, вы попадете в среду production.

Однако, если вы заметили, мы запускаем npm run build в нашем Dockerfile, что эквивалентно gatsby build, поэтому это сообщает приложению, что мы выполняем в production. окружающая обстановка.

Во-вторых, определение переменных среды для клиентского JavaScript

Для Project Env Vars, к которым вы хотите получить доступ в клиентском браузере JavaScript, вы можете определить файл конфигурации среды, .env.development и / или .env.production, в своей корневой папке. В зависимости от вашей активной среды будет найдена правильная среда, а ее значения встроены как переменные среды в JavaScript браузера.

Другими словами, нам нужно будет переименовать конфигурационный файл нашей среды с .env на .env.production, чтобы приложение Gatsby могло распознавать его в нашей production среде.

В-третьих, определение переменных среды с помощью префиксов

В дополнение к этим переменным среды проекта, определенным в .env.* файлах, вы также можете определить переменные окружения ОС. Варианты OS Env с префиксом GATSBY_ станут доступны в браузере JavaScript.

Если вы очень хорошо заметили, мы уже определяем это в нашем .env файле конфигурации как - GATSBY_API_URL=https://myapi.mywebsite.com, поэтому у нас нет проблем с этим.

В-четвертых, удаление env. файлы конфигурации из .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;
  }
}

Это все.

Надеюсь, это поможет

person Promise Preston    schedule 03.07.2020