We are building Node.js microservices. For some reusable components we have created a utils folder. This folder is outside the actual microservices package. When we run the microservices, we can refer to that code using require(../../utils/logger) and it works like a charm.
However when trying to create the docker image for my microservices
project the container gives me an error saying:
Error: Cannot find module '../../Utils/logger
which makes a lot of sense as we are building the docker image inside the microservice project. There are few architectural decisions which needs to be taken here:
We move the utils code into each microservice as required.
2.Create a private npm module and inject dependency into the microservice package.json file. Not sure if that would work.
Any suggestions on this are highly appreciated.
Best, - Vaibhav
Don't use require(../../utils/logger), use npm packages
You should avoid using same files for microservice with symlink or requiring from one folder, because it destroys Loose coupling.
Loose couplingis a design goal that seeks to reduce the inter-dependencies between components of a system with the goal of reducing the risk that changes in one component will require changes in any other component. Loose coupling is a much more generic concept intended to increase the flexibility of a system, make it more maintainable, and makes the entire framework more "stable".
Simply put, you can't have different version of your logger file, but you can have different version of your logger npm package.
Implementation details for using npm modules as reusable components for Node.js microservices:
@vaibhav/loggerChose npm registry. There are such options:
If you use 2.3 or 2.4 solution, then you need to choose ip or link for your server. My advice is use link. Example https://your-registry.com
registry=https://your-registry.com. Your registry should be able to cache public packages.@vaibhav:registry=https://mycustomregistry.example.org npm version with patch or minor param. Updating major version is breaking change, which we do manualy.package-lock.json file. Developers should check build status and press merge button manually.Its not part of your question to elaborate how to deal with shared libraries in Microservice-Ecosystems and what to avoid there, but if you like, you should read this up to get you at least a list for pros and cons of "sharing".
Beside that, you can create a library container which only offers this library to be mounted.
version: "2"
services:
shared:
image: me/mysharelib
m1:
volume_from:
- shared:ro
m2:
volume_from:
- shared:ro
while your mysharedlib image looks more or less like this
FROM busybox
COPY bin/busyscript.sh /usr/local/bin/busyscript
WORKDIR /your/lib/folder
VOLUME /your/lib/folder
CMD ["busyscript"]
and your busyscript is just a dummy like this
#!/bin/sh
#set -x
pid=0
# SIGTERM-handler
term_handler() {
if [ $pid -ne 0 ]; then
kill -SIGTERM "$pid"
wait "$pid"
fi
exit 143; # 128 + 15 -- SIGTERM
}
# setup handlers
# on callback, kill the last background process, which is `tail -f /dev/null` and execute the specified handler
trap 'kill ${!}; term_handler' SIGTERM
echo "Started DW php code"
# wait forever
while true
do
tail -f /dev/null & wait ${!}
done
As you see, m1/m2 ... m10 mount the library which and it is truly shared across all microservices.
Alternatives: You can for sure use an private NPM packages or simply package the shared lib into the microservice m1..m10 during image build time.
What describe above especially suits you well when you want to replace the shared library in the stack with very little overhead and want to ensure the library is in-sync for all container instancs
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With