Last active
July 11, 2018 17:19
-
-
Save stevenuray/425a38ee864beaddf3702d3bb1b1039f to your computer and use it in GitHub Desktop.
Dockerlith Application Container Entrypoint Script for Synchronizing Access to Shared NPM Dependencies
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env bash | |
# Application containers should not continue starting | |
# if their dependencies are unverified, | |
# so if any command in this script fails the container | |
# will stop it’s initialization process and | |
# an error message will be presented to the user. | |
set -euo pipefail | |
# Set variables here | |
# The resource to have synchronized write access is the node_modules directory. | |
# An empty, hidden file .npm_lock is created to use it’s file descriptor. | |
# The file descriptor to be locked is number 200. | |
# Finally, the .package_md5 file is used to store a hash string of the package.json file | |
# so no call to npm install is made unless the package.json file has changed. | |
readonly NPM_DIR=/app/src/node_modules | |
readonly LOCK_FILE=$NPM_DIR/.npm_lock | |
readonly LOCK_FD=200 | |
readonly MD5_FILE=$NPM_DIR/.package_md5 | |
# Define functions here | |
# Here is a generic function that locks a file with a file descriptor, | |
# using the flock unix command. | |
# Docker containers share the host’s kernel, | |
# so they can communicate with each other through these file descriptor locks. | |
lock() { | |
# Create lock file. | |
eval "exec $2>$1" | |
# Get exclusive, waiting lock on the file descriptor of the lock file. | |
flock --exclusive $2 | |
} | |
# Releases the lock acquired with lock() | |
unlock() { | |
echo "This container is releasing the lock on the npm libraries" | |
flock --unlock $1 | |
} | |
# Containers should only install npm libraries if the dependencies have changed | |
# in package.json. Therefore, package.json has an MD5 hash saved to a shared file | |
# each time the dependencies are installed. | |
# If package.json changes due to new dependencies, | |
# a different MD5 hash will be generated that differs from | |
# the one that has been saved. | |
check_npm_libraries() { | |
if [ ! -f $MD5_FILE ] || ! md5sum -c --status <<<"$(cat $MD5_FILE)"; then | |
echo "INVALID" | |
else | |
echo "VALID" | |
fi | |
} | |
# If the dependencies have changed, they are updated with a call to “npm install”. | |
# After this, the hash of the package.json file the dependencies came from | |
# is saved to the hash file. | |
install_npm_libraries() { | |
npm install grunt | |
echo "Installing npm Libraries..." | |
npm install --unsafe-perm --loglevel info | |
write_md5_sum_to_md5_file | |
} | |
write_md5_sum_to_md5_file() { | |
echo "package.json md5" $(md5sum ./package.json) | |
md5sum ./package.json > $MD5_FILE | |
} | |
prepare_npm_volume() { | |
#Try to get node_modules lock. | |
lock $LOCK_FILE $LOCK_FD | |
#Check status of npm libraries now that this container has the lock. | |
echo "This container has the lock on the npm libraries." | |
npm_library_status=$(check_npm_libraries) | |
if [ "$npm_library_status" == "INVALID" ]; then | |
install_npm_libraries | |
else | |
echo "Valid cached npm libraries detected, skipping npm install" | |
fi | |
# The lock must be explicitly released here, | |
# because the process is expected to continue after this script is done. | |
unlock $LOCK_FD | |
} | |
#Execute commands here | |
prepare_npm_volume | |
echo "arguments received: $@" | |
exec "$@" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment