DEV Community

Cover image for Flexible Angular Builds: A Guide to Angular 19 Build-Time Variables with Docker
Daniel Sogl
Daniel Sogl

Posted on • Originally published at Medium

Flexible Angular Builds: A Guide to Angular 19 Build-Time Variables with Docker

When deploying Angular applications as containers, managing environment variables at build time has always been a challenge. With Angular 19, the CLI now supports passing variables directly at build time. In this article, I’ll demonstrate how to dockerize your Angular application and leverage build-time variables for seamless containerized deployment.

What Are Build-Time Variables?

Build-time variables allow you to inject configuration values during the build process. These variables are embedded into the application, enabling different behaviors or settings based on the build environment.

This approach is perfect for:

  • Environment-Specific API Endpoints: Switch between development, staging, and production configurations seamlessly.
  • Feature Flags: Enable or disable features dynamically at build time.
  • Secure Secrets Management: Avoid exposing sensitive information in your source code.

Step-by-Step Guide: Dockerizing an Angular App with Build-Time Variables

Step 1: Define Variables in the Environment File

Start by defining your variables as constants in an environment.ts file (or another dedicated file). You can optionally define default values and export them as an environment object for reuse in your Angular project:

declare const apiKey: string;
declare const configuration: 'development' | 'production';

export const environment = {
  apiKey,
  configuration,
};

Enter fullscreen mode Exit fullscreen mode

Step 2: Create a Dockerfile with Build Arguments

Use a Dockerfile to define how the build-time variables will be injected. Below is a basic example; for a more complex setup, check the linked GitHub repository at the end of the article:

# Stage 1: Build Angular app
FROM node:lts-alpine AS build

# Set working directory
WORKDIR /app

# Copy package files and install dependencies
COPY package.json package-lock.json ./
RUN npm install

# Copy source code
COPY . .

# Define build arguments and use them during the build
ARG API_KEY
ARG CONFIGURATION=production
ENV API_KEY=$API_KEY
ENV CONFIGURATION=$CONFIGURATION

RUN npm run build -- --configuration=$CONFIGURATION --define apiKey=\"$API_KEY\" --define configuration=\"$CONFIGURATION\"

# Stage 2: Serve the app using Nginx
FROM nginx:alpine
COPY nginx.conf /etc/nginx/nginx.conf
COPY --from=build /app/dist /usr/share/nginx/html
Enter fullscreen mode Exit fullscreen mode

The new --define option passes the variable to the bundler and replaces the placeholder values we created in the first step.

Step 3: Pass Build-Time Variables in Docker Compose

Create a docker-compose.yml file to pass values for the build arguments defined in the Dockerfile:

services:
  webapp:
    build:
      context: .
      args:
        - API_KEY=YOUR_PRODUCTION_API_KEY
        - CONFIGURATION=production
    ports:
      - "4200:80"
    environment:
      - NODE_ENV=production
Enter fullscreen mode Exit fullscreen mode

This setup ensures that YOUR_PRODUCTION_API_KEY and production are injected into your Angular build process during container creation.

Step 4: Access Build-Time Variables in Your Application

In your Angular application, use the injected variables like this:

import { Component } from '@angular/core';
import { environment } from '../environment';

@Component({
  selector: 'app-root',
  template: `
    <div class="container">
      <h1>Angular Environment Variables Demo</h1>
      <p>Configuration: {{ configuration }}</p>
      <p>API Key: {{ apiKey }}</p>
    </div>
  `,
})
export class AppComponent {
  protected readonly apiKey = environment.apiKey;
  protected readonly configuration = environment.configuration;
}
Enter fullscreen mode Exit fullscreen mode

Step 5: Configure Nginx for Production

Finally, configure Nginx to serve your Angular application:

server {
    listen 80;
    server_name localhost;
    root /usr/share/nginx/html;
    index index.html;

    location / {
        try_files $uri $uri/ /index.html;
    }
}
Enter fullscreen mode Exit fullscreen mode

Place this configuration file (nginx.conf) in your project directory, and it will be included in the Docker image during the build process.

Benefits of Combining Docker and Build-Time Variables

Security: Embed secrets like API keys during the build process, avoiding exposure in source code or runtime environments.

Environment Flexibility: Switch environments by modifying Docker Compose files without hardcoding changes.

Streamlined CI/CD: Automate builds for multiple environments, enhancing deployment efficiency.

Conclusion

With Angular 19’s build-time variables and Docker, you can streamline application builds, manage environment-specific configurations effortlessly, and enhance security. This combination is essential for developers looking to create scalable and flexible deployment pipelines. As promised I created a GitHub repository with a extended Docker file that can be found here: https://github.com/danielsogl/ng-env-docker-demo

Try Dockerizing your Angular application today and share your experiences!

Top comments (0)