Compare commits
No commits in common. "main" and "v2.3" have entirely different histories.
12
.env
12
.env
@ -1,6 +1,6 @@
|
|||||||
#
|
#
|
||||||
# Parameters for ab-livereload stack:
|
# Parameters for node-livereload-tls stack:
|
||||||
# This file makes it easier to customize your ab-livereload stack deployment by providing centralized configuration options.
|
# This file makes it easier to customize your node-livereload-tls 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.
|
||||||
|
|
||||||
@ -81,12 +81,12 @@ TLS13_ONLY=TRUE
|
|||||||
LR_EXTS="html,xml,css,js,jsx,ts,tsx,php,py"
|
LR_EXTS="html,xml,css,js,jsx,ts,tsx,php,py"
|
||||||
|
|
||||||
# LR_EXCLUDE:
|
# LR_EXCLUDE:
|
||||||
# Comma-delimited set of regular-expressions defining what to exclude from monitoring in addition to the defaults.
|
# 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/"
|
# Upstream node-livereload lists the following as defaults: "/\.git\//,/\.svn\//,/\.hg\//"
|
||||||
# REQUIRED: NO
|
# REQUIRED: NO
|
||||||
# DEFAULT: ".vscode/,.idea/,.tmp$,.swp$"
|
# DEFAULT: "/\.vscode\//,/\.idea\//,/\.tmp/,/\.swp/"
|
||||||
# VALID OPTIONS: Any valid RegEx that matches files or directories
|
# VALID OPTIONS: Any valid RegEx that matches files or directories
|
||||||
LR_EXCLUDE=".vscode/,.idea/,.tmp$,.swp$"
|
LR_EXCLUDE="/\.vscode\//,/\.idea\//,/\.tmp/,/\.swp/"
|
||||||
|
|
||||||
# LR_DELAY:
|
# 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.
|
# 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
.gitignore
vendored
3
.gitignore
vendored
@ -70,6 +70,3 @@ 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
|
|
||||||
|
13
.idea/.idea.ab-livereload.dir/.idea/.gitignore
vendored
13
.idea/.idea.ab-livereload.dir/.idea/.gitignore
vendored
@ -1,13 +0,0 @@
|
|||||||
# 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/
|
|
@ -1,20 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="GitToolBoxProjectSettings">
|
|
||||||
<option name="commitMessageIssueKeyValidationOverride">
|
|
||||||
<BoolValueOverride>
|
|
||||||
<option name="enabled" value="true" />
|
|
||||||
</BoolValueOverride>
|
|
||||||
</option>
|
|
||||||
<option name="commitMessageValidationConfigOverride">
|
|
||||||
<CommitMessageValidationOverride>
|
|
||||||
<option name="enabled" value="true" />
|
|
||||||
</CommitMessageValidationOverride>
|
|
||||||
</option>
|
|
||||||
<option name="commitMessageValidationEnabledOverride">
|
|
||||||
<BoolValueOverride>
|
|
||||||
<option name="enabled" value="true" />
|
|
||||||
</BoolValueOverride>
|
|
||||||
</option>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,8 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="UserContentModel">
|
|
||||||
<attachedFolders />
|
|
||||||
<explicitIncludes />
|
|
||||||
<explicitExcludes />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,6 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="JavaScriptLibraryMappings">
|
|
||||||
<includedPredefinedLibrary name="Node.js Core" />
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<project version="4">
|
|
||||||
<component name="MarkdownSettings">
|
|
||||||
<enabledExtensions>
|
|
||||||
<entry key="MermaidLanguageExtension" value="false" />
|
|
||||||
<entry key="PlantUMLLanguageExtension" value="false" />
|
|
||||||
</enabledExtensions>
|
|
||||||
</component>
|
|
||||||
</project>
|
|
@ -1,13 +0,0 @@
|
|||||||
<?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>
|
|
@ -1,10 +0,0 @@
|
|||||||
<?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>
|
|
@ -1,29 +0,0 @@
|
|||||||
<component name="ProjectRunConfigurationManager">
|
|
||||||
<configuration default="false" name="build/Dockerfile" type="docker-deploy" factoryName="dockerfile" server-name="Docker LOCAL">
|
|
||||||
<deployment type="dockerfile">
|
|
||||||
<settings>
|
|
||||||
<option name="imageTag" value="docker.asifbacchus.dev/ab-livereload/ab-livereload:4.0.0" />
|
|
||||||
<option name="buildArgs">
|
|
||||||
<list>
|
|
||||||
<DockerEnvVarImpl>
|
|
||||||
<option name="name" value="BUILD_DATE" />
|
|
||||||
<option name="value" value="2022-05-02" />
|
|
||||||
</DockerEnvVarImpl>
|
|
||||||
<DockerEnvVarImpl>
|
|
||||||
<option name="name" value="GIT_COMMIT" />
|
|
||||||
<option name="value" value="6970776aa8" />
|
|
||||||
</DockerEnvVarImpl>
|
|
||||||
<DockerEnvVarImpl>
|
|
||||||
<option name="name" value="INTERNAL_VERSION" />
|
|
||||||
<option name="value" value="4.0.0" />
|
|
||||||
</DockerEnvVarImpl>
|
|
||||||
</list>
|
|
||||||
</option>
|
|
||||||
<option name="buildOnly" value="true" />
|
|
||||||
<option name="sourceFilePath" value="build/Dockerfile" />
|
|
||||||
</settings>
|
|
||||||
</deployment>
|
|
||||||
<EXTENSION ID="com.jetbrains.rider.docker.debug" isFastModeEnabled="true" isPublishEnabled="true" />
|
|
||||||
<method v="2" />
|
|
||||||
</configuration>
|
|
||||||
</component>
|
|
43
LICENSE
43
LICENSE
@ -1,43 +0,0 @@
|
|||||||
AB-LIVERELOAD:
|
|
||||||
Copyright (c) 2021 Asif Bacchus <asif@asifbacchus.dev>
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
||||||
of this software and associated documentation files (the "Software"), to deal
|
|
||||||
in the Software without restriction, including without limitation the rights
|
|
||||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
||||||
copies of the Software, and to permit persons to whom the Software is
|
|
||||||
furnished to do so, subject to the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be included in all
|
|
||||||
copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
||||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
||||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
||||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
||||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
||||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
||||||
SOFTWARE.
|
|
||||||
|
|
||||||
--------------------------
|
|
||||||
NODE-LIVERELOAD:
|
|
||||||
Copyright (c) 2010-2021 Brian P. Hogan and Joshua Peek
|
|
||||||
|
|
||||||
Permission is hereby granted, free of charge, to any person obtaining
|
|
||||||
a copy of this software and associated documentation files (the
|
|
||||||
"Software"), to deal in the Software without restriction, including
|
|
||||||
without limitation the rights to use, copy, modify, merge, publish,
|
|
||||||
distribute, sublicense, and/or sell copies of the Software, and to
|
|
||||||
permit persons to whom the Software is furnished to do so, subject to
|
|
||||||
the following conditions:
|
|
||||||
|
|
||||||
The above copyright notice and this permission notice shall be
|
|
||||||
included in all copies or substantial portions of the Software.
|
|
||||||
|
|
||||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
|
||||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
|
||||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
|
||||||
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
|
||||||
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
|
||||||
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
|
||||||
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
39
README.md
39
README.md
@ -1,7 +1,14 @@
|
|||||||
# ab-livereload (dockerized Livereload)
|
# node-livereload-tls (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.
|
||||||
|
|
||||||
|
**VERSION 2.x: IMPORTANT CHANGES**
|
||||||
|
|
||||||
|
Starting with the 2.x version line, I’ve added two *very* important features:
|
||||||
|
|
||||||
|
- SSL/TLS support with auto-generated self-signed certificates if you don’t have your own certificates
|
||||||
|
- Healthcheck allowing for proper integration using docker-compose into a webstack
|
||||||
|
|
||||||
**Please note:** This container only generates notifications for livereload clients. It does NOT contain a webserver! Please see [Examples](#examples) and [Docker-Compose](#docker-compose) for how to add this to your webdev-stack.
|
**Please note:** This container only generates notifications for livereload clients. It does NOT contain a webserver! Please see [Examples](#examples) and [Docker-Compose](#docker-compose) for how to add this to your webdev-stack.
|
||||||
|
|
||||||
## Contents
|
## Contents
|
||||||
@ -25,14 +32,13 @@ ## Contents
|
|||||||
* [Option 2: specify runtime GID](#option-2-specify-runtime-gid)
|
* [Option 2: specify runtime GID](#option-2-specify-runtime-gid)
|
||||||
* [Using Let’s Encrypt](#using-lets-encrypt)
|
* [Using Let’s Encrypt](#using-lets-encrypt)
|
||||||
- [Docker-Compose](#docker-compose)
|
- [Docker-Compose](#docker-compose)
|
||||||
- [Brief changelog](#brief-changelog)
|
|
||||||
- [Final thoughts](#final-thoughts)
|
- [Final thoughts](#final-thoughts)
|
||||||
|
|
||||||
<!-- tocstop -->
|
<!-- tocstop -->
|
||||||
|
|
||||||
## Private docker repository
|
## Private docker repository
|
||||||
|
|
||||||
If you prefer, you can also use my private repository to download possibly newer containers. Simply change `asifbacchus/livereload:tag` to `docker.asifbacchus.dev/ab-livereload/ab-livereload:tag`.
|
If you prefer, you can also use my private repository to download possibly newer containers. Simply change `asifbacchus/livereload:tag` to `docker.asifbacchus.dev/livereload/livereload:tag`.
|
||||||
|
|
||||||
## Source/Issues
|
## Source/Issues
|
||||||
|
|
||||||
@ -43,11 +49,11 @@ ## Environment variables
|
|||||||
All environment variables have sensible defaults and, thus, are *not* required to be set for the container to run successfully.
|
All environment variables have sensible defaults and, thus, are *not* required to be set for the container to run successfully.
|
||||||
|
|
||||||
| variable | description | default |
|
| variable | description | default |
|
||||||
|---------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|-------------------------------------------------------------------------------------------|
|
| ------------- | ------------------------------------------------------------ | ------------------------------------------------------------ |
|
||||||
| TZ | Set the container's time zone. NO impact on runtime, included for convenience. | Etc/UTC |
|
| 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_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_EXTS | Defines monitored extensions. | html,xml,css,js,jsx,ts,tsx,php,py |
|
||||||
| 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_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. I’ve filed an issue upstream and will update the container when it’s resolved. | /\\.vscode//,/\\.idea//,/\\.tmp/,/\\.swp/ |
|
||||||
| LR_DELAY | Time (ms) between polling for changed files. | 500 |
|
| 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_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 |
|
| LR_HTTPS | Use HTTPS and WSS. In other words, use a certificate for SSL/TLS operation. | true |
|
||||||
@ -72,14 +78,12 @@ ### Content mount
|
|||||||
|
|
||||||
Obviously, this container needs something to monitor to determine whether changes have been made. This is accomplished via bind-mounting a directory from the host and is why 'polling' is necessary. Mount a directory with files to be monitored to */watch* in the container.
|
Obviously, this container needs something to monitor to determine whether changes have been made. This is accomplished via bind-mounting a directory from the host and is why 'polling' is necessary. Mount a directory with files to be monitored to */watch* in the container.
|
||||||
|
|
||||||
> Starting with v4.0.0 you can watch up to 5 directories! Simply mount them to `/watch`, `/watch2` ... `/watch5'.
|
|
||||||
|
|
||||||
## Commands
|
## Commands
|
||||||
|
|
||||||
The container’s entrypoint script recognizes a few commands that tell it what you want to do:
|
The container’s entrypoint script recognizes a few commands that tell it what you want to do:
|
||||||
|
|
||||||
| command | description |
|
| command | description |
|
||||||
|-----------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
|
| --------- | ------------------------------------------------------------ |
|
||||||
| listen | Activate Livereload server using configured parameters.<br />Aliases: run \| server \| start<br />`docker run --rm ... asifbacchus/livereload listen` |
|
| listen | Activate Livereload server using configured parameters.<br />Aliases: run \| server \| start<br />`docker run --rm ... asifbacchus/livereload listen` |
|
||||||
| shell | Start container but drop to an Ash shell. Alternatvely, if you supply a command, the container will run that command in the shell, output results and then exit.<br />`docker run -it --rm ... asifbacchus/livereload shell`<br />`docker run --rm ... asifbacchus/livereload shell ls -lAsh /certs` |
|
| shell | Start container but drop to an Ash shell. Alternatvely, if you supply a command, the container will run that command in the shell, output results and then exit.<br />`docker run -it --rm ... asifbacchus/livereload shell`<br />`docker run --rm ... asifbacchus/livereload shell ls -lAsh /certs` |
|
||||||
| new-cert | Generate a new self-signed certificate with CN=CERT_HOSTNAME and matching DNS.1 value. Certificate and private key will be stored in */certs* as *fullchain.pem* and *privkey.pem*, respectively.<br />I strongly suggest running the container with `--user "uid:gid"` where the *gid* corresponds to one matching your webserver user, for example. That way your webserver would have read access to the generated private key. More information in the [Permissions](#permissions) section.<br />For example, running `docker run --rm -u "9999:6001" -v /etc/mycerts:/certs -e CERT_HOSTNAME=sub.domain.tld asifbacchus/livereload new-cert` would generate a new certificate and key pair in the */etc/mycerts/* directory on the host. Importantly, the private key would be readable by GID 6001 which, in this example, might be your webdev programs group including your webserver and you as the web-dev. |
|
| new-cert | Generate a new self-signed certificate with CN=CERT_HOSTNAME and matching DNS.1 value. Certificate and private key will be stored in */certs* as *fullchain.pem* and *privkey.pem*, respectively.<br />I strongly suggest running the container with `--user "uid:gid"` where the *gid* corresponds to one matching your webserver user, for example. That way your webserver would have read access to the generated private key. More information in the [Permissions](#permissions) section.<br />For example, running `docker run --rm -u "9999:6001" -v /etc/mycerts:/certs -e CERT_HOSTNAME=sub.domain.tld asifbacchus/livereload new-cert` would generate a new certificate and key pair in the */etc/mycerts/* directory on the host. Importantly, the private key would be readable by GID 6001 which, in this example, might be your webdev programs group including your webserver and you as the web-dev. |
|
||||||
@ -99,8 +103,6 @@ ### Run in HTTP (unsecured) mode
|
|||||||
- `-p 35729:35729`: map on all interfaces port 35729 on the host --> port 35729 in container
|
- `-p 35729:35729`: map on all interfaces port 35729 on the host --> port 35729 in container
|
||||||
- `listen`: start the Livereload server
|
- `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
|
### Run in HTTPS mode with supplied certificate
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
@ -139,7 +141,6 @@ ## Livereload client
|
|||||||
If you are running in an HTTP-permissive environment then lucky you! You can run this container in HTTP mode (`LR_HTTPS=false`) and use any of the clients and addons out there. If you want to use a snippet in your code instead of a client, simply insert this in the `<head>` of your page while using Livereload during dev:
|
If you are running in an HTTP-permissive environment then lucky you! You can run this container in HTTP mode (`LR_HTTPS=false`) and use any of the clients and addons out there. If you want to use a snippet in your code instead of a client, simply insert this in the `<head>` of your page while using Livereload during dev:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] +
|
document.write('<script src="http://' + (location.host || 'localhost').split(':')[0] +
|
||||||
':35729/livereload.js?snipver=1"></' + 'script>')
|
':35729/livereload.js?snipver=1"></' + 'script>')
|
||||||
@ -149,7 +150,6 @@ ## Livereload client
|
|||||||
If, however, you are like me and want/need to use HTTPS then things are a little different. As I said, I can’t find a single client or addon that works over HTTPS. Therefore, you *must* use a snippet in your webpage. It’s the exact same as above, just use HTTPS instead -- again inserting in the `<head>` of your page:
|
If, however, you are like me and want/need to use HTTPS then things are a little different. As I said, I can’t find a single client or addon that works over HTTPS. Therefore, you *must* use a snippet in your webpage. It’s the exact same as above, just use HTTPS instead -- again inserting in the `<head>` of your page:
|
||||||
|
|
||||||
```html
|
```html
|
||||||
|
|
||||||
<script>
|
<script>
|
||||||
document.write('<script src="https://' + (location.host || 'localhost').split(':')[0] +
|
document.write('<script src="https://' + (location.host || 'localhost').split(':')[0] +
|
||||||
':35729/livereload.js?snipver=1"></' + 'script>')
|
':35729/livereload.js?snipver=1"></' + 'script>')
|
||||||
@ -230,21 +230,6 @@ ## Docker-Compose
|
|||||||
|
|
||||||
Containers, like people, often get lonely and enjoy working with others. In the case of this container, it is quite useless if not paired with at least a web server. I’ve included the core of the actual set up I use for web development -- a customized NGINX container and this Livereload container all secured with a certificate so everything even in testing is working over TLS like in real life. Take a look at the *docker-compose.yml* for more details. If you’re using Let’s Encrypt certificates, read the section above and remember to mount the files individually. If you are interested in my AB-NGINX container which has several useful additions to the official container including a healthcheck, then [check out the repo](https://git.asifbacchus.dev/ab-docker/ab-nginx).
|
Containers, like people, often get lonely and enjoy working with others. In the case of this container, it is quite useless if not paired with at least a web server. I’ve included the core of the actual set up I use for web development -- a customized NGINX container and this Livereload container all secured with a certificate so everything even in testing is working over TLS like in real life. Take a look at the *docker-compose.yml* for more details. If you’re using Let’s Encrypt certificates, read the section above and remember to mount the files individually. If you are interested in my AB-NGINX container which has several useful additions to the official container including a healthcheck, then [check out the repo](https://git.asifbacchus.dev/ab-docker/ab-nginx).
|
||||||
|
|
||||||
## Brief changelog
|
|
||||||
|
|
||||||
### Version 3.0.0
|
|
||||||
|
|
||||||
- `npm` no longer present in final build, too many un-patched security vulnerabilities.
|
|
||||||
- multi-stage build with the final image being a minimal node installation directly on the Alpine base.
|
|
||||||
- container is now ~50% smaller due to multi-stage build :-)
|
|
||||||
|
|
||||||
### Version 2.x
|
|
||||||
|
|
||||||
Starting with the 2.x version line, I’ve added two *very* important features:
|
|
||||||
|
|
||||||
- SSL/TLS support with auto-generated self-signed certificates if you don’t have your own certificates
|
|
||||||
- Healthcheck allowing for proper integration using docker-compose into a webstack
|
|
||||||
|
|
||||||
## Final thoughts
|
## Final thoughts
|
||||||
|
|
||||||
That's it. Hopefully this is useful for you and makes it easier to run a live-reload server without having to install node on your machine. As always, let me know if you have any issues/suggestions or if something isn’t well documented by filing an issue on either git repo.
|
That's it. Hopefully this is useful for you and makes it easier to run a live-reload server without having to install node on your machine. As always, let me know if you have any issues/suggestions or if something isn’t well documented by filing an issue on either git repo.
|
||||||
|
@ -2,73 +2,65 @@
|
|||||||
|
|
||||||
# allow dynamic building by specifying base image elements as build-args
|
# allow dynamic building by specifying base image elements as build-args
|
||||||
ARG NODE_VERSION=16
|
ARG NODE_VERSION=16
|
||||||
ARG ALPINE_VERSION=3.15
|
ARG ALPINE_VERSION=3.14
|
||||||
FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION} as builder
|
FROM node:${NODE_VERSION}-alpine${ALPINE_VERSION}
|
||||||
ARG NODE_VERSION
|
|
||||||
ARG ALPINE_VERSION
|
|
||||||
|
|
||||||
# install node dependences
|
|
||||||
WORKDIR /build
|
|
||||||
COPY [ "package.json", "package-lock.json", "./" ]
|
|
||||||
RUN npm ci --production
|
|
||||||
|
|
||||||
# final container
|
|
||||||
FROM alpine:${ALPINE_VERSION} as final
|
|
||||||
ARG NODE_VERSION
|
|
||||||
ARG ALPINE_VERSION
|
|
||||||
|
|
||||||
# create new node user with set UID and GID from build-args and create volume directories
|
# create new node user with set UID and GID from build-args and create volume directories
|
||||||
ARG NODE_UID=9999
|
ARG NODE_UID=9999
|
||||||
ARG NODE_GID=9999
|
ARG NODE_GID=9999
|
||||||
RUN addgroup -g ${NODE_GID} -S node \
|
RUN deluser --remove-home node \
|
||||||
|
&& addgroup -g ${NODE_GID} -S node \
|
||||||
&& adduser -G node -S -u ${NODE_UID} node \
|
&& adduser -G node -S -u ${NODE_UID} node \
|
||||||
&& mkdir /watch /watch2 /watch3 /watch4 /watch5 /certs \
|
&& mkdir /watch /certs \
|
||||||
&& chown root:node /certs \
|
&& chown root:node /certs \
|
||||||
&& chmod 770 /certs
|
&& chmod 770 /certs
|
||||||
|
|
||||||
# create default volumes in case user forgets, expose default port
|
# create default volumes in-case user forgets, expose default port
|
||||||
VOLUME [ "/watch", "/certs" ]
|
VOLUME [ "/watch", "/certs" ]
|
||||||
EXPOSE 35729
|
EXPOSE 35729
|
||||||
|
|
||||||
# add tini, timezone support, nodejs and create certificate directories
|
# add tini, timezone support and create certificate directories
|
||||||
RUN apk --update --no-cache add \
|
RUN apk --update --no-cache add \
|
||||||
tini \
|
tini \
|
||||||
tzdata \
|
tzdata \
|
||||||
openssl \
|
openssl
|
||||||
nodejs~${NODE_VERSION} \
|
|
||||||
&& apk --update --no-cache upgrade
|
|
||||||
|
|
||||||
# labels
|
# 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.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.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/ab-livereload/raw/branch/main/README.md"
|
LABEL org.opencontainers.image.url="https://git.asifbacchus.dev/ab-docker/livereload"
|
||||||
LABEL org.opencontainers.image.source="https://git.asifbacchus.dev/ab-docker/ab-livereload.git"
|
LABEL org.opencontainers.image.documentation="https://git.asifbacchus.dev/ab-docker/livereload/raw/branch/master/README.md"
|
||||||
LABEL org.opencontainers.image.title="ab-livereload"
|
LABEL org.opencontainers.image.source="https://git.asifbacchus.dev/ab-docker/livereload.git"
|
||||||
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
|
# default environment variables
|
||||||
ENV NODE_ENV=production
|
ENV NODE_ENV=production
|
||||||
|
ENV NPM_CONFIG_PREFIX=/home/node/.npm-global
|
||||||
|
ENV PATH=/home/node/.npm-global/bin:$PATH
|
||||||
ENV TZ="Etc/UTC"
|
ENV TZ="Etc/UTC"
|
||||||
ENV LR_PORT=35729
|
ENV LR_PORT=35729
|
||||||
ENV LR_EXTS="html,xml,css,js,jsx,ts,tsx,php,py"
|
ENV LR_EXTS="html,xml,css,js,jsx,ts,tsx,php,py"
|
||||||
ENV LR_EXCLUDE=".vscode/,.idea/,.tmp$,.swp$"
|
ENV LR_EXCLUDE=".git/,.svn/,.vscode/,.idea/"
|
||||||
ENV LR_DELAY=500
|
ENV LR_DELAY=500
|
||||||
ENV LR_DEBUG=true
|
ENV LR_DEBUG=true
|
||||||
ENV LR_HTTPS=true
|
ENV LR_HTTPS=true
|
||||||
ENV CERT_HOSTNAME=""
|
ENV CERT_HOSTNAME=""
|
||||||
|
|
||||||
# set-up application and copy dependencies from builder
|
# install node-livereload and express as node user then switch back to root user
|
||||||
|
USER node
|
||||||
WORKDIR /home/node
|
WORKDIR /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
|
||||||
|
|
||||||
|
# copy scripts and fix-up all permissions
|
||||||
|
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" ]
|
||||||
COPY --chown=node:node [ "ab-livereload.js", "/home/node/"]
|
RUN chown node:node /home/node/livereload.js \
|
||||||
COPY --from=builder [ "/build/node_modules", "/home/node/node_modules" ]
|
&& chmod 644 /home/node/livereload.js \
|
||||||
RUN chown -R node:node /home/node/* \
|
|
||||||
&& chmod 644 /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
|
||||||
|
|
||||||
@ -82,15 +74,15 @@ 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", "-e", "143", "--", "/usr/local/bin/entrypoint.sh" ]
|
ENTRYPOINT [ "/sbin/tini", "--", "/usr/local/bin/entrypoint.sh" ]
|
||||||
|
|
||||||
# set build timestamp and version labels
|
# set build timestamp and version labels
|
||||||
ARG INTERNAL_VERSION
|
ARG INTERNAL_VERSION
|
||||||
ARG GIT_COMMIT
|
|
||||||
ARG BUILD_DATE
|
ARG BUILD_DATE
|
||||||
LABEL org.opencontainers.image.version="NODE=${NODE_VERSION}, node-livereload=0.9.3"
|
LABEL org.opencontainers.image.version="16.5.0, 0.9.3"
|
||||||
LABEL dev.asifbacchus.docker.internalVersion=${INTERNAL_VERSION}
|
LABEL org.opencontainers.image.vendor="NODE.js, node-livereload"
|
||||||
LABEL org.opencontainers.image.revision=${GIT_COMMIT}
|
LABEL dev.asifbacchus.image.name="node-livereload-tls"
|
||||||
|
LABEL dev.asifbacchus.image.version=${INTERNAL_VERSION}
|
||||||
LABEL org.opencontainers.image.created=${BUILD_DATE}
|
LABEL org.opencontainers.image.created=${BUILD_DATE}
|
||||||
|
|
||||||
#EOF
|
#EOF
|
||||||
|
@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
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', '/watch2', '/watch3', '/watch4', '/watch5']);
|
|
||||||
|
|
||||||
// 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);
|
|
||||||
}
|
|
@ -1,7 +1,7 @@
|
|||||||
#!/bin/sh
|
#!/bin/sh
|
||||||
|
|
||||||
#
|
#
|
||||||
# entrypoint script for ab-livereload container
|
# entrypoint script for node-livereload-tls 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 ab-livereload server:\n"
|
printf "Starting node-livereload-tls 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 ab-livereload.js
|
exec node livereload.js
|
||||||
exit "$?"
|
exit "$?"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
61
build/livereload.js
Normal file
61
build/livereload.js
Normal file
@ -0,0 +1,61 @@
|
|||||||
|
// 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
build/package-lock.json
generated
1208
build/package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@ -1,8 +0,0 @@
|
|||||||
{
|
|
||||||
"name": "ab-livereload",
|
|
||||||
"version": "3.0.0",
|
|
||||||
"dependencies": {
|
|
||||||
"express": "^4.17.1",
|
|
||||||
"livereload": "^0.9.3"
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,5 +1,5 @@
|
|||||||
#
|
#
|
||||||
# ab-livereload stack
|
# node-livereload-tls stack
|
||||||
#
|
#
|
||||||
|
|
||||||
version: '2.4'
|
version: '2.4'
|
||||||
|
Loading…
Reference in New Issue
Block a user