Substitute environment variables for a frontend app served by Kestrel
When serving a website from a docker container, we usually create a multi staged Dockerfile using nginx as our web server. The Dockerfile
probably looks something like this:
... left out for brevity...
FROM nginx:alpine AS deploy
WORKDIR /usr/share/nginx/html
COPY --from=build /app/dist .
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80 443
If your frontend application ever need to use environment variables passed into your docker container during runtime, you'll probably googled your way to several solutions suggesting that envsubst
might help you out.
... left out for brevity...
FROM nginx:alpine AS deploy
WORKDIR /usr/share/nginx/html
COPY --from=build /app/dist .
COPY ./nginx.conf /etc/nginx/conf.d/default.conf
EXPOSE 80 443
CMD ["/bin/bash", "-c", "envsubst < /usr/share/nginx/html/env.template.js > /usr/share/nginx/html/env.js && exec nginx -g 'daemon off;'"]
But, what if you want to swap out nginx
and serve your frontend app using ASP.NET Core
's web server, Kestrel
?
Execute envsubst when running a ASP.NET Core containarized application
Initally our Dockerfile used the mcr.microsoft.com/dotnet/aspnet:7.0
as our runtime base image.
FROM mcr.microsoft.com/dotnet/sdk:7.0 as build-env
WORKDIR /app
# steps to build the application
# is left out..
FROM mcr.microsoft.com/dotnet/aspnet:7.0 as runtime
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "MyExecutingAssembly.dll"]
What happens if we just replace the ENTRYPOINT with
CMD ["/bin/sh", "-c", "envsubst < /some-path/env.template.js > /some-other-path/env.js && exec nginx -g 'daemon off;'"]
You're obviously able to build the image, but will fail when you try to run a container with this image
/bin/bash: line 1: envsubst: command not found
Okay, that makes sense given that the image we're using mcr.microsoft.com/dotnet/aspnet:7.0
doesnt support envsubst
.
The solution to this problem is to replace the base image with the alpine version, in our case mcr.microsoft.com/dotnet/aspnet:7.0.2-alpine3.17-amd64.
The entrypoint for the container will now look something like this:
CMD ["/bin/sh", "-c", "apk add gettext && envsubst < /some-path/env.template.js > /some-path/env.js && dotnet MyExecutingAssembly.dll"]
Using envsubst
is a powerful way to read environment variables passed into a docker container and replace the values served as a javascript file. This articled showed how we can use this command when serving our frontend as static files from ASP.NET Cores web server Kestrel.