From 070bcb7d2de8f678da05dbc6722e473e72f2e3ae Mon Sep 17 00:00:00 2001 From: Radoslav Pitonak Date: Wed, 26 Apr 2017 13:54:32 +0200 Subject: [PATCH 01/12] Intial setup of repo --- .s2i/bin/assemble | 48 ++++++++++ .s2i/bin/run | 49 ++++++++++ .s2i/bin/usage | 12 +++ Dockerfile | 73 +++++++++++++++ help.md | 88 ++++++++++++++++++ root/help.1 | 183 +++++++++++++++++++++++++++++++++++++ test/.gitignore | 1 + test/run | 159 ++++++++++++++++++++++++++++++++ test/test-app/iisnode.yml | 27 ++++++ test/test-app/package.json | 32 +++++++ test/test-app/server.js | 58 ++++++++++++ test/test-app/web.config | 17 ++++ 12 files changed, 747 insertions(+) create mode 100755 .s2i/bin/assemble create mode 100755 .s2i/bin/run create mode 100755 .s2i/bin/usage create mode 100644 Dockerfile create mode 100644 help.md create mode 100644 root/help.1 create mode 100644 test/.gitignore create mode 100755 test/run create mode 100644 test/test-app/iisnode.yml create mode 100644 test/test-app/package.json create mode 100644 test/test-app/server.js create mode 100644 test/test-app/web.config diff --git a/.s2i/bin/assemble b/.s2i/bin/assemble new file mode 100755 index 0000000..8a7ad10 --- /dev/null +++ b/.s2i/bin/assemble @@ -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 diff --git a/.s2i/bin/run b/.s2i/bin/run new file mode 100755 index 0000000..870bb05 --- /dev/null +++ b/.s2i/bin/run @@ -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 diff --git a/.s2i/bin/usage b/.s2i/bin/usage new file mode 100755 index 0000000..b1a46b4 --- /dev/null +++ b/.s2i/bin/usage @@ -0,0 +1,12 @@ +#!/bin/bash -e +cat < nodejs:6 + +You can then run the resulting image via: +docker run +EOF diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..bb04ba5 --- /dev/null +++ b/Dockerfile @@ -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 + +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 nodejs:6 " \ + 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 :" +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 diff --git a/help.md b/help.md new file mode 100644 index 0000000..63ba335 --- /dev/null +++ b/help.md @@ -0,0 +1,88 @@ +% nodejs(1) +% Rado Pitonak \ +% 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 nodejs:6 + + +To run your application in docker container: + + + # docker -d run -p 8080:8080 + +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 /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 + +To run the container in production mode, run: + + # docker run --env DEV_MODE=false + +To run the container in development mode with a debug port of 5454, run + + # docker run --env DEV_MODE=true DEBUG_PORT=5454 + +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. diff --git a/root/help.1 b/root/help.1 new file mode 100644 index 0000000..fdfa3e3 --- /dev/null +++ b/root/help.1 @@ -0,0 +1,183 @@ +.TH "nodejs" "1" "" "Rado Pitonak \" "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 nodejs:6 + +.fi +.RE + +.PP +To run your application in docker container: + +.PP +.RS + +.nf +# docker run \-d \-p 8080:8080 + +.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 /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 + +.fi +.RE + +.PP +To run the container in production mode, run: + +.PP +.RS + +.nf +# docker run \-\-env DEV\_MODE=false + +.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 + +.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 diff --git a/test/.gitignore b/test/.gitignore new file mode 100644 index 0000000..2d2ecd6 --- /dev/null +++ b/test/.gitignore @@ -0,0 +1 @@ +.git/ diff --git a/test/run b/test/run new file mode 100755 index 0000000..d6a53f9 --- /dev/null +++ b/test/run @@ -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 diff --git a/test/test-app/iisnode.yml b/test/test-app/iisnode.yml new file mode 100644 index 0000000..52b201b --- /dev/null +++ b/test/test-app/iisnode.yml @@ -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: \ No newline at end of file diff --git a/test/test-app/package.json b/test/test-app/package.json new file mode 100644 index 0000000..7ec3c6b --- /dev/null +++ b/test/test-app/package.json @@ -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 ", + "license": "", + "bugs": { + "url": "http://github.com/bettiolo/node-echo/issues" + }, + "homepage": "http://apilb.com" +} diff --git a/test/test-app/server.js b/test/test-app/server.js new file mode 100644 index 0000000..3c3e671 --- /dev/null +++ b/test/test-app/server.js @@ -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); +}); diff --git a/test/test-app/web.config b/test/test-app/web.config new file mode 100644 index 0000000..a6b44a3 --- /dev/null +++ b/test/test-app/web.config @@ -0,0 +1,17 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file From 7e1b5afe3e182de02adadfbd66cecce40f7c7832 Mon Sep 17 00:00:00 2001 From: Radoslav Pitonak Date: Wed, 26 Apr 2017 14:27:03 +0200 Subject: [PATCH 02/12] update name in Dockefile --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index bb04ba5..c56924c 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,7 +22,7 @@ ENV NAME=nodejs \ ARCH=x86_64 LABEL summary="Javascript runtime." \ - name="Node.js" \ + name="$NAME" \ version="$VERSION" \ release="$RELEASE.$DISTTAG" \ architecture="$ARCH" \ From ea4d25a9c0a1d446e7065b85f6ec331810370e44 Mon Sep 17 00:00:00 2001 From: Radoslav Pitonak Date: Wed, 26 Apr 2017 14:36:05 +0200 Subject: [PATCH 03/12] name update --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c56924c..35ccc9a 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,7 +22,7 @@ ENV NAME=nodejs \ ARCH=x86_64 LABEL summary="Javascript runtime." \ - name="$NAME" \ + name="$FGC/$NAME" \ version="$VERSION" \ release="$RELEASE.$DISTTAG" \ architecture="$ARCH" \ From 9bdd9ba9ec9bb2b3c74ec897f893ac60dbdc1ad4 Mon Sep 17 00:00:00 2001 From: Adam Miller Date: Tue, 23 May 2017 16:16:07 -0500 Subject: [PATCH 04/12] Bump RELEASE for automatic rebuild --- Dockerfile | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/Dockerfile b/Dockerfile index 35ccc9a..9d2838e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,10 +16,7 @@ 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 +ENV NAME=nodejs VERSION=0 RELEASE=2 ARCH=x86_64 LABEL summary="Javascript runtime." \ name="$FGC/$NAME" \ From d53cf50fe1d16f60b9ab761300382c524dd57249 Mon Sep 17 00:00:00 2001 From: Radoslav Pitonak Date: Wed, 31 May 2017 10:34:16 +0200 Subject: [PATCH 05/12] change base image to s2i-base --- Dockerfile | 14 ++----- Makefile | 16 ++++++++ test/run | 112 +++++++++++++++++++++++++++++++++++++++++++++++++---- 3 files changed, 125 insertions(+), 17 deletions(-) create mode 100644 Makefile diff --git a/Dockerfile b/Dockerfile index 35ccc9a..6c21d92 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM registry.fedoraproject.org/fedora:25 +FROM registry.fedoraproject.org/f25/s2i-base # Description # Environment: @@ -10,16 +10,12 @@ FROM registry.fedoraproject.org/fedora:25 # Additional packages # * findutils are needed to help fix permissions. -MAINTAINER Rado Pitonak +LABEL MAINTAINER Rado Pitonak 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 +ENV NAME=nodejs VERSION=0 RELEASE=2 ARCH=x86_64 LABEL summary="Javascript runtime." \ name="$FGC/$NAME" \ @@ -52,9 +48,7 @@ ENV HOME_APP_ROOT=/opt/app-root \ # 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 +RUN mkdir -p ${HOME_APP_ROOT} # EXPOSE instruction exposes port from container to host. # Specify it during `docker run` as parameter: "-p :" diff --git a/Makefile b/Makefile new file mode 100644 index 0000000..c232933 --- /dev/null +++ b/Makefile @@ -0,0 +1,16 @@ +.PHONY: build build-test run test + +IMAGE_NAME = nodejs +CANDIDATE_IMAGE_NAME=nodejs-candidate + +build: + docker build --tag=$(IMAGE_NAME):6 . + +build-test: + docker build --tag=$(CANDIDATE_IMAGE_NAME) . + +run: build + docker run -d $(IMAGE_NAME):6 + +test: build-test + ./test/run diff --git a/test/run b/test/run index d6a53f9..3b50f2c 100755 --- a/test/run +++ b/test/run @@ -9,7 +9,7 @@ # 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} +IMAGE_NAME=${IMAGE_NAME-nodejs-candidate} # Determining system utility executables (darwin compatibility check) READLINK_EXEC="readlink" @@ -26,11 +26,15 @@ 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" +s2i_args="--force-pull=false" # Port the image exposes service to be tested test_port=8080 +info() { + echo -e "\n\e[1m[INFO] $@...\e[0m\n" +} + image_exists() { docker inspect $1 &>/dev/null } @@ -47,6 +51,10 @@ container_ip() { fi } +container_logs() { + docker logs $(cat $cid_file) +} + container_port() { if [ ! -z "$DOCKER_HOST" ] && [[ "$OSTYPE" =~ 'darwin' ]]; then docker inspect --format="{{(index .NetworkSettings.Ports \"$test_port/tcp\" 0).HostPort}}" "$(cat "${cid_file}")" @@ -70,11 +78,10 @@ prepare() { 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 + docker run --rm --cidfile=${cid_file} -p ${test_port} $1 ${IMAGE_NAME}-testapp } cleanup() { @@ -84,8 +91,9 @@ cleanup() { fi fi if image_exists ${IMAGE_NAME}-testapp; then - docker rmi ${IMAGE_NAME}-testapp + docker rmi -f ${IMAGE_NAME}-testapp fi + rm -rf ${test_dir}/test-app/.git } check_result() { @@ -110,11 +118,56 @@ wait_for_cid() { done } -test_usage() { +test_s2i_usage() { echo "Testing 's2i usage'..." s2i usage ${s2i_args} ${IMAGE_NAME} &>/dev/null } +test_docker_run_usage() { + echo "Testing 'docker run' usage..." + docker run ${IMAGE_NAME} &>/dev/null +} + +validate_default_value() { + local label=$1 + + IFS=':' read -a label_vals <<< $(docker inspect -f "{{index .Config.Labels \"$label\"}}" ${IMAGE_NAME}) + label_var=${label_vals[0]} + default_label_val=${label_vals[1]} + + actual_label_val=$(docker run --rm $IMAGE_NAME /bin/bash -c "echo $"$label_var) + + if [ "$actual_label_val" != "$default_label_val" ]; then + echo "ERROR default value for $label with environment variable $label_var; Expected $default_label_val, got $actual_label_val" + return 1 + fi +} + +# Gets the NODE_ENV environment variable from the container. +get_node_env_from_container() { + local dev_mode="$1" + local node_env="$2" + + IFS=':' read -a label_val <<< $(docker inspect -f '{{index .Config.Labels "com.redhat.dev-mode"}}' $IMAGE_NAME) + dev_mode_label_var="${label_val[0]}" + + echo $(docker run --rm --env $dev_mode_label_var=$dev_mode --env NODE_ENV=$node_env $IMAGE_NAME /bin/bash -c 'echo "$NODE_ENV"') +} + +# Ensures that a docker container run with '--env NODE_ENV=$current_val' produces a NODE_ENV value of $expected when +# DEV_MODE=dev_mode. +validate_node_env() { + local current_val="$1" + local dev_mode_val="$2" + local expected="$3" + + actual=$(get_node_env_from_container "$dev_mode_val" "$current_val") + if [ "$actual" != "$expected" ]; then + echo "ERROR default value for NODE_ENV when development mode is $dev_mode_val; should be $expected but is $actual" + return 1 + fi +} + test_connection() { echo "Testing HTTP connection (http://$(container_ip):$(container_port))" local max_attempts=10 @@ -143,10 +196,20 @@ prepare run_s2i_build check_result $? +info "Save-artifacts test passed successfully" + # Verify the 'usage' script is working properly -test_usage +test_s2i_usage check_result $? +info "Usage test passed successfully" + +# Verify the 'usage' script is working properly when running the base image with 'docker run ...' +test_docker_run_usage +check_result $? + +info "Run usage test passed successfully" + # Verify that the HTTP connection can be established to test application container run_test_application & @@ -156,4 +219,39 @@ wait_for_cid test_connection check_result $? +info "Connection test passed successfully" + +echo "Testing DEV_MODE=false" +logs=$(container_logs) +echo ${logs} | grep -q DEV_MODE=false +check_result $? +echo ${logs} | grep -q NODE_ENV=production +check_result $? +echo ${logs} | grep -q DEBUG_PORT=5858 +check_result $? + +info "Production test passed" + +docker kill $(cat $cid_file) +rm $cid_file + +echo "Testing DEV_MODE=true" +run_test_application "-e DEV_MODE=true" & +wait_for_cid + +test_connection +check_result $? + +logs=$(container_logs) +echo ${logs} | grep -q DEV_MODE=true +check_result $? +echo ${logs} | grep -q NODE_ENV=development +check_result $? +echo ${logs} | grep -q DEBUG_PORT=5858 +check_result $? + +info "Development test passed" + cleanup + +info "All tests finished successfully." From 9fb50fb1658702f73f5dcb29fdcd171468860c45 Mon Sep 17 00:00:00 2001 From: Adam Miller Date: Wed, 14 Jun 2017 22:02:44 -0500 Subject: [PATCH 06/12] Bump RELEASE for automatic rebuild --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 6c21d92..5acae4d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ LABEL MAINTAINER Rado Pitonak RUN dnf install -y --setopt=tsflags=nodocs nodejs npm && \ dnf -y clean all -ENV NAME=nodejs VERSION=0 RELEASE=2 ARCH=x86_64 +ENV NAME=nodejs VERSION=0 RELEASE=3 ARCH=x86_64 LABEL summary="Javascript runtime." \ name="$FGC/$NAME" \ From 70a4f156ebae4312d20a84ca8b8845d0b151004d Mon Sep 17 00:00:00 2001 From: Adam Miller Date: Tue, 27 Jun 2017 11:50:21 -0500 Subject: [PATCH 07/12] Bump RELEASE for automatic rebuild --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 5acae4d..f097f48 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ LABEL MAINTAINER Rado Pitonak RUN dnf install -y --setopt=tsflags=nodocs nodejs npm && \ dnf -y clean all -ENV NAME=nodejs VERSION=0 RELEASE=3 ARCH=x86_64 +ENV NAME=nodejs VERSION=0 RELEASE=4 ARCH=x86_64 LABEL summary="Javascript runtime." \ name="$FGC/$NAME" \ From f5e746d887244ca4c2a6b671103002e5f0e6c90f Mon Sep 17 00:00:00 2001 From: Adam Miller Date: Tue, 27 Jun 2017 12:21:38 -0500 Subject: [PATCH 08/12] Bump RELEASE for automatic rebuild --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index f097f48..99636c1 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ LABEL MAINTAINER Rado Pitonak RUN dnf install -y --setopt=tsflags=nodocs nodejs npm && \ dnf -y clean all -ENV NAME=nodejs VERSION=0 RELEASE=4 ARCH=x86_64 +ENV NAME=nodejs VERSION=0 RELEASE=5 ARCH=x86_64 LABEL summary="Javascript runtime." \ name="$FGC/$NAME" \ From bcb8bd5a872fb56116cd467a61921ca1011ca175 Mon Sep 17 00:00:00 2001 From: Adam Miller Date: Thu, 6 Jul 2017 15:27:46 -0500 Subject: [PATCH 09/12] Bump RELEASE for automatic rebuild --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 99636c1..ab3e1be 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ LABEL MAINTAINER Rado Pitonak RUN dnf install -y --setopt=tsflags=nodocs nodejs npm && \ dnf -y clean all -ENV NAME=nodejs VERSION=0 RELEASE=5 ARCH=x86_64 +ENV NAME=nodejs VERSION=0 RELEASE=6 ARCH=x86_64 LABEL summary="Javascript runtime." \ name="$FGC/$NAME" \ From 2e3f9b6593f291ede38fe0f98807976f6fb36fc1 Mon Sep 17 00:00:00 2001 From: Adam Miller Date: Tue, 25 Jul 2017 14:55:06 -0500 Subject: [PATCH 10/12] Bump RELEASE for automatic rebuild --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index ab3e1be..1e7ad03 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ LABEL MAINTAINER Rado Pitonak RUN dnf install -y --setopt=tsflags=nodocs nodejs npm && \ dnf -y clean all -ENV NAME=nodejs VERSION=0 RELEASE=6 ARCH=x86_64 +ENV NAME=nodejs VERSION=0 RELEASE=7 ARCH=x86_64 LABEL summary="Javascript runtime." \ name="$FGC/$NAME" \ From 1490c3ff8a5132933a90b5781fb37cd164da4d54 Mon Sep 17 00:00:00 2001 From: Adam Miller Date: Thu, 24 Aug 2017 16:30:15 -0500 Subject: [PATCH 11/12] Bump RELEASE for automatic rebuild --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index 1e7ad03..c6ea9e8 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ LABEL MAINTAINER Rado Pitonak RUN dnf install -y --setopt=tsflags=nodocs nodejs npm && \ dnf -y clean all -ENV NAME=nodejs VERSION=0 RELEASE=7 ARCH=x86_64 +ENV NAME=nodejs VERSION=0 RELEASE=8 ARCH=x86_64 LABEL summary="Javascript runtime." \ name="$FGC/$NAME" \ From e81b0bdc9adb4f74da04be0fd7c9d2c2b0552b24 Mon Sep 17 00:00:00 2001 From: Adam Miller Date: Thu, 21 Sep 2017 12:19:16 -0500 Subject: [PATCH 12/12] Bump RELEASE for automatic rebuild --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index c6ea9e8..0853abd 100644 --- a/Dockerfile +++ b/Dockerfile @@ -15,7 +15,7 @@ LABEL MAINTAINER Rado Pitonak RUN dnf install -y --setopt=tsflags=nodocs nodejs npm && \ dnf -y clean all -ENV NAME=nodejs VERSION=0 RELEASE=8 ARCH=x86_64 +ENV NAME=nodejs VERSION=0 RELEASE=9 ARCH=x86_64 LABEL summary="Javascript runtime." \ name="$FGC/$NAME" \