JeanSaigne
JeanSaigne

Reputation: 333

How to make a single React Docker build/image to run through all environments?

i'm trying to deploy a React application in a single Docker container able to run through dev, preprod and prod on an OpenShift platform on which i can only push tagged docker images. In order to do this i have:

What i can do:

I can easily generate a production build '/build' that will be added in the docker image build phase and will run with a production context or i can build at run start (but just writing it feels bad).

The problem:

This generated image isn't able to run through all environment, and i don't want to have a specific build for each environment.

What i want:

I want to be able to generate a single docker image that will run through all environments without having to install dependencies or build when only RUN is needed.

here is my 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

And here is the script 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;'

Upvotes: 4

Views: 2348

Answers (2)

Fabian Braun
Fabian Braun

Reputation: 3930

A possible approach is described on this blog-post

Basically: You use placeholders for all environment specific parts in your static resources. Then you configure nginx' sub_filter to replace those at runtime with the environment specific values.

Upvotes: 3

JeanSaigne
JeanSaigne

Reputation: 333

I finally found a way.

Build application

The first step is to make a static build of your application, environment agnostic. (Actually for my situation this is done by the CI so i directly retrieve the static build in Docker build part)

Create Nginx conf

In your project, create a file holding the default configuration for nginx, plus the reverse proxy configuration your need, and fill the proxy_pass with values easily and uniquely replacable.

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 configuration

In your OC application, go to the "environment" tab, and add all the environnement variables you will use in your nginx conf.

Dockerfile build

In the dockerfile build part, move your build to its correct position into nginx html folder, and handle your configuration files, including 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 run

In the dockerfile run part (CMD), just use the command line tool sed in order to replace paths in your nginx reverse proxy configuration.

#!/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;'

And here you are.

Upvotes: 0

Related Questions