Onde estou? – Definição de variável de ambiente para informar a aplicação de qual é o ambiente
Esse é um texto sobre uma definição que é bem simples de arquitetura, mas que muitos “arquitetos” não fazem. O conceito é informar a aplicação, com o uso de uma definição externa, em qual ambiente essa aplicação se encontra. Com isso, a aplicação é capaz de tomar ações com base no ambiente em que ela está em execução.
Leia mais: Onde estou? – Definição de variável de ambiente para informar a aplicação de qual é o ambienteNesse cenário, o código é o menos importante. O conceito é o que faz a diferença. Mas caso queira fazer o acompanhamento, aqui está o código: https://github.com/escovabit-tec-br/nodejs-env-environment
Bem, vamos ao conceito.
Nossa aplicação precisa se relacionar com o meio (ambiente) em que ela está em execução, e o meio deve influenciar como nossa aplicação se comporta. Partindo disso, podemos definir um padrão:
Deve existir uma variável de ambiente com o nome
environmentque pode ter os valores:
- local
- development
- staging
- production
Sabendo disso. Nossa aplicação deve ser capaz de se adaptar ao “ambiente” que se encontra, abaixo um exemplo bem simples:
const appConfig = {
development: {
apiUrl: "https://api.publicapis.org/entries",
},
production: {
apiUrl: "https://catfact.ninja/fact",
},
};
const environment = process.env.ENVIRONMENT || "development";
const resultData = appConfig[environment];
module.exports = resultData;
Podemos ver que o conteúdo no module.export muda de acordo com o ambiente em que e aplicação se encontra. Assim, para cada ambiente, a apiUrl será diferente.

Este é um modelo bem simples de fazer o uso deste tipo de arquitetura. Já falei aqui de um modelo mais organizado que é usando o spring-cloud.
Do lado do “ambiente”, é necessário de alguma forma ter esse valor de ENVIRONMENT disponível para a aplicação. Como exemplo, vou simular a aplicação rodando em um Kubernetes.
Primeiro, criamos uma secret com o dado:
apiVersion: v1
kind: Secret
metadata:
name: default-cfg-environment
namespace: l2-app-backend
labels:
app.kubernetes.io/managed-by: Helm
annotations:
meta.helm.sh/release-name: base
meta.helm.sh/release-namespace: l4-cfg-helm
type: Opaque
data:
ENVIRONMENT: ZGV2ZWxvcG1lbnQ= #development
Abaixo em destaque a configuração no deployment:
apiVersion: apps/v1
kind: Deployment
spec:
spec:
containers:
- name: ms-generic
envFrom:
- secretRef:
name: default-cfg-environment
Aqui o arquivo de deployment completo com o uso da secret:
apiVersion: apps/v1
kind: Deployment
metadata:
name: my-app
namespace: l2-app-backend
labels:
app.kubernetes.io/instance: my-app
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: my-app
annotations:
deployment.kubernetes.io/revision: '24'
meta.helm.sh/release-name: my-app
meta.helm.sh/release-namespace: l2-app-backend
spec:
replicas: 1
selector:
matchLabels:
app.kubernetes.io/instance: my-app
app.kubernetes.io/name: my-app
template:
metadata:
creationTimestamp: null
labels:
app.kubernetes.io/instance: my-app
app.kubernetes.io/managed-by: Helm
app.kubernetes.io/name: my-app
spec:
containers:
- name: ms-generic
image: ### IMAGE NAME ###
ports:
- name: app
containerPort: 3000
protocol: TCP
envFrom:
- secretRef:
name: my-app-helm
- secretRef:
name: default-cfg-environment
resources: {}
livenessProbe:
httpGet:
path: /metrics
port: app
scheme: HTTP
initialDelaySeconds: 80
timeoutSeconds: 10
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
readinessProbe:
httpGet:
path: /metrics
port: app
scheme: HTTP
initialDelaySeconds: 80
timeoutSeconds: 10
periodSeconds: 10
successThreshold: 1
failureThreshold: 3
terminationMessagePath: /dev/termination-log
terminationMessagePolicy: File
imagePullPolicy: IfNotPresent
securityContext: {}
restartPolicy: Always
terminationGracePeriodSeconds: 30
dnsPolicy: ClusterFirst
serviceAccountName: my-app
serviceAccount: my-app
securityContext: {}
schedulerName: default-scheduler
strategy:
type: RollingUpdate
rollingUpdate:
maxUnavailable: 25%
maxSurge: 25%
revisionHistoryLimit: 10
progressDeadlineSeconds: 600
Com “tudo” isso feito, agora temos uma aplicação “portável” entre ambientes. Podendo assim levar a mesma aplicação sem precisar recompilar (“re-buildar”) ela.
Obrigado pela atenção, e até a próxima.