Configurable website in Docker

This commit is contained in:
Mahesh Asolkar 2023-01-02 11:19:30 -08:00
commit e6cd7a0f6d
6 changed files with 425 additions and 0 deletions

2
.dockerignore Normal file
View File

@ -0,0 +1,2 @@
node_modules
npm-debug.log

17
Dockerfile Normal file
View 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
View 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
View 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
View 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
View 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 = "&bull; &bull; &bull; &bull;";
} 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> &bull;
<a href="javascript:change_display('hex')" title="Display colors in Hex values" id="hex_ln"> Hex</a> &bull;
<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}/`);
});