11 Commits

Author SHA1 Message Date
asif 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
asif 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
asif 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
asif 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
asif c0a4fc1c6c fix(env): update env file to match new exclusion defaults 2021-07-29 22:53:51 -06:00
asif cad203a7c0 fix(dockerfile): reorganize and add new labels
- add deprecated maintainer tag and label
- fix internal label names
- add git commit label
- reorganize labels
2021-07-28 04:41:28 -06:00
asif 8cafe6e164 fix readme formatting error 2021-07-28 04:24:42 -06:00
asif 99cc14532c docs(readme): update readme to reflect fixed exclusions 2021-07-28 04:20:50 -06:00
asif 13ec1a72e9 style(livereload): format code 2021-07-28 04:12:19 -06:00
asif 1194fc63c6 fix(livereload): fix exclusions bug
- read environment var as array
- convert array elements to regex objects
- update environment variable defaults
2021-07-28 03:51:56 -06:00
asif 574b6e1e07 refactor(dockerfile): update existing packages to latest versions 2021-07-28 03:50:03 -06:00
15 changed files with 1408 additions and 90 deletions
+6 -6
View File
@@ -1,6 +1,6 @@
#
# Parameters for node-livereload-tls stack:
# This file makes it easier to customize your node-livereload-tls stack deployment by providing centralized configuration options.
# Parameters for ab-livereload stack:
# 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.
# There is *no* sensitive information in this file.
@@ -81,12 +81,12 @@ TLS13_ONLY=TRUE
LR_EXTS="html,xml,css,js,jsx,ts,tsx,php,py"
# LR_EXCLUDE:
# Comma-delimited set of /regular-expressions/ defining what to exclude from monitoring in addition to the defaults.
# Upstream node-livereload lists the following as defaults: "/\.git\//,/\.svn\//,/\.hg\//"
# Comma-delimited set of regular-expressions defining what to exclude from monitoring in addition to the defaults.
# Upstream node-livereload already ignores: ".git/,.svn/,.hg/"
# REQUIRED: NO
# DEFAULT: "/\.vscode\//,/\.idea\//,/\.tmp/,/\.swp/"
# DEFAULT: ".vscode/,.idea/,.tmp$,.swp$"
# VALID OPTIONS: Any valid RegEx that matches files or directories
LR_EXCLUDE="/\.vscode\//,/\.idea\//,/\.tmp/,/\.swp/"
LR_EXCLUDE=".vscode/,.idea/,.tmp$,.swp$"
# LR_DELAY:
# Amount of time in milliseconds before detecting a change and sending a trigger for a browser reload. Useful if you need to allow time for background recompilation, etc.
+3
View File
@@ -70,3 +70,6 @@ fabric.properties
# Android studio 3.1+ serialized cache file
.idea/caches/build_file_checksums.ser
# node modules
build/node_modules
+13
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/
+8
View File
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="UserContentModel">
<attachedFolders />
<explicitIncludes />
<explicitExcludes />
</component>
</project>
@@ -0,0 +1,6 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="JavaScriptLibraryMappings">
<includedPredefinedLibrary name="Node.js Core" />
</component>
</project>
+13
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>
+10
View File
@@ -0,0 +1,10 @@
<?xml version="1.0" encoding="UTF-8"?>
<project version="4">
<component name="GitToolBoxProjectSettings">
<option name="commitMessageValidationOverride">
<BoolValueOverride>
<option name="value" value="true" />
</BoolValueOverride>
</option>
</component>
</project>
+4 -2
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.
@@ -53,7 +53,7 @@ All environment variables have sensible defaults and, thus, are *not* required t
| TZ | Set the container's time zone. NO impact on runtime, included for convenience. | Etc/UTC |
| LR_PORT | Port over which Livereload will communicate. All clients presently expect port 35729, so I suggest leaving this alone. | 35729 |
| LR_EXTS | Defines monitored extensions. | html,xml,css,js,jsx,ts,tsx,php,py |
| LR_EXCLUDE | Array of JavaScript regular-expressions (Regex) that define paths or files to ignore. These are *appended* to the node-livereload upstream defaults which ignore everything in the `.git/`, `.svn/` and `.hg/` directories.<br />JavaScript regex format is: `/your-regex/`<br />**N.B.** At present, exclusions do not seem to be working properly. Ive filed an issue upstream and will update the container when its resolved. | /\\.vscode//,/\\.idea//,/\\.tmp/,/\\.swp/ |
| LR_EXCLUDE | Comma-delimited regular-expressions (Regex) that define paths or files to ignore. These are *appended* to the node-livereload upstream defaults which ignore everything in the `.git/`, `.svn/` and `.hg/` directories.<br />**N.B.** You do *not* have to use JavaScript format. The script will automatically convert things to JS-RegEx. You do, however, need to escape any special characters. | .vscode/,.idea/,.tmp$,.swp$/ |
| LR_DELAY | Time (ms) between polling for changed files. | 500 |
| LR_DEBUG | Print informational messages to the console. Allows you to see Livereload working. | true |
| LR_HTTPS | Use HTTPS and WSS. In other words, use a certificate for SSL/TLS operation. | true |
@@ -103,6 +103,8 @@ docker run -d --rm -v /var/www:/watch:ro -e LR_HTTPS=false -p 35729:35729 asifba
- `-p 35729:35729`: map on all interfaces port 35729 on the host --> port 35729 in container
- `listen`: start the Livereload server
> Depending on your environment, you may *not* want to expose your Livereload server on all interfaces! You may want to map your port to something like `127.0.0.1:35729:35729` and then establishing an SSH-tunnel from your client. This is completely dependent on your environment and beyond the scope of this readme, sorry.
### Run in HTTPS mode with supplied certificate
```bash
+25 -17
View File
@@ -4,6 +4,8 @@
ARG NODE_VERSION=16
ARG ALPINE_VERSION=3.14
FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION}
ARG NODE_VERSION
ARG ALPINE_VERSION
# create new node user with set UID and GID from build-args and create volume directories
ARG NODE_UID=9999
@@ -21,17 +23,22 @@ EXPOSE 35729
# add tini, timezone support and create certificate directories
RUN apk --update --no-cache add \
tini \
tzdata \
openssl
tini \
tzdata \
openssl \
&& apk --update --no-cache upgrade
# labels
MAINTAINER Asif Bacchus <asif@asifbacchus.dev>
LABEL maintainer="Asif Bacchus <asif@asifbacchus.dev>"
LABEL dev.asifbacchus.docker.internalName="ab-livereload"
LABEL org.opencontainers.image.authors="Asif Bacchus <asif@asifbacchus.dev>"
LABEL org.opencontainers.image.title="node-livereload-tls"
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.url="https://git.asifbacchus.dev/ab-docker/livereload"
LABEL org.opencontainers.image.documentation="https://git.asifbacchus.dev/ab-docker/livereload/raw/branch/master/README.md"
LABEL org.opencontainers.image.source="https://git.asifbacchus.dev/ab-docker/livereload.git"
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/ab-livereload.git"
LABEL org.opencontainers.image.title="ab-livereload"
LABEL org.opencontainers.image.url="https://git.asifbacchus.dev/ab-docker/ab-livereload"
LABEL org.opencontainers.image.vendor="Asif Bacchus <asif@asifbacchus.dev>"
# default environment variables
ENV NODE_ENV=production
@@ -40,7 +47,7 @@ ENV PATH=/home/node/.npm-global/bin:$PATH
ENV TZ="Etc/UTC"
ENV LR_PORT=35729
ENV LR_EXTS="html,xml,css,js,jsx,ts,tsx,php,py"
ENV LR_EXCLUDE=".git/,.svn/,.vscode/,.idea/"
ENV LR_EXCLUDE=".vscode/,.idea/,.tmp$,.swp$"
ENV LR_DELAY=500
ENV LR_DEBUG=true
ENV LR_HTTPS=true
@@ -49,18 +56,19 @@ ENV CERT_HOSTNAME=""
# install node-livereload and express as node user then switch back to root user
USER node
WORKDIR /home/node
COPY --chown=node:node [ "package.json", "package-lock.json", "/home/node/" ]
RUN mkdir -p .npm-global/bin .npm-global/lib \
&& npm config set fund 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
USER root
COPY [ "selfsigned.cnf", "/etc/selfsigned.cnf" ]
COPY [ "livereload.js", "/home/node/livereload.js" ]
COPY [ "entrypoint.sh", "/usr/local/bin/entrypoint.sh" ]
RUN chown node:node /home/node/livereload.js \
&& chmod 644 /home/node/livereload.js \
RUN chown node:node /home/node/* \
&& chmod 644 /home/node/package* /home/node/ab-livereload.js \
&& chmod 755 /usr/local/bin/entrypoint.sh \
&& chmod 644 /etc/selfsigned.cnf
@@ -74,15 +82,15 @@ HEALTHCHECK \
# switch to node user, run entrypoint script by default
USER 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
ARG INTERNAL_VERSION
ARG GIT_COMMIT
ARG BUILD_DATE
LABEL org.opencontainers.image.version="16.5.0, 0.9.3"
LABEL org.opencontainers.image.vendor="NODE.js, node-livereload"
LABEL dev.asifbacchus.image.name="node-livereload-tls"
LABEL dev.asifbacchus.image.version=${INTERNAL_VERSION}
LABEL org.opencontainers.image.version="NODE=${NODE_VERSION}, node-livereload=0.9.3"
LABEL dev.asifbacchus.docker.internalVersion=${INTERNAL_VERSION}
LABEL org.opencontainers.image.revision=${GIT_COMMIT}
LABEL org.opencontainers.image.created=${BUILD_DATE}
#EOF
+100
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);
}
+3 -3
View File
@@ -1,7 +1,7 @@
#!/bin/sh
#
# entrypoint script for node-livereload-tls container
# entrypoint script for ab-livereload container
#
# functions
@@ -105,7 +105,7 @@ esac
# action: run server
if [ "$doServer" -eq 1 ]; then
printf "Starting node-livereload-tls server:\n"
printf "Starting ab-livereload server:\n"
# https pre-flight check
if [ "$enableHTTPS" = "true" ]; then
@@ -130,7 +130,7 @@ if [ "$doServer" -eq 1 ]; then
;;
esac
fi
exec node livereload.js
exec node ab-livereload.js
exit "$?"
fi
-61
View File
@@ -1,61 +0,0 @@
// implement node-livereload over an HTTPS connection
// healthcheck function
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 livereload module
const livereload = require('livereload');
// set createServer options
const fs = require('fs');
const options = {
port: process.env.LR_PORT,
exts: process.env.LR_EXTS,
exclusions: process.env.LR_EXCLUDE,
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
View File
File diff suppressed because it is too large Load Diff
+8
View File
@@ -0,0 +1,8 @@
{
"name": "ab-livereload",
"version": "1.0.0",
"dependencies": {
"express": "^4.17.1",
"livereload": "^0.9.3"
}
}
+1 -1
View File
@@ -1,5 +1,5 @@
#
# node-livereload-tls stack
# ab-livereload stack
#
version: '2.4'