如何使单个 React Docker 构建/映像在所有环境中运行?

IT技术 reactjs docker continuous-integration environment-variables
2021-05-04 19:59:34

我正在尝试在单个 Docker 容器中部署 React 应用程序,该容器能够在 OpenShift 平台上通过 dev、preprod 和 prod 运行,在该平台上我只能推送标记的 docker 镜像。为了做到这一点,我有:

  • 使用托管在 Github 上的 create-react-app 生成的 React 应用程序
  • 项目根目录下的 Dockerfile 包含 docker build/run 过程
  • 包含持续集成检查和部署方法的 .gitlab-ci.yml 文件
  • 一个可访问的 OpenShift 平台

我可以做什么:

我可以很容易地生成一个生产构建“/build”,它将被添加到 docker 镜像构建阶段,并将在生产上下文中运行,或者我可以在运行开始时构建(但只是编写它感觉很糟糕)。

问题:

这个生成的图像不能在所有环境中运行,我不想为每个环境都有一个特定的构建。

我想要的是:

我希望能够生成一个可以在所有环境中运行的 docker 镜像,而无需安装依赖项或在只需要 RUN 时构建。

这是我的 Dockerfile:

FROM nginx:1.15.5-alpine
RUN addgroup --system app \
    && adduser --uid 1001 --system --ingroup app app \
    && rm -rf /etc/nginx/conf.d/default.conf \
    && apk add --update nodejs nodejs-npm \
    && mkdir /apptmp
COPY . /apptmp
RUN chmod 777 /apptmp
COPY config/default.conf /etc/nginx/conf.d/
COPY config/buildWithEnv.sh .

RUN touch /var/run/nginx.pid && \
  chown -R app:app /var/run/nginx.pid && \
  chown -R app:app /var/cache/nginx && \
  chown -R app:app /usr/share/nginx/html
EXPOSE 8080
USER 1001
CMD sh buildWithEnv.sh

这是脚本 buildWithEnv.sh

#!/bin/bash

echo "===> Changin directory: /apptmp ..."
cd /apptmp

echo "===> Installing dependencies: npm install ..."
npm install

echo "===> Building application: npm run build ..."
npm run build

echo "===> Copying to exposed html folder ... "
rm -rf /usr/share/nginx/html/*
cp -r build/* /usr/share/nginx/html/

echo "===> Launching http server ... "
nginx -g 'daemon off;'
2个回答

博客文章中描述了一种可能的方法

基本上:您对静态资源中的所有环境特定部分使用占位符。然后配置 nginx'sub_filter以在运行时用环境特定值替换它们。

我终于找到了办法。

构建应用程序

第一步是对您的应用程序进行静态构建,与环境无关。(实际上对于我的情况,这是由 CI 完成的,所以我直接检索 Docker 构建部分中的静态构建)

创建 Nginx 配置

在您的项目中,创建一个文件,其中包含 nginx 的默认配置以及您需要的反向代理配置,并proxy_pass用可轻松且唯一可替换的值填充

server {
  gzip on;
  gzip_types text/plain application/xml application/json;
  gzip_vary on;
  listen 8080;
  location / {
    root   /usr/share/nginx/html;
    index  index.html index.htm;
    try_files $uri $uri/ /index.html;
  }
  location /api/ {
    proxy_set_header x-clientapikey REACT_APP_BAMBOO_API_KEY;
    proxy_pass REACT_APP_SERVICE_BACK_URL;
  }
  location /auth {
    proxy_set_header Authorization "Basic REACT_APP_AUTHENTIFICATION_AUTHORIZATION";
    proxy_pass REACT_APP_SERVICE_AUTH_URL;
  }
  error_page   500 502 503 504  /50x.html;
  location = /50x.html {
    root   /usr/share/nginx/html;
  }
}

Openshift 配置

在您的 OC 应用程序中,转到“环境”选项卡,并添加您将在 nginx conf 中使用的所有环境变量。

Dockerfile 构建

在 dockerfile 构建部分,将您的构建移动到 nginx html 文件夹中的正确位置,并处理您的配置文件,包括 nginx。

FROM nginx:1.15.5-alpine
RUN addgroup --system app \
  && adduser --uid 1001 --system --ingroup app app \
  && rm -rf /etc/nginx/conf.d/default.conf \
  && apk --update add sed
COPY ./build /usr/share/nginx/html/
COPY config/default.conf /etc/nginx/conf.d/
RUN chmod 777 -R /etc/nginx/conf.d/
COPY config/nginxSetup.sh .

RUN touch /var/run/nginx.pid && \
  chown -R app:app /var/run/nginx.pid && \
  chown -R app:app /var/cache/nginx && \
  chown -R app:app /usr/share/nginx/html
EXPOSE 8080
USER 1001
CMD sh nginxSetup.sh

运行 Dockerfile

在 dockerfile 运行部分 (CMD) 中,只需使用命令行工具sed即可替换 nginx 反向代理配置中的路径。

#!/usr/bin/env bash
sed -i "s|REACT_APP_SERVICE_BACK_URL|${REACT_APP_SERVICE_BACK_URL}|g" /etc/nginx/conf.d/default.conf
sed -i "s|REACT_APP_SERVICE_AUTH_URL|${REACT_APP_SERVICE_AUTH_URL}|g" /etc/nginx/conf.d/default.conf
sed -i "s|REACT_APP_BAMBOO_API_KEY|${REACT_APP_BAMBOO_API_KEY}|g" /etc/nginx/conf.d/default.conf
sed -i "s|REACT_APP_AUTHENTIFICATION_AUTHORIZATION|${REACT_APP_AUTHENTIFICATION_AUTHORIZATION}|g" /etc/nginx/conf.d/default.conf
echo "===> Launching http server ... "
nginx -g 'daemon off;'

你来了。