DEV Community

loading...
Cover image for Variável de ambiente - (ReactJS, Docker, AKS)

Variável de ambiente - (ReactJS, Docker, AKS)

Felipe de Senna
Front-end apaixonado por tecnologia, conhecimento e aprendizado.
Updated on ・6 min read

A maioria dos projetos hoje em dia são desenvolvidos para diversos ambientes de trabalho (homolog, staging, production). E junto com esses ambientes temos a preocupação com a infraestrutura que o projeto vai utilizar, além do Framework utilizado no front-end para usabilidade e visualização de conteúdo.

Seguindo nesse raciocínio vamos falar sobre como utilizar variável de ambiente em um projeto que utiliza ReactJS, Docker e AKS, fazendo uma configuração simples para conseguir consumir a URL de uma API diferente de acordo com o ambiente em que o usuário está.

Após criar o projeto base com o npx create-react-app my-app vamos criar uma pasta onde ficará as configurações de variáveis para cada ambiente.

environments/base.js

export default {
  api: 'http://localhost:5000/api'
}
Enter fullscreen mode Exit fullscreen mode

O base.js é um arquivo inicial com o proposito de ser utilizado se nenhum outro arquivo ambiente for detectado pelas configurações.

environments/Homolog.js

export default {
  api: 'http://suaapi.hlg.seudominio.com.br/api',
};
Enter fullscreen mode Exit fullscreen mode

environments/Staging.js

export default {
  api: 'http://suaapi.stg.seudominio.com.br/api',
};
Enter fullscreen mode Exit fullscreen mode

environments/Production.js

export default {
  api: 'http://suaapi.prd.seudominio.com.br/api',
};
Enter fullscreen mode Exit fullscreen mode

Agora para finalizar as configurações das variáveis de ambiente vamos criar um último arquivo.

environments/index.js

import base from './base';

if (window.ENV) {
  localStorage.setItem('@environment', window.ENV);

  delete window.ENV;
}

const envClient = localStorage.getItem('@environment');
const environments = envClient || 'base';

const env = require('./' + environments).default;

export default {
  ...base,
  ...env,
}
Enter fullscreen mode Exit fullscreen mode

Nessa configuração verificamos se existe algum valor em window.ENV se existir valor salvamos ele no localStorage e deletamos o window.ENV, depois recuperamos esse valor salvo no localStorage para utiliza-lo e caso esse valor não exista utilizamos 'base'.
Ao final da configuração criamos uma nova importação utilizando require onde ela importa o arquivo correto utilizando a variável environments que pode conter o valor do localStorage ou 'base' e na conclusão exportamos as variáveis base e env onde teremos as informações necessárias para utilizar mais tarde.

Seguindo na configuração de variáveis de ambiente eu fiz uma alteração no App.js, essa alteração é simplesmente para exibir a variável env.api que vai ser consumida das configurações que fizemos anteriormente na pasta environments.

App.js

import React from 'react';

import logo from './logo.svg';
import env from './environments';
import './App.css';

function App() {
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>{env.api}</p>
      </header>
    </div>
  );
}

export default App;
Enter fullscreen mode Exit fullscreen mode

E para finalizar a configuração inicial e antes de partirmos para a criação da imagem do Docker e as configurações .YAML do Kubernetes, faremos algumas modificações na pasta public.

Primeiro vamos criar um novo arquivo .js dentro dela.

config.js

window.ENV = "Homolog"
Enter fullscreen mode Exit fullscreen mode

Dentro desse arquivo temos uma configuração do window.ENV que utilizamos para leitura dentro do environments/index.js e que futuramente vai ser alterada via Kubernetes.

Logo após a criação desse arquivo vamos adicionar mais um script dentro do arquivo index.html que fica na pasta public.

index.html

<script type="text/javascript" src="%PUBLIC_URL%/config.js"></script>
Enter fullscreen mode Exit fullscreen mode

Essa alteração é para o projeto conseguir consumir o arquivo config.js após o build do projeto.

Configuração de build e Kubernetes

Antes de criar a imagem do projeto no Docker vamos primeiro executar o build do próprio ReactJS, o que vai facilitar a criação da imagem no Docker.

npm run build / yarn build
Enter fullscreen mode Exit fullscreen mode

Para criação da imagem do Docker o arquivo Dockerfile ficará da seguinte maneira:

Dockerfile

# Stage 1
FROM nginx:1.17

# Stage 2
COPY build/ /usr/share/nginx/html
Enter fullscreen mode Exit fullscreen mode

Além de já utilizar o build que foi feito pelo ReactJS anteriormente, utilizamos o nginx para rodar o html do projeto. Vale lembrar que o arquivo .dockerignore não deve conter a pasta build, porque se não ocorrerá um erro quando a imagem for criada.

Seguiremos para criação da imagem do Docker executando os comando na sequencia:

1 - Criando a imagem do projeto
docker build -t react-docker-aks .

2 - Criação do registro no Docker local
docker run -d -p 5000:5000 --restart=always --name registry registry:2

3 - Criação de tag para referencia da imagem
docker tag react-docker-aks localhost:5000/react-docker-aks

4 - Fazendo o push da imagem para o Docker local
docker push localhost:5000/react-docker-aks
Enter fullscreen mode Exit fullscreen mode

Obs.: é importante lembrar que para executar os comandos acima é necessário ter o Docker Desktop instalado na máquina.

E para finalizar criaremos os arquivos .YAML que são utilizados pelo Kubernetes para configuração dos clusters.

deployment.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: react-docker-aks
  labels:
    app: react-docker-aks
data:
  config.js: "window.ENV = \"Homolog\";"
---
kind: Deployment
apiVersion: apps/v1
metadata:
  name: react-docker-aks
spec:
  replicas: 1
  selector:
    matchLabels:
      app: react-docker-aks
  template:
    metadata:
      labels:
        app: react-docker-aks
    spec:
      containers:
        - name: react-docker-aks
          image: localhost:5000/react-docker-aks
          imagePullPolicy: Always
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config-js
              mountPath: /usr/share/nginx/html/config.js
              subPath: config.js
      volumes:
        - name: config-js
          configMap:
            name: react-docker-aks
      restartPolicy: Always
---
kind: Service
apiVersion: v1
metadata:
  name: react-docker-aks
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
      nodePort: 31000
  selector:
    app: react-docker-aks
Enter fullscreen mode Exit fullscreen mode

Na criação dos arquivos .YAML utilizamos uma estrutura padrão de configuração adicionando apenas alguns métodos que serviram para leitura e configuração do arquivo config.js que está na pasta public do projeto. São eles:

No ConfigMap adicionei

data:
  config.js: "window.ENV = \"Homolog\";"
Enter fullscreen mode Exit fullscreen mode

No Deployment dentro de spec containers

volumeMounts:
  - name: config-js
    mountPath: /usr/share/nginx/html/config.js
    subPath: config.js
Enter fullscreen mode Exit fullscreen mode

E a criação do volumes dentro do spec

volumes:
  - name: config-js
    configMap:
      name: react-docker-aks
Enter fullscreen mode Exit fullscreen mode

Foi uma escolha minha criar todas as configurações dentro do arquivo deployment.yaml mas da certo criando os arquivos separados em configmap.yaml, deployment.yaml e service.yaml, e depois criando o kustomization.yaml para juntar todos eles.

Para simular outros ambientes eu criei mais dois arquivos deployment.yaml o deployment-staging.yaml e deployment-production.yaml que tem o mesmo conteúdo do primeiro só modificando namespace, o valor do window.ENV e criando uma outra porta pro service.

deployment-staging.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: react-docker-aks-stg
  labels:
    app: react-docker-aks-stg
data:
  config.js: "window.ENV = \"Staging\";"
--------
kind: Deployment
apiVersion: apps/v1
metadata:
  name: react-docker-aks-stg
spec:
  replicas: 1
  selector:
    matchLabels:
      app: react-docker-aks-stg
  template:
    metadata:
      labels:
        app: react-docker-aks-stg
    spec:
      containers:
        - name: react-docker-aks-stg
          image: localhost:5000/react-docker-aks
          imagePullPolicy: Always
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config-js
              mountPath: /usr/share/nginx/html/config.js
              subPath: config.js
      volumes:
        - name: config-js
          configMap:
            name: react-docker-aks-stg
      restartPolicy: Always
--------
kind: Service
apiVersion: v1
metadata:
  name: react-docker-aks-stg
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
      nodePort: 31001
  selector:
    app: react-docker-aks-stg
Enter fullscreen mode Exit fullscreen mode

deployment-production.yaml

apiVersion: v1
kind: ConfigMap
metadata:
  name: react-docker-aks-prd
  labels:
    app: react-docker-aks-prd
data:
  config.js: "window.ENV = \"Production\";"
--------
kind: Deployment
apiVersion: apps/v1
metadata:
  name: react-docker-aks-prd
spec:
  replicas: 1
  selector:
    matchLabels:
      app: react-docker-aks-prd
  template:
    metadata:
      labels:
        app: react-docker-aks-prd
    spec:
      containers:
        - name: react-docker-aks-prd
          image: localhost:5000/react-docker-aks
          imagePullPolicy: Always
          ports:
            - containerPort: 80
          volumeMounts:
            - name: config-js
              mountPath: /usr/share/nginx/html/config.js
              subPath: config.js
      volumes:
        - name: config-js
          configMap:
            name: react-docker-aks-prd
      restartPolicy: Always
--------
kind: Service
apiVersion: v1
metadata:
  name: react-docker-aks-prd
spec:
  type: NodePort
  ports:
    - port: 80
      targetPort: 80
      protocol: TCP
      nodePort: 31002
  selector:
    app: react-docker-aks-prd
Enter fullscreen mode Exit fullscreen mode

Para executar o Kubernetes no Docker Desktop é necessário ativar-lo e também é preciso ter o Minikube instalado para executar os comandos que virão na sequencia.

Ativando o Kubernetes
Ativando o Kubernetes no Docker-Desktop

Executando os comandos

1 - Criando o contexto padrão para o cluster do Kubernetes
kubectl config use-context docker-desktop

2 - Criando o serviço Kubernetes
kubectl apply -f deployment.yaml

3 - Serviço do ambiente staging
kubectl apply -f deployment-staging.yaml

4 - Serviço do ambiente production
kubectl apply -f deployment-production.yaml
Enter fullscreen mode Exit fullscreen mode

Os ambientes ficaram disponivéis nas URLs:
HLG
http://localhost:31000/

STG
http://localhost:31001/

PRD
http://localhost:31002/

E assim se concluí o projeto e todas as configurações realizadas para conseguir ler uma variável de ambiente após o build do ReactJS via Kubernetes.
O projeto todo pode ser acessado e baixado no meu github: https://github.com/felipedesenna/react-docker-aks

Discussion (0)

Forem Open with the Forem app