Initial setup of repo

This commit is contained in:
Radoslav Pitonak 2017-04-26 14:11:02 +02:00
commit a13a5dbf91
12 changed files with 747 additions and 0 deletions

48
.s2i/bin/assemble Executable file
View file

@ -0,0 +1,48 @@
#!/bin/bash -e
#
# S2I assemble script for the 'nodejs-fedora' image.
# The 'assemble' script builds your application source so that it is ready to run.
#
# For more information refer to the documentation:
# https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md
#
if [[ "$1" == "-h" ]]; then
# If the 'nodejs' assemble script is executed with '-h' flag,
# print the usage.
exec /usr/local/s2i/usage
fi
echo "---> Installing application source..."
mv /tmp/src/* ./
if [ ! -z $HTTP_PROXY ]; then
echo "---> Setting npm http proxy to $HTTP_PROXY"
npm config set proxy $HTTP_PROXY
fi
if [ ! -z $http_proxy ]; then
echo "---> Setting npm http proxy to $http_proxy"
npm config set proxy $http_proxy
fi
if [ ! -z $HTTPS_PROXY ]; then
echo "---> Setting npm https proxy to $HTTPS_PROXY"
npm config set https-proxy $HTTPS_PROXY
fi
if [ ! -z $https_proxy ]; then
echo "---> Setting npm https proxy to $https_proxy"
npm config set https-proxy $https_proxy
fi
# Change the npm registry mirror if provided
if [ -n "$NPM_MIRROR" ]; then
npm config set registry $NPM_MIRROR
fi
echo "---> Building application from source..."
npm install
# Fix permissions
chmod -Rf g+w /opt/app-root/ || true

49
.s2i/bin/run Executable file
View file

@ -0,0 +1,49 @@
#!/bin/bash -e
#
# S2I run script for the 'nodejs' image.
# The run script executes the server that runs your application.
#
# For more information see the documentation:
# https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md
#
# Runs the nodejs application server. If the container is run in development mode,
# hot deploy and debugging are enabled.
run_node() {
echo -e "Environment: \n\tDEV_MODE=${DEV_MODE}\n\tNODE_ENV=${NODE_ENV}\n\tDEBUG_PORT=${DEBUG_PORT}"
if [ "$DEV_MODE" == true ]; then
echo "Launching via nodemon..."
exec nodemon --debug="$DEBUG_PORT"
else
echo "Launching via npm..."
exec npm run -d $NPM_RUN
fi
}
#Set the debug port to 5858 by default.
if [ -z "$DEBUG_PORT" ]; then
export DEBUG_PORT=5858
fi
# Set the environment to development by default.
if [ -z "$DEV_MODE" ]; then
export DEV_MODE=false
fi
# If NODE_ENV is not set by the user, then NODE_ENV is determined by whether
# the container is run in development mode.
if [ -z "$NODE_ENV" ]; then
if [ "$DEV_MODE" == true ]; then
export NODE_ENV=development
else
export NODE_ENV=production
fi
fi
# Allow users to inspect/debug the builder image itself, by using:
# $ docker run -i -t openshift/centos-nodejs-builder --debug
#
[ "$1" == "--debug" ] && exec /bin/bash
run_node

12
.s2i/bin/usage Executable file
View file

@ -0,0 +1,12 @@
#!/bin/bash -e
cat <<EOF
This is the nodejs S2I image:
To use it, install S2I: https://github.com/openshift/source-to-image
Sample invocation:
s2i build <source code path/URL> nodejs:6 <application image>
You can then run the resulting image via:
docker run <application image>
EOF

73
Dockerfile Normal file
View file

@ -0,0 +1,73 @@
FROM registry.fedoraproject.org/fedora:25
# Description
# Environment:
# * $HOME_APP_ROOT - Root directory of application
# * $NPM_RUN - Select an alternate / custom runtime mode, defined in your package.json file's scripts section (default: npm run "start").
# These user-defined run-scripts are unavailable while DEV_MODE is in use.
# Exposed ports:
# * 8080 - Unprivileged port used by nodejs application
# Additional packages
# * findutils are needed to help fix permissions.
MAINTAINER Rado Pitonak <rpitonak@redhat.com>
RUN dnf install -y --setopt=tsflags=nodocs nodejs npm && \
dnf install -y --setopt=tsflags=nodocs findutils && \
dnf -y clean all
ENV NAME=nodejs \
VERSION=0 \
RELEASE=1 \
ARCH=x86_64
LABEL summary="Javascript runtime." \
name="Node.js" \
version="$VERSION" \
release="$RELEASE.$DISTTAG" \
architecture="$ARCH" \
description="Node.js is a platform built on V8 JavaScript Engine for easily building fast, scalable network applications." \
vendor="Fedora Project" \
com.redhat.component="$NAME" \
usage="s2i build <SOURCE-REPOSITORY> nodejs:6 <APP-NAME>" \
org.fedoraproject.component="nodejs" \
authoritative-source-url="registry.fedoraproject.org" \
io.k8s.description="Node.js is a platform built on V8 JavaScript Engine for easily building fast, scalable network applications." \
io.k8s.display-name="Node.js 6.10.1" \
io.openshift.tags="nodejs, js, JavaScript" \
io.openshift.expose-services="8080:https" \
io.openshift.s2i.scripts-url="image:///usr/local/s2i"
# Copy s2i scripts
COPY ./.s2i/bin/ /usr/local/s2i
# Add help file
COPY root /
# set enviroment variables
# add path to npm binaries to PATH enviroment variable
ENV HOME_APP_ROOT=/opt/app-root \
NPM_RUN=start \
PATH=/opt/app-root/node_modules/.bin/:/opt/app-root/.npm-global/bin/:$PATH
# create home directory and system user with UID 1001 GID 0 and default name
# set user home directory to $HOME_APP_ROOT
RUN mkdir -p ${HOME_APP_ROOT} && \
useradd -u 1001 -r -g 0 -d ${HOME_APP_ROOT} -s /sbin/nologin \
-c "Default user" default
# EXPOSE instruction exposes port from container to host.
# Specify it during `docker run` as parameter: "-p <host_port>:<container_port>"
EXPOSE 8080
# drop the root user and make content of /opt/app-root owned by user 1001
RUN chown -R 1001:0 /opt/app-root && \
find ${HOME_APP_ROOT} -type d -exec chmod g+ws {} \;
# Default user for image
USER 1001
WORKDIR ${HOME_APP_ROOT}
# Command which will start service during command `docker run`
CMD /usr/local/s2i/usage

88
help.md Normal file
View file

@ -0,0 +1,88 @@
% nodejs(1)
% Rado Pitonak \<rpitonak@redhat.com\>
% DATE 07.04.2017
# NAME
nodejs - source to image builder of node.js applications.
# DESCRIPTION
Image for building node.js application as reproducible Docker image using source to image.Image is based on fedora.
# USAGE
To pull the nodejs container run:
# docker pull rpitonak/nodejs:6
To build your node.js application use run:
# s2i build <SOURCE-REPOSITORY> nodejs:6 <NAME-OF-APP>
To run your application in docker container:
# docker -d run -p 8080:8080 <NAME-OF-APP>
By default container is running in production mode with exposed port 8080.To change behavior see Enviroment variables section below.
# ENVIRONMENT VARIABLES
NODE_ENV=runtime_mode
Node.js runtime mode (default: "production")
DEV_MODE=mode
When set to "true", `nodemon` will be used to automatically reload the server while you work (default: "false"). Setting `DEV_MODE` to "true" will change the `NODE_ENV` default to "development" (if not explicitly set).
NPM_RUN=value
Select an alternate / custom runtime mode, defined in your `package.json` file's [`scripts`](https://docs.npmjs.com/misc/scripts) section (default: npm run "start"). These user-defined run-scripts are unavailable while `DEV_MODE` is in use.
HTTP_PROXY=url
Use an npm proxy during assembly
HTTPS_PROXY=url
Use an npm proxy during assembly
NPM_MIRROR=registry
Use a custom NPM registry mirror to download packages during the build process
# DEVELOPMENT
This image supports development mode. This mode can be switched on and off with the environment variable `DEV_MODE`. `DEV_MODE` can either be set to `true` or `false`.
The debug port can be specified with the environment variable `DEBUG_PORT`. `DEBUG_PORT` is only valid if `DEV_MODE=true`.
By default, `DEV_MODE` is set to `false`, and `DEBUG_PORT` is set to `5858`, however the `DEBUG_PORT` is only relevant if `DEV_MODE=true`.
# HOT DEPLOY
As part of development mode, this image supports hot deploy. If development mode is enabled, any souce code that is changed in the running container will be immediately reflected in the running nodejs application
To change your source code in a running container, use Docker's exec (https://docs.docker.com/engine/reference/commandline/exec/) command:
# docker exec -it <CONTAINER_ID> /bin/bash
After you enter into the running container, your current directory is set to /opt/app-root/, where the source code is located.
# EXAMPLE
To run your application in development mode run:
# docker run --env DEV_MODE=true -p 8080:8080 <NAME-OF-APP>
To run the container in production mode, run:
# docker run --env DEV_MODE=false <NAME-OF-APP>
To run the container in development mode with a debug port of 5454, run
# docker run --env DEV_MODE=true DEBUG_PORT=5454 <NAME-OF-APP>
To build your application with using of npm proxy.
# s2i build ./test/test-app nodejs:6 my-app --env HTTP_PROXY=url
# SECURITY IMPLICATIONS
-d
Runs continuously as a daemon process in the background
-p 8080:8080
Opens container port 8080 and maps it to the same port on the Host.

183
root/help.1 Normal file
View file

@ -0,0 +1,183 @@
.TH "nodejs" "1" "" "Rado Pitonak \<rpitonak@redhat.com\>" "DATE 07.04.2017" ""
.SH NAME
.PP
nodejs \- source to image builder of node.js applications.
.SH DESCRIPTION
.PP
Image for building node.js application as reproducible Docker image using source to image.Image is based on fedora.
.SH USAGE
.PP
To pull the nodejs container run:
.PP
.RS
.nf
# docker pull rpitonak/nodejs:6
.fi
.RE
.PP
To build your node.js application use run:
.PP
.RS
.nf
# s2i build <SOURCE\-REPOSITORY> nodejs:6 <NAME\-OF\-APP>
.fi
.RE
.PP
To run your application in docker container:
.PP
.RS
.nf
# docker run \-d \-p 8080:8080 <NAME\-OF\-APP>
.fi
.RE
.PP
By default container is running in production mode with exposed port 8080.To change behavior see Enviroment variables section below.
.SH ENVIRONMENT VARIABLES
.PP
NODE\_ENV=runtime\_mode
Node.js runtime mode (default: "production")
.PP
DEV\_MODE=mode
When set to "true", \fB\fCnodemon\fR will be used to automatically reload the server while you work (default: "false"). Setting \fB\fCDEV\_MODE\fR to "true" will change the \fB\fCNODE\_ENV\fR default to "development" (if not explicitly set).
.PP
NPM\_RUN=value
Select an alternate / custom runtime mode, defined in your \fB\fCpackage.json\fR file's
\[la]https://docs.npmjs.com/misc/scripts\[ra] section (default: npm run "start"). These user\-defined run\-scripts are unavailable while \fB\fCDEV\_MODE\fR is in use.
.PP
HTTP\_PROXY=url
Use an npm proxy during assembly
.PP
HTTPS\_PROXY=url
Use an npm proxy during assembly
.PP
NPM\_MIRROR=registry
Use a custom NPM registry mirror to download packages during the build process
.SH DEVELOPMENT
.PP
This image supports development mode. This mode can be switched on and off with the environment variable \fB\fCDEV\_MODE\fR. \fB\fCDEV\_MODE\fR can either be set to \fB\fCtrue\fR or \fB\fCfalse\fR.
The debug port can be specified with the environment variable \fB\fCDEBUG\_PORT\fR. \fB\fCDEBUG\_PORT\fR is only valid if \fB\fCDEV\_MODE=true\fR.
By default, \fB\fCDEV\_MODE\fR is set to \fB\fCfalse\fR, and \fB\fCDEBUG\_PORT\fR is set to \fB\fC5858\fR, however the \fB\fCDEBUG\_PORT\fR is only relevant if \fB\fCDEV\_MODE=true\fR.
.SH HOT DEPLOY
.PP
As part of development mode, this image supports hot deploy. If development mode is enabled, any souce code that is changed in the running container will be immediately reflected in the running nodejs application
.PP
To change your source code in a running container, use Docker's exec (
\[la]https://docs.docker.com/engine/reference/commandline/exec/\[ra]) command:
.PP
.RS
.nf
# docker exec \-it <CONTAINER\_ID> /bin/bash
.fi
.RE
.PP
After you enter into the running container, your current directory is set to /opt/app\-root/, where the source code is located.
.SH EXAMPLE
.PP
To run your application in development mode run:
.PP
.RS
.nf
# docker run \-\-env DEV\_MODE=true \-p 8080:8080 <NAME\-OF\-APP>
.fi
.RE
.PP
To run the container in production mode, run:
.PP
.RS
.nf
# docker run \-\-env DEV\_MODE=false <NAME\-OF\-APP>
.fi
.RE
.PP
To run the container in development mode with a debug port of 5454, run
.PP
.RS
.nf
# docker run \-\-env DEV\_MODE=true DEBUG\_PORT=5454 <NAME\-OF\-APP>
.fi
.RE
.PP
To build your application with using of npm proxy.
.PP
.RS
.nf
# s2i build ./test/test\-app nodejs:6 my\-app \-\-env HTTP\_PROXY=url
.fi
.RE
.SH SECURITY IMPLICATIONS
.PP
\-d
.PP
.RS
.nf
Runs continuously as a daemon process in the background
.fi
.RE
.PP
\-p 8080:8080
.PP
.RS
.nf
Opens container port 8080 and maps it to the same port on the Host.
.fi
.RE

1
test/.gitignore vendored Normal file
View file

@ -0,0 +1 @@
.git/

159
test/run Executable file
View file

@ -0,0 +1,159 @@
#!/bin/bash
#
# The 'run' performs a simple test that verifies the S2I image.
# The main focus here is to exercise the S2I scripts.
#
# For more information see the documentation:
# https://github.com/openshift/source-to-image/blob/master/docs/builder_image.md
#
# IMAGE_NAME specifies a name of the candidate image used for testing.
# The image has to be available before this script is executed.
#
IMAGE_NAME=${IMAGE_NAME-nodejs-fedora-candidate}
# Determining system utility executables (darwin compatibility check)
READLINK_EXEC="readlink"
MKTEMP_EXEC="mktemp"
if [[ "$OSTYPE" =~ 'darwin' ]]; then
! type -a "greadlink" &>"/dev/null" || READLINK_EXEC="greadlink"
! type -a "gmktemp" &>"/dev/null" || MKTEMP_EXEC="gmktemp"
fi
test_dir="$($READLINK_EXEC -zf $(dirname "${BASH_SOURCE[0]}"))"
image_dir=$($READLINK_EXEC -zf ${test_dir}/..)
scripts_url="file://${image_dir}/.s2i/bin"
cid_file=$($MKTEMP_EXEC -u --suffix=.cid)
# Since we built the candidate image locally, we don't want S2I to attempt to pull
# it from Docker hub
s2i_args="--pull-policy=never --loglevel=2"
# Port the image exposes service to be tested
test_port=8080
image_exists() {
docker inspect $1 &>/dev/null
}
container_exists() {
image_exists $(cat $cid_file)
}
container_ip() {
if [ ! -z "$DOCKER_HOST" ] && [[ "$OSTYPE" =~ 'darwin' ]]; then
docker-machine ip
else
docker inspect --format="{{ .NetworkSettings.IPAddress }}" $(cat $cid_file)
fi
}
container_port() {
if [ ! -z "$DOCKER_HOST" ] && [[ "$OSTYPE" =~ 'darwin' ]]; then
docker inspect --format="{{(index .NetworkSettings.Ports \"$test_port/tcp\" 0).HostPort}}" "$(cat "${cid_file}")"
else
echo $test_port
fi
}
run_s2i_build() {
s2i build --incremental=true ${s2i_args} file://${test_dir}/test-app ${IMAGE_NAME} ${IMAGE_NAME}-testapp
}
prepare() {
if ! image_exists ${IMAGE_NAME}; then
echo "ERROR: The image ${IMAGE_NAME} must exist before this script is executed."
exit 1
fi
# s2i build requires the application is a valid 'Git' repository
pushd ${test_dir}/test-app >/dev/null
git init
git config user.email "build@localhost" && git config user.name "builder"
git add -A && git commit -m "Sample commit"
popd >/dev/null
run_s2i_build
}
run_test_application() {
docker run --rm --cidfile=${cid_file} -p ${test_port} ${IMAGE_NAME}-testapp
}
cleanup() {
if [ -f $cid_file ]; then
if container_exists; then
docker stop $(cat $cid_file)
fi
fi
if image_exists ${IMAGE_NAME}-testapp; then
docker rmi ${IMAGE_NAME}-testapp
fi
}
check_result() {
local result="$1"
if [[ "$result" != "0" ]]; then
echo "S2I image '${IMAGE_NAME}' test FAILED (exit code: ${result})"
cleanup
exit $result
fi
}
wait_for_cid() {
local max_attempts=10
local sleep_time=1
local attempt=1
local result=1
while [ $attempt -le $max_attempts ]; do
[ -f $cid_file ] && break
echo "Waiting for container to start..."
attempt=$(( $attempt + 1 ))
sleep $sleep_time
done
}
test_usage() {
echo "Testing 's2i usage'..."
s2i usage ${s2i_args} ${IMAGE_NAME} &>/dev/null
}
test_connection() {
echo "Testing HTTP connection (http://$(container_ip):$(container_port))"
local max_attempts=10
local sleep_time=1
local attempt=1
local result=1
while [ $attempt -le $max_attempts ]; do
echo "Sending GET request to http://$(container_ip):$(container_port)/"
response_code=$(curl -s -w %{http_code} -o /dev/null http://$(container_ip):$(container_port)/)
status=$?
if [ $status -eq 0 ]; then
if [ $response_code -eq 200 ]; then
result=0
fi
break
fi
attempt=$(( $attempt + 1 ))
sleep $sleep_time
done
return $result
}
# Build the application image twice to ensure the 'save-artifacts' and
# 'restore-artifacts' scripts are working properly
prepare
run_s2i_build
check_result $?
# Verify the 'usage' script is working properly
test_usage
check_result $?
# Verify that the HTTP connection can be established to test application container
run_test_application &
# Wait for the container to write its CID file
wait_for_cid
test_connection
check_result $?
cleanup

27
test/test-app/iisnode.yml Normal file
View file

@ -0,0 +1,27 @@
# For documentation see https://github.com/tjanczuk/iisnode/blob/master/src/samples/configuration/iisnode.yml
# loggingEnabled: false
# debuggingEnabled: false
# devErrorsEnabled: false
node_env: production
# nodeProcessCountPerApplication: 1
# maxConcurrentRequestsPerProcess: 1024
# maxNamedPipeConnectionRetry: 24
# namedPipeConnectionRetryDelay: 250
# maxNamedPipeConnectionPoolSize: 512
# maxNamedPipePooledConnectionAge: 30000
# asyncCompletionThreadCount: 0
# initialRequestBufferSize: 4096
# maxRequestBufferSize: 65536
watchedFiles: iisnode.yml;node_modules\*;*.js
# uncFileChangesPollingInterval: 5000
# gracefulShutdownTimeout: 60000
# logDirectoryNameSuffix: logs
# debuggerPortRange: 5058-6058
# debuggerPathSegment: debug
# maxLogFileSizeInKB: 128
# appendToExistingLog: false
# logFileFlushInterval: 5000
# flushResponse: false
# enableXFF: false
# promoteServerVars:

View file

@ -0,0 +1,32 @@
{
"name": "node-echo",
"version": "0.0.1",
"description": "node-echo",
"main": "server.js",
"dependencies": {
},
"devDependencies": {
"nodemon": "*"
},
"engine": {
"node": "*",
"npm": "*"
},
"scripts": {
"dev": "nodemon --ignore node_modules/ server.js",
"start": "node server.js"
},
"repository": {
"type": "git",
"url": "http://github.com/bettiolo/node-echo.git"
},
"keywords": [
"Echo"
],
"author": "Marco Bettiolo <marco@bettiolo.it>",
"license": "",
"bugs": {
"url": "http://github.com/bettiolo/node-echo/issues"
},
"homepage": "http://apilb.com"
}

58
test/test-app/server.js Normal file
View file

@ -0,0 +1,58 @@
var util = require('util');
var http = require('http');
var url = require('url');
var qs = require('querystring');
var os = require('os')
var port = process.env.PORT || process.env.port || process.env.OPENSHIFT_NODEJS_PORT || 8080;
var ip = process.env.OPENSHIFT_NODEJS_IP || '0.0.0.0';
var nodeEnv = process.env.NODE_ENV || 'unknown';
var version = require('./package.json').version || 'unknown';
var startedByNpm = !!process.env.npm_package_version;
var server = http.createServer(function (req, res) {
var url_parts = url.parse(req.url, true);
var body = '';
req.on('data', function (data) {
body += data;
});
req.on('end', function () {
var formattedBody = qs.parse(body);
res.writeHead(200, {'Content-Type': 'text/plain'});
res.write('This is a node.js echo service v' + version + '\n');
res.write('Host: ' + req.headers.host + '\n');
res.write('\n');
res.write('node.js Production Mode: ' + (nodeEnv == 'production' ? 'yes' : 'no') + '\n');
res.write('node.js ' + process.version + '\n');
res.write('Executed by npm: ' + (startedByNpm ? 'yes' : 'no') + '\n');
res.write('\n');
res.write('HTTP/' + req.httpVersion +'\n');
res.write('Request headers:\n');
res.write(util.inspect(req.headers, null) + '\n');
res.write('Request query:\n');
res.write(util.inspect(url_parts.query, null) + '\n');
res.write('Request body:\n');
res.write(util.inspect(formattedBody, null) + '\n');
res.write('\n');
res.write('Host: ' + os.hostname() + '\n');
res.write('OS Type: ' + os.type() + '\n');
res.write('OS Platform: ' + os.platform() + '\n');
res.write('OS Arch: ' + os.arch() + '\n');
res.write('OS Release: ' + os.release() + '\n');
res.write('OS Uptime: ' + os.uptime() + '\n');
res.write('OS Free memory: ' + os.freemem() / 1024 / 1024 + 'mb\n');
res.write('OS Total memory: ' + os.totalmem() / 1024 / 1024 + 'mb\n');
res.write('OS CPU count: ' + os.cpus().length + '\n');
res.write('OS CPU model: ' + os.cpus()[0].model + '\n');
res.write('OS CPU speed: ' + os.cpus()[0].speed + 'mhz\n');
res.end('\n');
});
});
console.log('Initializing Server on ' + ip + ':' + port);
server.listen(port,ip, function(){
var address = server.address();
console.log('Server running on ' + address.address + ':' + address.port);
});

17
test/test-app/web.config Normal file
View file

@ -0,0 +1,17 @@
<configuration>
<system.webServer>
<handlers>
<add name="iisnode" path="server.js" verb="*" modules="iisnode" />
</handlers>
<iisnode loggingEnabled="false" />
<rewrite>
<rules>
<rule name="myapp">
<match url="/*" />
<action type="Rewrite" url="server.js" />
</rule>
</rules>
</rewrite>
</system.webServer>
</configuration>