Type-Safe Node.js app configuration with Docker secrets
Most of the apps, especially those dealing with external world need some configuration in order to work properly.
As it may run in different environments it is not possible to provide those at compile time to ensure type safety,
but we may use libraries like typematcher there.
In this post I’ll go through the process of configuring a nodejs application
in type-safe manner and running it as docker swarm service.
App and Configuration
As a demo app for this example I’m going to use a seed repo
I personally use for new projects, written in TypeScript.
Configuration is loaded using config package
and typematcher is matching config for pre-defined structure and types.
Let’s assume we have a component which require some config options and define them as:
Our app will probably need more of such configurations so we can compose them into single app config type:
Next we define validations for config types:
And finally load config and export it to its users:
If loaded config will fail to match defined requirements it will throw an exception.
I usually keep default configuration file in config/ folder (config/default.json) and commit it to git
(it does not contain any secret info, only defines the structure), and there is 1 more file per environment,
ex: development.json, production.json, in same folder, ignored with .gitignore and .dockerignore,
but any other folder which works for you - is just perfect.
DO NOT commit configs files to git and DO NOT bundle with docker images, this is bad, bad practice!
For this demo I’ll name service as express-ts-seed, and same will be used as HOSTNAME, so, following
config’s file load order rules
will prepare 2 config files:
Create docker secrets
Let’s check available secrets:
Filenames (and secret names) selected to avoid conflicts with other services running on same swarm cluster and also using docker secrets.
By setting NODE_CONFIG_DIR=/run/secrets environment variable - we configuredconfig
package to use /run/secrets for searching config files, and using --hostname "express-ts-seed" and NODE_ENV=production
2 of file load order rules matched: