Setting Up Dynamic Environment Variables with Vite and Docker
Tags: vite, docker, webdev, devops
Published: 2024-06-18 14:42:02

In this tutorial, we'll walk through the process of setting up dynamic environment variables in a Vite project, ensuring that these variables can be replaced dynamically within a Docker container. This setup allows for flexibility and ease of deployment across different environments.

## Setting Up the Environment Variables

First, ensure that your environment variables for Vite start with the `VITE_` prefix. This makes it easy to manage and replace them dynamically.

### Step 1: Define Environment Variables

Create environment variable files for different environments at the root of your project. Vite uses different `.env` files for different environments:

- **Production:** Create a `.env.production` file.
- **Local Development:** Optionally, create a `.env.local` file for local development.

#### Example: `.env.production`

```properties
VITE_PREFIX_VALUE=PREFIX_VALUE
```

### Step 2: Create an Environment Class

In your project, create a class to map these Vite environment variables to constants that you can use throughout your project.

```typescript
class Environment {
    PREFIX_VALUE: string;
    constructor() {
        this.PREFIX_VALUE = import.meta.env.VITE_PREFIX_VALUE;
    }
}

const environment = new Environment();

export default environment;
```

## Setting Up the Tooling

We'll use a shell script to dynamically replace the baked-in environment variables within the Docker container.

### Step 3: Create a Shell Script

Create a file named `env.sh` with the following content. 

 > **Important**: Ensure the file has `LF` line endings, not `CRLF`.

```shell
#! /bin/sh

if [ -z "$APP_ENV_PREFIX" ]; then
    echo "APP_ENV_PREFIX is not set. Exiting."
    exit 1
fi

for i in $(env | grep "^$APP_ENV_PREFIX"); do
    key=$(echo "$i" | cut -d '=' -f 1)
    value=$(echo "$i" | cut -d '=' -f 2-)
    
    echo "$key=$value"
    
    find "/tmpl/dist/web-app/" -type f -exec sed -i "s|${key}|${value}|g" '{}' +
done
```

Ensure that the `$APP_ENV_PREFIX` matches your chosen prefix (`PREFIX_` in this example). The path `/tmpl/dist/web-app/` should match the location of your built project within the Docker container.

## Setting Up the Docker Container

### Step 4: Create a Dockerfile

Create a `Dockerfile` with the following content:

```dockerfile
FROM node:hydrogen-alpine as build-env

COPY package.json package-lock.json ./
RUN npm install

RUN mkdir -p /usr/src/app && cp -R ./node_modules ./usr/src/app

WORKDIR /usr/src/app

COPY . ./

RUN npm run build

FROM nginx:mainline-alpine3.18-perl

COPY ./.nginx/${NGINX_CONFIG_FILE:-nginx.conf} /etc/nginx/nginx.conf

RUN rm -rf /usr/share/nginx/html/*

COPY --from=build-env /usr/src/app/dist /usr/share/nginx/html/web-app

COPY --from=build-env /usr/src/app/dist/* /tmpl/dist/web-app/

COPY env.sh /docker-entrypoint.d/env.sh

RUN chmod +x /docker-entrypoint.d/env.sh

CMD ["nginx", "-g", "daemon off;"]
```

### Key Points:

- **File Paths:** Ensure the path `/tmpl/dist/web-app/` matches the location specified in the shell script.
- **Shell Script:** Place the `env.sh` file in `/docker-entrypoint.d/` to ensure it runs on container startup.

## Setting Up Docker Compose

### Step 5: Create a Docker Compose File

Create a `docker-compose.yml` file to define and run your container.

```yaml
services:
    app:
        image: webapp:latest
        environment:
            APP_ENV_PREFIX: PREFIX_
            PREFIX_VALUE: "This is the value you want to dynamically use in your container."
```

### Key Points:

- **Environment Variable Prefix:** Set the `APP_ENV_PREFIX` to match your prefix (`PREFIX_`).
- **Dynamic Values:** Define your environment variables with the specified prefix.

## Conclusion

By following this tutorial, you've set up a Vite project within a Docker container, enabling dynamic environment variables. This approach ensures that your application can adapt to different environments seamlessly, making deployments more flexible and efficient.

Feel free to adjust the paths and prefixes to fit your specific project requirements. Happy coding!