【问题标题】:Use enviroment variables in dockerized react app在 dockerized react app 中使用环境变量
【发布时间】:2021-02-05 10:56:37
【问题描述】:

我试图实现的目标是构建一个使用来自主机的环境变量的 docker 映像(其中包含一个 react 应用程序)。

计划的工作流程:

  1. 在本地构建 docker 镜像
  2. 上传 docker 镜像
  3. 调用命令docker-compose up

我希望系统的环境变量REACT_APP_SOME_ENV_VARIABLE(图像所在的位置)可供 React 应用使用。

目前的解决方案:

// App.js
function App() {
  return (
    <p>SOME_ENV_VARIABLE = {process.env.REACT_APP_SOME_ENV_VARIABLE}</p>
  );
}
# Dockerfile
FROM    node:13.12.0-alpine as build-step

# Install the app
RUN     mkdir /app
WORKDIR /app
COPY    package.json /app
RUN     npm install --silent

# Build the app
COPY    . /app
RUN     npm run-script build

# Create nginx server and copy build there
FROM    nginx:1.19-alpine
COPY    --from=build-step /app/build /usr/share/nginx/html

# docker-compose.yml
version: '3.5'

services:
  react-env:
    image:  react-env
    ports:
      - 80:80/tcp
    environment: 
      - REACT_APP_SOME_ENV_VARIABLE=FOO

我做错了什么,我该如何解决?

【问题讨论】:

  • 有什么问题?

标签: reactjs docker nginx docker-compose


【解决方案1】:

在您的方法中,环境变量在容器启动时注入,到那时您的应用程序已构建并创建 docker 映像,您也无法在客户端访问 process.env。因此,要在客户端访问它们,我们必须执行以下步骤。

你必须在你的 React 应用中使用 webpack 来打包和其他东西。

所以在你的 webpack.config.js 中,使用定义插件声明你的环境变量 REACT_APP_SOME_ENV_VARIABLE,这将导致将变量声明为应用程序的全局变量。

你的 webpack 配置应该如下所示:

const path = require("path");
const webpack = require("webpack");

module.exports = {
  target: "web",
  performance: {
    hints: false,
  },
  node: {
    fs: "empty"
  },
  entry: "./src/index.js",
  output: {
    path: path.join(__dirname, "/build"),
    filename: "[name].[contenthash].js"
  },
  
  module: {
    rules: [
      //your rules
    ]
  },

  plugins: [
    new webpack.DefinePlugin({
      "envVariable": JSON.stringify(process.env.REACT_APP_SOME_ENV_VARIABLE),
    }),
  ],
};

在你的应用中,你可以像这样使用变量

// App.js
function App() {
  return (
    <p>SOME_ENV_VARIABLE = {envVariable}</p>
  );
}

注意:确保在运行RUN npm run-script build 命令之前,将环境变量注入到 docker 容器中。 为此,您应该在RUN npm run-script build 步骤之前使用ENV 在DockerFile 中声明您的环境变量。

【讨论】:

  • 那么本地构建镜像,托管镜像,使用托管实例的环境变量的目标就落空了。
  • 查看您是否在 react App 的服务器端使用环境变量,然后您可以将这些变量传递给托管容器但如果您在客户端使用变量,那么我们必须按照上面的回答脚步。 @Hultan
【解决方案2】:

通过使用 NGINX docker 包解决了这个问题,将编译后的 React 生产代码注入 NGINX html 文件夹,然后修改 docker-entrypoint.sh 文件。

FROM nginx:1.19-alpine
COPY --from=build-step /app/build /usr/share/nginx/html
COPY ./docker/docker-entrypoint.sh /docker-entrypoint.sh

然后在该文件中在旧脚本的末尾添加以下代码

#!/bin/sh
#!/bin/sh
# vim:sw=4:ts=4:et

set -e

if [ -z "${NGINX_ENTRYPOINT_QUIET_LOGS:-}" ]; then
    exec 3>&1
else
    exec 3>/dev/null
fi

if [ "$1" = "nginx" -o "$1" = "nginx-debug" ]; then
    if /usr/bin/find "/docker-entrypoint.d/" -mindepth 1 -maxdepth 1 -type f -print -quit 2>/dev/null | read v; then
        echo >&3 "$0: /docker-entrypoint.d/ is not empty, will attempt to perform configuration"

        echo >&3 "$0: Looking for shell scripts in /docker-entrypoint.d/"
        find "/docker-entrypoint.d/" -follow -type f -print | sort -n | while read -r f; do
            case "$f" in
                *.sh)
                    if [ -x "$f" ]; then
                        echo >&3 "$0: Launching $f";
                        "$f"
                    else
                        # warn on shell scripts without exec bit
                        echo >&3 "$0: Ignoring $f, not executable";
                    fi
                    ;;
                *) echo >&3 "$0: Ignoring $f";;
            esac
        done

        echo >&3 "$0: Configuration complete; ready for start up"
    else
        echo >&3 "$0: No files found in /docker-entrypoint.d/, skipping configuration"
    fi
fi

# Set up endpoint for env retrieval
echo "window._env_ = {" > /usr/share/nginx/html/env_config.js

# Collect enviroment variables for react
eval enviroment_variables="$(env | grep REACT_APP.*=)"

# Loop over variables
env | grep REACT_APP.*= | while read -r line; 
do
    printf "%s',\n" $line | sed "s/=/:'/" >> /usr/share/nginx/html/env_config.js
    
    # Notify the user
    printf "Env variable %s' was injected into React App. \n" $line | sed "0,/=/{s//:'/}"

done

# End the object creation
echo "}" >> /usr/share/nginx/html/env_config.js

echo "Enviroment Variable Injection Complete."


exec "$@"

功能:

这将找到发送到运行前端的 docker 容器的所有环境变量,以提取所有以 REACT_APP 开头的变量并将它们添加到名为 env_config.js 的文件中。

您需要在 React 应用程序中加载该脚本文件,然后使用 window._env_.&lt;property&gt; 访问环境变量。

免责声明 使用此方法注入的环境变量对于使用该站点的任何人都是完全可读的。这不是敏感信息的安全方法。仅将其用于诸如“后端 api 端点在哪里”或其他可以轻松提取的非敏感信息。

【讨论】:

    猜你喜欢
    • 2019-01-15
    • 2022-06-18
    • 2019-06-02
    • 2020-11-26
    • 1970-01-01
    • 1970-01-01
    • 2018-10-16
    • 2017-10-27
    • 2021-10-27
    相关资源
    最近更新 更多