Skip to content
This repository has been archived by the owner on Nov 8, 2019. It is now read-only.

This is to build static content services on OpenShift #208

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 79 additions & 0 deletions s2i-nginx/.s2i/bin/assemble
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
#!/bin/bash -e
#
# S2I assemble script for the 's2i-nginx' image.
# The 'assemble' script builds your application source 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 's2i-nginx' assemble script is executed with '-h' flag,
# print the usage.
exec /usr/libexec/s2i/usage
fi

NGINX_STATIC_DIR=${NGINX_STATIC_DIR-html}
NGINX_CONF_FILE=${NGINX_CONF_FILE-}
NGINX_CONF_DIR=${NGINX_CONF_DIR-conf.d}
NGINX_AUX_DIR=${NGINX_AUX_DIR-aux}

copy_static_files() {
echo "---> Copying static files"
if [ -d /tmp/src/"${NGINX_STATIC_DIR}" ]; then
cp -Rf /tmp/src/"${NGINX_STATIC_DIR}"/. ./html
else
cp -Rf /tmp/src/. ./html
fi
}

copy_default_config() {
cp /opt/app-root/etc/nginx.server.sample.conf /opt/app-root/etc/nginx.conf.d/default.conf
}

copy_server_configs() {
echo "---> Copying nginx config"
rm /opt/app-root/etc/nginx.conf.d/default.conf
if [ ! -d /tmp/src/"${NGINX_STATIC_DIR}" ]; then
copy_default_config
elif [ -n "${NGINX_SERVER_CONF_FILE}" -a -f /tmp/src/"${NGINX_SERVER_CONF_FILE}" ]; then
cp /tmp/src/"${NGINX_SERVER_CONF_FILE}" /opt/app-root/etc/nginx.conf.d
elif [ -n "${NGINX_CONF_DIR}" -a -d /tmp/src/"${NGINX_CONF_DIR}" ]; then
cp -Rf /tmp/src/"${NGINX_CONF_DIR}"/. /opt/app-root/etc/nginx.conf.d
else
copy_default_config
fi
}

copy_aux_dir() {
if [ -d /tmp/src/"${NGINX_AUX_DIR}" ]; then
echo "---> Copying auxiliary files"
mkdir /opt/app-root/etc/aux
cp -Rf /tmp/src/"${NGINX_AUX_DIR}"/. /opt/app-root/etc/aux
fi
}

test_config() {
echo "---> testing config"
if ! $NGINX_BASE_DIR/usr/sbin/nginx -c /opt/app-root/etc/nginx.conf -t ; then
echo "nginx configuration not valid."
echo
for f in /opt/app-root/etc/nginx.conf.d/*; do
echo "==> $f <=="
cat $f
done
exit 1
fi
}

cleanup() {
echo "---> cleanup"
rm -f /opt/app-root/run/nginx.pid $NGINX_VAR_DIR/log/nginx/error.log
}

copy_static_files
copy_server_configs
copy_aux_dir

test_config
cleanup
10 changes: 10 additions & 0 deletions s2i-nginx/.s2i/bin/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/bash -e
#
# S2I run script for the 's2i-nginx' 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
#
NGINX_CONF=${NGINX_CONF-/opt/app-root/etc/nginx.conf}
exec /usr/sbin/nginx -c "$NGINX_CONF"
12 changes: 12 additions & 0 deletions s2i-nginx/.s2i/bin/usage
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/bin/bash -e
cat <<EOF
This is the s2i-nginx S2I image:
To use it, install S2I: https://github.com/openshift/source-to-image

Sample invocation:

s2i build git://<source code> s2i-nginx <application image>

You can then run the resulting image via:
docker run <application image>
EOF
38 changes: 38 additions & 0 deletions s2i-nginx/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
FROM fedora

MAINTAINER http://fedoraproject.org/wiki/Cloud

ENV NGINX_VERSION="1.8"

LABEL io.k8s.description="Platform for building nginx-based application (aka static content)" \
io.k8s.display-name="Nginx 1.8 builder" \
io.openshift.expose-services="8080:http" \
io.openshift.tags="builder,nginx,nginx18" \
Name="fedora-cloud/s2i-nginx" \
Version="1.8" \
Release="1" \
Architecture="x86_64"

RUN dnf install --setopt=tsflags=nodocs -y bcrypt nginx && \
dnf update -y && \
dnf clean all -y && \
mkdir -p /opt/app-root/etc/nginx.conf.d && \
chmod -R a+rx /var/lib/nginx && \
chmod -R a+rwX /var/lib/nginx/tmp \
/var/log \
/var/run

ENV STI_SCRIPTS_PATH="/usr/libexec/s2i" \
STI_SCRIPTS_URL="image:///usr/libexec/s2i"

COPY ./etc/ /opt/app-root/etc
COPY ./.s2i/bin/ ${STI_SCRIPTS_PATH}

RUN cp /opt/app-root/etc/nginx.server.sample.conf /opt/app-root/etc/nginx.conf.d/default.conf && \
chown -R 1001:1001 /opt/app-root

USER 1001

EXPOSE 8080

CMD ["usage"]
10 changes: 10 additions & 0 deletions s2i-nginx/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@

IMAGE_NAME = s2i-nginx

build:
docker build -t $(IMAGE_NAME) .

.PHONY: test
test:
docker build -t $(IMAGE_NAME)-candidate .
IMAGE_NAME=$(IMAGE_NAME)-candidate test/run
43 changes: 43 additions & 0 deletions s2i-nginx/Readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
# Source-to-image builder for static nginx containers

## Basic use case

Have a git repo with a directory `html` (or `NGINX_STATIC_DIR`), in which all
static files to serve are.

s2i-nginx will take all files within, copy them into the docker image and take
a basic nginx config that will simply serve these files.

If there is no `html` directory, it will just copy all files in the repo.
In that case you will not be able to customize the nginx config.


## Configuring nginx

You can supply a nginx.conf-snippet that will be used by the built container.

If there is a directory `conf.d` containing (possibly multiple) nginx `server`
snippets these will be used. It will _not_ copy the default config, so be
sure to include the right files. See `etc/nginx.server.sample.conf` for the
default config.


## Auxiliary files

You can put auxiliary files in a directory `aux` (or `NGINX_AUX_DIR`) to copy
them to the resulting image, e.g. htpasswd files.

These will be copied to `/opt/app-root/etc/aux`.


## Environment variables

There are some environment variables you can set to influence **build** behavior.

`NGINX_STATIC_DIR` sets the repo subdir to use for static files, default
`html`.

Either `NGINX_CONF_FILE` sets a config snippet to use or `NGINX_CONF_DIR`
will copy config from this dir (defaults to `conf.d`).

`NGINX_AUX_DIR` sets the aux directory for auxiliary files.
19 changes: 19 additions & 0 deletions s2i-nginx/etc/nginx.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
worker_processes 1;
pid /opt/app-root/run/nginx.pid;
error_log stderr notice;
daemon off;
events {
worker_connections 1024;
}
http {
include /etc/opt/rh/rh-nginx18/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log off;
sendfile on;
keepalive_timeout 65;

include /opt/app-root/etc/nginx.conf.d/*.conf;
}
16 changes: 16 additions & 0 deletions s2i-nginx/etc/nginx.server.sample.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
server {
listen 8080;
server_name localhost;
location / {
root /opt/app-root/src/html;
index index.html index.htm;
}
error_page 404 /404.html;
location = /40x.html {
root /opt/app-root/src/html;
}
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root /opt/app-root/src/html;
}
}
154 changes: 154 additions & 0 deletions s2i-nginx/test/run
Original file line number Diff line number Diff line change
@@ -0,0 +1,154 @@

#!/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-s2i-nginx-candidate}

# Determining system utility executables (darwin compatibility check)
READLINK_EXEC="readlink"
MKTEMP_EXEC="mktemp"
if (echo "$OSTYPE" | egrep -qs '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="--force-pull=false -s ${scripts_url} --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() {
docker inspect --format="{{ .NetworkSettings.IPAddress }}" $(cat $cid_file)
}

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..."
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):${test_port}/"
if (echo "$OSTYPE" | egrep -qs 'darwin'); then
echo "Warning for OSX users: if you can't access the container's IP ${container_ip} directly (because you use boot2docker for example)"
echo "you should run the curl command in a container, for example using:"
echo "docker run --rm -it sequenceiq/alpine-curl curl -s -w %{http_code} -o /dev/null http://$(container_ip):${test_port}/"
fi
response_code=$(curl -s -w %{http_code} -o /dev/null http://$(container_ip):${test_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