# Reading Config Vars in Docker Often you will need to read in config values in a react app, for example when connecting to a backend API, or when using config values to change various UI elements or control enabled features. When using a full stack framework such as Next.JS or Gatsby, you can use the `process.env` object to read in environment variables as these applications are both server and client side rendered. If we are using a client side only framework we will not have the luxury of using `process.env`. In this case we need to be able to load in our own configuration values into the app running in a Docker container. To this end we can create a `config.json` file, and serve this file in the Docker container mounted as a volume. For this demo we'll be using a simple Vite react frontend, with an ExpressJS backend. We'll be using Docker to containerize our application. ## Creating a Backend ### Setup First get started by creating a `backend` directory, and inside it a `package.json` with the following content: ::: code-group ```json [backend/package.json] { "name": "backend" } ``` ::: ### Installing Dependencies ```bash cd backend npm install typescript express cors npm install -D @types/express @types/cors @types/node ts-node ``` ### Creating the backend In our case the backend will be a simple ExpressJS server that returns a list of users, so we can make this all one file: ::: code-group ```typescript [backend/src/index.ts] import express from "express"; import cors from "cors"; const USERS = [ { id: 1, name: 'John Doe', email: 'john.doe@gmail.com' }, { id: 2, name: 'Jane Doe', email: 'jane.doe@gmail.com' }, { id: 3, name: 'John Smith', email: 'john.smith@gmail.com' } ] const app = express(); app.use(cors()); app.get('/', (_, res) => { res.send('Hello World!'); }); app.get('/users', (_, res) => { res.json(USERS); }); app.listen(3000, () => { console.log('Server is running on port 3000'); }); ``` ::: ### Setting Up Typescript Create a `tsconfig.json` file in the `backend` directory with the following content: ::: code-group ```json [backend/tsconfig.json] { "compilerOptions": { "target": "es2016", "module": "commonjs", "esModuleInterop": true, "strict": true, "skipLibCheck": true, "rootDir": "./src", "outDir": "./dist", } } ``` ::: ### Add Scripts Add the following scripts to the `package.json` file: ::: code-group ```json [backend/package.json] { "scripts": { "dev": "ts-node src/index.ts", "build": "tsc", "start": "node dist/index.js" }, } ``` ::: ## Creating a Frontend ### Setup Create a new Vite React TS app using the command `npm create vite@latest frontend -- --template react-ts`, ensuring you are in the parent directory of the `backend` directory. ### Ignore the Local Config File Update the `.gitignore` file to ignore the `config.json` file we will be creating later: ::: code-group ``` [frontend/.gitignore] # ... public/config.json ``` ::: ### Create Config File Create a `config.js` file in the `public` directory with the following content: ::: code-group ```js [frontend/public/config.js] const config = { apiUrl: 'http://localhost:3000' } window.config = config; ``` ::: Next update the `index.html` file to include the `config.json` file: ::: code-group ```html [frontend/public/index.html] ``` ::: ### Create a Config Util Create a `config.ts` file in the `src` directory with the following content: ::: code-group ```typescript [frontend/src/config.ts] export interface Config { apiUrl: string; } export const config = (window as any).config as Config; ``` ::: ### Update App Update the app to call the backend API: ::: code-group ```tsx [frontend/src/App.tsx] import { useEffect, useState } from "react" import { config } from "./config" type User = { id: number, name: string email: string } function App() { const [users, setUsers] = useState([] as User[]) useEffect(() => { const fetchUsers = async () => { const response = await fetch(`${config.apiUrl}/users`) const data = await response.json() setUsers(data) } fetchUsers(); }, []) return ( <>