Compare commits

...

4 Commits

Author SHA1 Message Date
f673f94283 fix(dockerfile): use tini to correct error code on exit
- node returns error on sigterm but this normal for docker termination
- coupled with javascript signal capture, tini ignores return 143,
reports 0
- allows for proper automatic restart since no error is reported
2021-07-30 17:10:37 -06:00
5994f3b82e perf(dockerfile): moved copy file order
- moved node file copy order, allow for package.json usage
- invocation js moved after node install, faster builds
2021-07-30 17:07:46 -06:00
106fe86cb9 feature(livereload): rewrite javascript: graceful async socket close
- rewrite javascript livereload script to use object for healthcheck
- aysnc operations shutting down healthcheck and livereload sockets
- handle signals properly
- fix error code reported by signals (node issue)
2021-07-30 17:06:05 -06:00
9717e8a6fa refactor: rename repo, image, containers
- rename for integration with node-dev environment and production
deployment
- update image and product name across all files
- use generated project file to install node dependencies
- bump internal version to 2.6
2021-07-30 11:53:41 -06:00
14 changed files with 1378 additions and 84 deletions

4
.env
View File

@ -1,6 +1,6 @@
# #
# Parameters for node-livereload-tls stack: # Parameters for ab-livereload stack:
# This file makes it easier to customize your node-livereload-tls stack deployment by providing centralized configuration options. # This file makes it easier to customize your ab-livereload stack deployment by providing centralized configuration options.
# This file is *not required* since all values have (sane) default settings. # This file is *not required* since all values have (sane) default settings.
# There is *no* sensitive information in this file. # There is *no* sensitive information in this file.

3
.gitignore vendored
View File

@ -70,3 +70,6 @@ fabric.properties
# Android studio 3.1+ serialized cache file # Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser .idea/caches/build_file_checksums.ser
# node modules
build/node_modules

View File

@ -0,0 +1,13 @@
# Default ignored files
/shelf/
/workspace.xml
# Rider ignored files
/projectSettingsUpdater.xml
/contentModel.xml
/modules.xml
/.idea.ab-livereload.iml
# Datasource local storage ignored files
/dataSources/
/dataSources.local.xml
# Editor-based HTTP Client requests
/httpRequests/

View File

@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>

View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="CommitMessageInspectionProfile">
<profile version="1.0">
<inspection_tool class="BodyLimit" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="SubjectBodySeparation" enabled="true" level="ERROR" enabled_by_default="true" />
<inspection_tool class="SubjectLimit" enabled="true" level="ERROR" enabled_by_default="true" />
</profile>
</component>
<component name="VcsDirectoryMappings">
<mapping directory="$PROJECT_DIR$" vcs="Git" />
</component>
</project>

View File

@ -1,4 +1,4 @@
# node-livereload-tls (dockerized Livereload) # ab-livereload (dockerized Livereload)
Containerized implementation of [node-livereload](https://www.npmjs.com/package/livereload) as forked by [Brian Hogan](https://github.com/napcs) ([github repo](https://github.com/napcs/node-livereload)). This container is based on Node running on Alpine and provides for easy version-pinning and node user UID/GID changes via build args. Time zone, monitored extensions, excluded files/directories and polling delays can be set via environment variables passed at runtime. The container runs under the non-root user *'node'* over the standard livereload port *35729* for compatibility with browser addons. Containerized implementation of [node-livereload](https://www.npmjs.com/package/livereload) as forked by [Brian Hogan](https://github.com/napcs) ([github repo](https://github.com/napcs/node-livereload)). This container is based on Node running on Alpine and provides for easy version-pinning and node user UID/GID changes via build args. Time zone, monitored extensions, excluded files/directories and polling delays can be set via environment variables passed at runtime. The container runs under the non-root user *'node'* over the standard livereload port *35729* for compatibility with browser addons.

View File

@ -31,14 +31,14 @@ RUN apk --update --no-cache add \
# labels # labels
MAINTAINER Asif Bacchus <asif@asifbacchus.dev> MAINTAINER Asif Bacchus <asif@asifbacchus.dev>
LABEL maintainer="Asif Bacchus <asif@asifbacchus.dev>" LABEL maintainer="Asif Bacchus <asif@asifbacchus.dev>"
LABEL dev.asifbacchus.docker.internalName="node-livereload-tls" LABEL dev.asifbacchus.docker.internalName="ab-livereload"
LABEL org.opencontainers.image.authors="Asif Bacchus <asif@asifbacchus.dev>" LABEL org.opencontainers.image.authors="Asif Bacchus <asif@asifbacchus.dev>"
LABEL org.opencontainers.image.description="Dockerized node-livereload supporting TLS and running under limited user account. Environment variables allow specifying files to watch/exclude and notification delay." LABEL org.opencontainers.image.description="Dockerized node-livereload supporting TLS and running under limited user account. Environment variables allow specifying files to watch/exclude and notification delay."
LABEL org.opencontainers.image.documentation="https://git.asifbacchus.dev/ab-docker/livereload/raw/branch/master/README.md" LABEL org.opencontainers.image.documentation="https://git.asifbacchus.dev/ab-docker/ab-livereload/raw/branch/master/README.md"
LABEL org.opencontainers.image.source="https://git.asifbacchus.dev/ab-docker/livereload.git" LABEL org.opencontainers.image.source="https://git.asifbacchus.dev/ab-docker/ab-livereload.git"
LABEL org.opencontainers.image.title="node-livereload-tls" LABEL org.opencontainers.image.title="ab-livereload"
LABEL org.opencontainers.image.url="https://git.asifbacchus.dev/ab-docker/livereload" LABEL org.opencontainers.image.url="https://git.asifbacchus.dev/ab-docker/ab-livereload"
LABEL org.opencontainers.image.vendor="NODE.js, node-livereload" LABEL org.opencontainers.image.vendor="Asif Bacchus <asif@asifbacchus.dev>"
# default environment variables # default environment variables
ENV NODE_ENV=production ENV NODE_ENV=production
@ -56,18 +56,19 @@ ENV CERT_HOSTNAME=""
# install node-livereload and express as node user then switch back to root user # install node-livereload and express as node user then switch back to root user
USER node USER node
WORKDIR /home/node WORKDIR /home/node
COPY --chown=node:node [ "package.json", "package-lock.json", "/home/node/" ]
RUN mkdir -p .npm-global/bin .npm-global/lib \ RUN mkdir -p .npm-global/bin .npm-global/lib \
&& npm config set fund false \ && npm config set fund false \
&& npm config set update-notifier false \ && npm config set update-notifier false \
&& npm install livereload express --save && npm install --save
COPY --chown=node:node [ "ab-livereload.js", "/home/node/"]
# copy scripts and fix-up all permissions # copy scripts and fix-up all permissions
USER root USER root
COPY [ "selfsigned.cnf", "/etc/selfsigned.cnf" ] COPY [ "selfsigned.cnf", "/etc/selfsigned.cnf" ]
COPY [ "livereload.js", "/home/node/livereload.js" ]
COPY [ "entrypoint.sh", "/usr/local/bin/entrypoint.sh" ] COPY [ "entrypoint.sh", "/usr/local/bin/entrypoint.sh" ]
RUN chown node:node /home/node/livereload.js \ RUN chown node:node /home/node/* \
&& chmod 644 /home/node/livereload.js \ && chmod 644 /home/node/package* /home/node/ab-livereload.js \
&& chmod 755 /usr/local/bin/entrypoint.sh \ && chmod 755 /usr/local/bin/entrypoint.sh \
&& chmod 644 /etc/selfsigned.cnf && chmod 644 /etc/selfsigned.cnf
@ -81,7 +82,7 @@ HEALTHCHECK \
# switch to node user, run entrypoint script by default # switch to node user, run entrypoint script by default
USER node USER node
WORKDIR /home/node WORKDIR /home/node
ENTRYPOINT [ "/sbin/tini", "--", "/usr/local/bin/entrypoint.sh" ] ENTRYPOINT [ "/sbin/tini", "-e", "143", "--", "/usr/local/bin/entrypoint.sh" ]
# set build timestamp and version labels # set build timestamp and version labels
ARG INTERNAL_VERSION ARG INTERNAL_VERSION

100
build/ab-livereload.js Normal file
View File

@ -0,0 +1,100 @@
/*
Implement node-livereload over HTTP or HTTPS connection with integrated
health-check, signal handling and graceful socket shutdown.
*/
// load required modules
const livereload = require('livereload');
const fs = require('fs');
const http = require('http');
// health check object
const healthCheck = {
app: healthCheckApp(),
server: function () {
return http.createServer(this.app);
},
start: function () {
this.server().listen(3000);
},
stop: function (callback) {
this.server().close(callback());
}
};
// set LiveReload server options
const extraExclusions = process.env.LR_EXCLUDE.split(",");
extraExclusions.forEach((exclusion, idx) => {
extraExclusions[idx] = new RegExp(exclusion);
});
// noinspection SpellCheckingInspection
const lrOptions = {
port: process.env.LR_PORT,
exts: process.env.LR_EXTS,
exclusions: extraExclusions,
usePolling: true,
delay: process.env.LR_DELAY
};
if (process.env.LR_DEBUG === 'true') {
lrOptions.debug = true;
console.log("[Debug output ENABLED]");
}
if (process.env.LR_HTTPS === 'true') {
lrOptions.https = {
cert: fs.readFileSync('/certs/fullchain.pem'),
key: fs.readFileSync('/certs/privkey.pem')
};
console.log("[HTTPS mode]");
}
else {
console.log("[HTTP mode]");
}
// start LiveReload server
// noinspection JSVoidFunctionReturnValueUsed
const lrServer = livereload.createServer(lrOptions, healthCheck.start());
lrServer.watch('/watch');
// graceful termination on signals
const termSignals = {
'SIGHUP': 1,
'SIGINT': 2,
'SIGTERM': 15
};
const shutdown = async (signal, value) => {
console.log("shutting down...\n");
await lrServer.close();
await healthCheck.stop(() => {
console.log("health-check STOPPED\n");
});
console.log(`server stopped after receiving ${signal}(${value}).`);
}
// iterate signals and create listener for each
Object.keys(termSignals).forEach((signal) => {
process.on(signal, () => {
console.log("\n! received signal:", signal, " !");
shutdown(signal, termSignals[signal]).then(() => {
process.exit(128 + termSignals[signal]);
});
});
});
//
// functions
function healthCheckApp() {
const express = require('express');
const app = express();
const router = express.Router();
router.use((req, res, next) => {
res.header('Access-Control-Allow-Methods', 'GET');
next();
});
router.get('/health', (req, res) => {
res.status(200).send('Ok');
});
return app.use('/api/v1', router);
}

View File

@ -1,7 +1,7 @@
#!/bin/sh #!/bin/sh
# #
# entrypoint script for node-livereload-tls container # entrypoint script for ab-livereload container
# #
# functions # functions
@ -105,7 +105,7 @@ esac
# action: run server # action: run server
if [ "$doServer" -eq 1 ]; then if [ "$doServer" -eq 1 ]; then
printf "Starting node-livereload-tls server:\n" printf "Starting ab-livereload server:\n"
# https pre-flight check # https pre-flight check
if [ "$enableHTTPS" = "true" ]; then if [ "$enableHTTPS" = "true" ]; then
@ -130,7 +130,7 @@ if [ "$doServer" -eq 1 ]; then
;; ;;
esac esac
fi fi
exec node livereload.js exec node ab-livereload.js
exit "$?" exit "$?"
fi fi

View File

@ -1,66 +0,0 @@
// implement node-livereload over an HTTP or HTTPS connection
function healthcheck() {
const express = require('express');
const http = require('http');
const app = express();
const router = express.Router();
router.use((req, res, next) => {
res.header('Access-Control-Allow-Methods', 'GET');
next();
});
router.get('/health', (req, res) => {
res.status(200).send('Ok');
});
app.use('/api/v1', router);
const hServer = http.createServer(app);
hServer.listen(3000);
}
// load modules
const livereload = require('livereload');
const fs = require('fs');
// process from environment variable as array and convert elements to RegEx objects
const extraExclusions = process.env.LR_EXCLUDE.split(",");
extraExclusions.forEach((exclusion, idx) => {
extraExclusions[idx] = new RegExp(exclusion);
});
// set createServer options
const options = {
port: process.env.LR_PORT,
exts: process.env.LR_EXTS,
exclusions: extraExclusions,
usePolling: true,
delay: process.env.LR_DELAY
};
// set debugging output as per LR_DEBUG
if (process.env.LR_DEBUG === "true") {
options.debug = true
console.log("[Debug output ENABLED]");
}
// set HTTPS as per LR_HTTPS
if (process.env.LR_HTTPS === "true") {
options.https = {
cert: fs.readFileSync('/certs/fullchain.pem'),
key: fs.readFileSync('/certs/privkey.pem')
};
console.log("[HTTPS mode]");
}
else {
console.log("[HTTP mode]");
}
// start server
const lrServer = livereload.createServer(options, healthcheck);
lrServer.watch('/watch')
//#EOF

1208
build/package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

8
build/package.json Normal file
View File

@ -0,0 +1,8 @@
{
"name": "ab-livereload",
"version": "1.0.0",
"dependencies": {
"express": "^4.17.1",
"livereload": "^0.9.3"
}
}

View File

@ -1,5 +1,5 @@
# #
# node-livereload-tls stack # ab-livereload stack
# #
version: '2.4' version: '2.4'