Within an Angular project, base and API endpoint URLs are typically defined inside environment files located in the src/environments folder. A common practice involves generating a dedicated environment file for every deployment target.
- environment.ts
- environment.dev.ts
- environment.test.ts
- environment.stage.ts
- environment.prod.ts
environment.ts
import packageInfo from '../../package.json';
export const environment = {
production: false,
BASE_URL: '//localhost:4200',
VERSION: packageInfo.version,
};
At build time, a configuration flag determines which environment file gets swapped in as the default—either environment.ts or environment.<CONFIGURATION>.ts—with the selection driven by the supplied flag.
npm run build -- --configuration=stage
The drawback of that strategy is that a single build can’t be reused across different environments like DEV, TEST, STAGE, and PROD, because BASE_URL gets baked in at build time. To work around it, we swap out BASE_URL in the generated main.*.js file when the Docker container fires up.
Next, examine a typical multi-stage Dockerfile. For a deeper dive, check out my previous article.
Dockerfile
// See my other post for Build stage, so skipping it here
############ User Nginx alpine image ############
FROM nginx:stable-alpine
# Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*
# Copy nginx config file
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
# Copy dist folder fro build stage to nginx public folder
COPY --from=builder /app/dist /usr/share/nginx/html
# Start NgInx services
CMD ["nginx", "-g", "daemon off;"]
For this setup, one command can handle updating the BASE_URL at the time a Docker container or service starts. If the existing BASE_URL/API_URL is set to employee-dev.example.com, swapping it out is possible with a UNIX sed command, demonstrated here
CMD sed -i "s/employee-dev.example.com/employee-$CONFIGURATION.example.com/g" /usr/share/nginx/html/main.*.js && nginx -g 'daemon off;'
Here’s what the revised Dockerfile now looks like:
Dockerfile (Updated)
// See my other post for Build stage, so skipping it here
############ User Nginx alpine image ############
FROM nginx:stable-alpine
# Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*
# Copy nginx config file
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
# Copy dist folder fro build stage to nginx public folder
COPY --from=builder /app/dist /usr/share/nginx/html
# Start NgInx services
CMD sed -i "s/employee-dev.example.com/employee-$CONFIGURATION.example.com/g" /usr/share/nginx/html/main.*.js && nginx -g 'daemon off;'
you can then launch the container by using the Docker run command.
docker run -p 4000:80 -e CONFIGURATION=test <IMAGE_ID>
An alternate path is to rely on Docker ENTRYPOINT for the identical outcome. For that approach, craft a fresh start.sh script file and paste the command inside.
start.sh
#!/bin/sh
sed -i "s/employee-dev.example.com/employee-$CONFIGURATION.example.com/g" /usr/share/nginx/html/main.*.js
nginx -g 'daemon off;'
ensure this file is duplicated, given execute permissions, and referenced in the ENTRYPOINT instruction
Dockerfile (Revised to Include ENTRYPOINT)
###### User Nginx alpine image ######
FROM nginx:stable-alpine
ENV CONFIGURATION='dev'
# Remove default nginx website
RUN rm -rf /usr/share/nginx/html/*
# Copy nginx config file
COPY ./nginx/nginx.conf /etc/nginx/nginx.conf
# Copy dist folder fro build stage to nginx public folder
COPY /dist /usr/share/nginx/html
COPY start.sh /usr/share/nginx/html
RUN chmod +x /usr/share/nginx/html/start.sh
# Start NgInx service
ENTRYPOINT ["./usr/share/nginx/html/start.sh", "$CONFIGURATION"]
launch the container via the Docker run command
docker run -p 4000:80 -e CONFIGURATION=test <IMAGE_ID>
Even without Docker, this method still applies, because sed is just a basic UNIX utility.
