Configurable website in Docker
This commit is contained in:
commit
e6cd7a0f6d
2
.dockerignore
Normal file
2
.dockerignore
Normal file
@ -0,0 +1,2 @@
|
|||||||
|
node_modules
|
||||||
|
npm-debug.log
|
17
Dockerfile
Normal file
17
Dockerfile
Normal file
@ -0,0 +1,17 @@
|
|||||||
|
# Based on node
|
||||||
|
FROM node:13-alpine
|
||||||
|
|
||||||
|
RUN apk add git
|
||||||
|
|
||||||
|
# Create app directory
|
||||||
|
WORKDIR /usr/src/app
|
||||||
|
|
||||||
|
# Install app dependencies
|
||||||
|
RUN git clone https://git.heshapps.com/asolkar/mma-website.git .
|
||||||
|
|
||||||
|
RUN npm install
|
||||||
|
RUN npm ci --only=production
|
||||||
|
|
||||||
|
EXPOSE 3000
|
||||||
|
CMD ["node", "website.js"]
|
||||||
|
|
54
README.md
Normal file
54
README.md
Normal file
@ -0,0 +1,54 @@
|
|||||||
|
# Build docker image
|
||||||
|
|
||||||
|
% cd <app source directory>
|
||||||
|
% docker build --tag mahesh/mma-website --no-cache .
|
||||||
|
|
||||||
|
*Note*: If `--no-cache` is not used, cloning of git repo from the docker file does not work in subsequent builds
|
||||||
|
|
||||||
|
# Run docker container
|
||||||
|
|
||||||
|
% docker run --publish 49330:3000 --detach mahesh/mma-website
|
||||||
|
7e4dfed65d776e3c8cd8e5c6e970699b561bbbc6f2d63d5d75b7ee68c9672358
|
||||||
|
|
||||||
|
# Get a shell in running container
|
||||||
|
|
||||||
|
% docker exec --interactive --tty 7e4dfed65d776e3c8cd8e5c6e970699b561bbbc6f2d63d5d75b7ee68c9672358 /bin/bash
|
||||||
|
|
||||||
|
# Manage docker containers
|
||||||
|
|
||||||
|
* List running containers
|
||||||
|
|
||||||
|
```
|
||||||
|
% docker ps
|
||||||
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
|
d511b20c73d6 mahesh/mma-website "docker-entrypoint.s…" 8 minutes ago Up 8 minutes 0.0.0.0:49330->3000/tcp upbeat_lederberg
|
||||||
|
```
|
||||||
|
|
||||||
|
* List all docker containrs
|
||||||
|
|
||||||
|
```
|
||||||
|
% docker ps --all
|
||||||
|
CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES
|
||||||
|
d511b20c73d6 mahesh/mma-website "docker-entrypoint.s…" 12 minutes ago Exited (137) 3 minutes ago upbeat_lederberg
|
||||||
|
% docker ps --all --quiet
|
||||||
|
d511b20c73d6
|
||||||
|
```
|
||||||
|
|
||||||
|
* Stop a running container
|
||||||
|
|
||||||
|
```
|
||||||
|
% docker stop d511b20c73d6
|
||||||
|
```
|
||||||
|
|
||||||
|
* Remove a container
|
||||||
|
|
||||||
|
```
|
||||||
|
% docker rm d511b20c73d6
|
||||||
|
```
|
||||||
|
|
||||||
|
# Local debug
|
||||||
|
|
||||||
|
```
|
||||||
|
% SITE_NAME="asolkar.net" SITE_URL="https://asolkar.net" SITE_TITLE="Home of the Asolkars ..." node website.js
|
||||||
|
Server running at http://0.0.0.0:3000/
|
||||||
|
```
|
10
package.json
Normal file
10
package.json
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
{
|
||||||
|
"name": "mma_website_docker",
|
||||||
|
"version": "0.1",
|
||||||
|
"description": "Generic Website",
|
||||||
|
"author": "Mahesh Asolkar <mahesh@mahesha.com>",
|
||||||
|
"main": "website.js",
|
||||||
|
"scripts": {
|
||||||
|
"start": "node website.js"
|
||||||
|
}
|
||||||
|
}
|
48
siteinfo.js
Normal file
48
siteinfo.js
Normal file
@ -0,0 +1,48 @@
|
|||||||
|
// Exported functions
|
||||||
|
module.exports = {
|
||||||
|
site_info: function (req) {
|
||||||
|
|
||||||
|
var ret = {
|
||||||
|
"site_name": "Website Template",
|
||||||
|
"site_url": "https://website.template",
|
||||||
|
"site_title": "Title of website",
|
||||||
|
};
|
||||||
|
|
||||||
|
if ("SITE_NAME" in process.env) {
|
||||||
|
ret.name = process.env.SITE_NAME;
|
||||||
|
}
|
||||||
|
if ("SITE_URL" in process.env) {
|
||||||
|
ret.url = process.env.SITE_URL;
|
||||||
|
}
|
||||||
|
if ("SITE_TITLE" in process.env) {
|
||||||
|
ret.title = process.env.SITE_TITLE;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
},
|
||||||
|
site_ga_stub: function (req) {
|
||||||
|
// Tracking disabled by DNT
|
||||||
|
if (("dnt" in req.headers) && (req.headers["dnt"] == 1)) {
|
||||||
|
return `<!-- DNT - Tracking disabled -->`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Google Analytics stub
|
||||||
|
if ("SITE_GA_ID" in process.env) {
|
||||||
|
return `
|
||||||
|
<!-- Google Analytics stuff -->
|
||||||
|
<script type="text/javascript">
|
||||||
|
var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
|
||||||
|
document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
|
||||||
|
</script>
|
||||||
|
<script type="text/javascript">
|
||||||
|
try {
|
||||||
|
var pageTracker = _gat._getTracker("${process.env.SITE_GA_ID}");
|
||||||
|
pageTracker._trackPageview();
|
||||||
|
} catch(err) {}</script>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Default - no tracking information provided
|
||||||
|
return "<!-- No GA Tracking -->";
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
294
website.js
Normal file
294
website.js
Normal file
@ -0,0 +1,294 @@
|
|||||||
|
'use strict';
|
||||||
|
|
||||||
|
const http = require('http');
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
const hostname = '0.0.0.0';
|
||||||
|
const port = 3000;
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
var siteinfo = require('./siteinfo.js');
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
function getPage(req) {
|
||||||
|
var route = req.url.substring(1);
|
||||||
|
var website = siteinfo.site_info(req);
|
||||||
|
var ga_tracking_stub = siteinfo.site_ga_stub(req);
|
||||||
|
|
||||||
|
console.log(`Serving route ${route}`);
|
||||||
|
|
||||||
|
return `<!DOCTYPE HTML PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
||||||
|
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"><head>
|
||||||
|
<title>${website.title}</title>
|
||||||
|
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
|
||||||
|
<meta name="description" content="${website.title}">
|
||||||
|
<meta name="keywords" content="">
|
||||||
|
|
||||||
|
<!-- Mobile stylesheet -->
|
||||||
|
<style type="text/css" media="handheld">
|
||||||
|
body {
|
||||||
|
font-family : "Trebuchet MS", sans-serif;
|
||||||
|
font-size : 13px;
|
||||||
|
background-color : white;
|
||||||
|
color: gray;
|
||||||
|
margin : 0 0 0 0;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
visibility : visible;
|
||||||
|
overflow : auto;
|
||||||
|
margin : 0;
|
||||||
|
padding : 0;
|
||||||
|
}
|
||||||
|
img {
|
||||||
|
display : none;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<!-- All other media -->
|
||||||
|
<style type="text/css" media="screen">
|
||||||
|
body {
|
||||||
|
font-family : "Trebuchet MS", sans-serif;
|
||||||
|
font-size : 13px;
|
||||||
|
background-color : white;
|
||||||
|
margin : 0 0 0 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#osc_txt {
|
||||||
|
margin: 0pt auto;
|
||||||
|
display: block;
|
||||||
|
width: 600px;
|
||||||
|
font-size: 64px;
|
||||||
|
font-weight: bold;
|
||||||
|
text-align: center;
|
||||||
|
vertical-align: middle;
|
||||||
|
padding-top: 10px;
|
||||||
|
padding-bottom: 10px;
|
||||||
|
border-bottom: 3px solid #eeeeee;
|
||||||
|
border-top: 3px solid #eeeeee;
|
||||||
|
}
|
||||||
|
#col_1, #col_2, #col_3, #col_4, #col_5 {
|
||||||
|
text-align: center;
|
||||||
|
padding-top: 6px;
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
#col_1 {
|
||||||
|
opacity: 1;
|
||||||
|
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
|
||||||
|
filter: alpha(opacity=100);
|
||||||
|
font-size: 30px;
|
||||||
|
}
|
||||||
|
#col_2 {
|
||||||
|
opacity: .8;
|
||||||
|
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
|
||||||
|
filter: alpha(opacity=80);
|
||||||
|
font-size: 25px;
|
||||||
|
}
|
||||||
|
#col_3 {
|
||||||
|
opacity: .6;
|
||||||
|
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=60)";
|
||||||
|
filter: alpha(opacity=60);
|
||||||
|
font-size: 20px;
|
||||||
|
}
|
||||||
|
#col_4 {
|
||||||
|
opacity: .4;
|
||||||
|
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=40)";
|
||||||
|
filter: alpha(opacity=40);
|
||||||
|
font-size: 16px;
|
||||||
|
}
|
||||||
|
#col_5 {
|
||||||
|
opacity: .2;
|
||||||
|
-ms-filter:"progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
|
||||||
|
filter: alpha(opacity=20);
|
||||||
|
font-size: 12px;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Navigation strip */
|
||||||
|
#nav_strip {
|
||||||
|
/*float: right;*/
|
||||||
|
text-align: center;
|
||||||
|
margin-top: 150px;
|
||||||
|
margin-bottom: 20px;
|
||||||
|
color: #bbbbbb;
|
||||||
|
}
|
||||||
|
#nav_strip a {
|
||||||
|
color: #777777;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
#nav_strip a:hover {
|
||||||
|
color: #77aa77;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Setlist, control */
|
||||||
|
#foot {
|
||||||
|
position: fixed;
|
||||||
|
bottom: 5px;
|
||||||
|
text-align: center;
|
||||||
|
color: #cccccc;
|
||||||
|
width: 100%;
|
||||||
|
}
|
||||||
|
#setlist a, #control a {
|
||||||
|
color: #777777;
|
||||||
|
text-decoration: none;
|
||||||
|
}
|
||||||
|
#setlist a:hover, #control a:hover {
|
||||||
|
color: #77aa77;
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
//<![CDATA[
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
//<![CDATA[
|
||||||
|
var rd = {val:0, max:0, min:0, step:0, trend:1, itr:0};
|
||||||
|
var gr = {val:0, max:0, min:0, step:0, trend:1, itr:0};
|
||||||
|
var bl = {val:0, max:0, min:0, step:0, trend:1, itr:0};
|
||||||
|
var col_update_timer = 50;
|
||||||
|
var color_display = 'dot';
|
||||||
|
var player_state = 'play';
|
||||||
|
|
||||||
|
function advance_color(clr) {
|
||||||
|
if ((clr.itr == 0) && (clr.trend == 1)) {
|
||||||
|
clr.min = Math.ceil(Math.random() * 50);
|
||||||
|
clr.max = 206 + (Math.ceil(Math.random() * 50));
|
||||||
|
clr.val = clr.min;
|
||||||
|
clr.step = 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (clr.trend == 1) {
|
||||||
|
clr.itr ++;
|
||||||
|
if (clr.itr < (clr.max - clr.min)) {
|
||||||
|
clr.val += clr.step;
|
||||||
|
} else {
|
||||||
|
clr.val -= clr.step;
|
||||||
|
clr.trend = 0;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
clr.itr --;
|
||||||
|
if (clr.itr > 0) {
|
||||||
|
clr.val -= clr.step;
|
||||||
|
} else {
|
||||||
|
clr.val += clr.step;
|
||||||
|
clr.trend = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function random_colorize_job () {
|
||||||
|
var item = document.getElementById ("osc_txt");
|
||||||
|
|
||||||
|
advance_color (rd);
|
||||||
|
advance_color (gr);
|
||||||
|
advance_color (bl);
|
||||||
|
|
||||||
|
item.style.color = "rgb("+rd.val+","+gr.val+","+bl.val+")";
|
||||||
|
if (color_display == 'rgb') {
|
||||||
|
color_str = item.style.color;
|
||||||
|
} else if (color_display == 'dot') {
|
||||||
|
color_str = "• • • •";
|
||||||
|
} else {
|
||||||
|
color_str = "#" + rd.val.toString(16) + gr.val.toString(16) + bl.val.toString(16);
|
||||||
|
}
|
||||||
|
|
||||||
|
col_update_timer--;
|
||||||
|
|
||||||
|
if (col_update_timer == 0) {
|
||||||
|
col_update_timer = 50;
|
||||||
|
document.getElementById ("col_5").innerHTML = document.getElementById ("col_4").innerHTML;
|
||||||
|
document.getElementById ("col_5").style.color = document.getElementById ("col_4").style.color;
|
||||||
|
document.getElementById ("col_4").innerHTML = document.getElementById ("col_3").innerHTML;
|
||||||
|
document.getElementById ("col_4").style.color = document.getElementById ("col_3").style.color;
|
||||||
|
document.getElementById ("col_3").innerHTML = document.getElementById ("col_2").innerHTML;
|
||||||
|
document.getElementById ("col_3").style.color = document.getElementById ("col_2").style.color;
|
||||||
|
document.getElementById ("col_2").innerHTML = document.getElementById ("col_1").innerHTML;
|
||||||
|
document.getElementById ("col_2").style.color = document.getElementById ("col_1").style.color;
|
||||||
|
// document.getElementById ("col_1").innerHTML = item.style.color;
|
||||||
|
document.getElementById ("col_1").innerHTML = color_str;
|
||||||
|
document.getElementById ("col_1").style.color = item.style.color;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function random_colorize() {
|
||||||
|
if (player_state == 'play') {
|
||||||
|
random_colorize_job();
|
||||||
|
}
|
||||||
|
tmot = setTimeout("random_colorize()",20);
|
||||||
|
}
|
||||||
|
|
||||||
|
function initialize () {
|
||||||
|
change_display(color_display);
|
||||||
|
|
||||||
|
random_colorize();
|
||||||
|
}
|
||||||
|
|
||||||
|
function change_display (elem) {
|
||||||
|
color_display = elem;
|
||||||
|
if (color_display == 'rgb') {
|
||||||
|
document.getElementById('rgb_ln').style.fontWeight = 'bold';
|
||||||
|
document.getElementById('hex_ln').style.fontWeight = 'normal';
|
||||||
|
document.getElementById('dot_ln').style.fontWeight = 'normal';
|
||||||
|
} else if (color_display == 'dot') {
|
||||||
|
document.getElementById('rgb_ln').style.fontWeight = 'normal';
|
||||||
|
document.getElementById('hex_ln').style.fontWeight = 'normal';
|
||||||
|
document.getElementById('dot_ln').style.fontWeight = 'bold';
|
||||||
|
} else {
|
||||||
|
document.getElementById('rgb_ln').style.fontWeight = 'normal';
|
||||||
|
document.getElementById('hex_ln').style.fontWeight = 'bold';
|
||||||
|
document.getElementById('dot_ln').style.fontWeight = 'normal';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function toggle_play () {
|
||||||
|
if (player_state == 'play') {
|
||||||
|
player_state = 'pause';
|
||||||
|
document.getElementById('pp_button').innerHTML = 'Play';
|
||||||
|
} else {
|
||||||
|
player_state = 'play';
|
||||||
|
document.getElementById('pp_button').innerHTML = 'Pause';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//]]>
|
||||||
|
</script>
|
||||||
|
</head><body onload="initialize()">
|
||||||
|
<div id="nav_strip">
|
||||||
|
<a href="${website.url}" title="Home">Home</a>
|
||||||
|
</div>
|
||||||
|
<div id="osc_txt">
|
||||||
|
${website.name}
|
||||||
|
</div>
|
||||||
|
<div id="col_1"></div>
|
||||||
|
<div id="col_2"></div>
|
||||||
|
<div id="col_3"></div>
|
||||||
|
<div id="col_4"></div>
|
||||||
|
<div id="col_5"></div>
|
||||||
|
<div id="foot">
|
||||||
|
<div id="control">
|
||||||
|
<a href="javascript:toggle_play()" title="Toggle Play" id="pp_button">Pause</a>
|
||||||
|
</div>
|
||||||
|
<div id="setlist">
|
||||||
|
<a href="javascript:change_display('rgb')" title="Display colors in RGB values" id="rgb_ln"> RGB</a> •
|
||||||
|
<a href="javascript:change_display('hex')" title="Display colors in Hex values" id="hex_ln"> Hex</a> •
|
||||||
|
<a href="javascript:change_display('dot')" title="Display colored dots" id="dot_ln"> Dots</a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
${ga_tracking_stub}
|
||||||
|
|
||||||
|
</body>
|
||||||
|
</html>`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
const server = http.createServer((req, res) => {
|
||||||
|
res.statusCode = 200;
|
||||||
|
res.setHeader('Content-Type', 'text/html');
|
||||||
|
res.write(getPage(req));
|
||||||
|
res.end();
|
||||||
|
console.log(`Serviced request ${req}`);
|
||||||
|
}).listen(port, hostname, () => {
|
||||||
|
console.log(`Server running at http://${hostname}:${port}/`);
|
||||||
|
});
|
Loading…
Reference in New Issue
Block a user