Skip to content
Merged
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
13 changes: 7 additions & 6 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@ jobs:
build:
runs-on: ${{ matrix.runner }}
outputs:
# image-arm64: ${{ steps.gen-output.outputs.image-arm64 }}
image-arm64: ${{ steps.gen-output.outputs.image-arm64 }}
image-x64: ${{ steps.gen-output.outputs.image-x64 }}
strategy:
fail-fast: false
matrix:
runner:
- ubuntu-24.04
# - ubuntu-24.04-arm
- ubuntu-24.04-arm
steps:
- name: Checkout code
uses: actions/checkout@v4
Expand Down Expand Up @@ -77,7 +77,7 @@ jobs:
runs-on: ubuntu-24.04
needs: build
env:
# DOCKER_APP_IMAGE_ARM64: ${{ needs.build.outputs.image-arm64 }}
DOCKER_APP_IMAGE_ARM64: ${{ needs.build.outputs.image-arm64 }}
DOCKER_APP_IMAGE_X64: ${{ needs.build.outputs.image-x64 }}
outputs:
image: ${{ steps.meta.outputs.tags }}
Expand Down Expand Up @@ -106,7 +106,7 @@ jobs:
run: |
docker buildx imagetools create \
--tag "$DOCKER_METADATA_OUTPUT_TAGS" \
"$DOCKER_APP_IMAGE_X64"
"$DOCKER_APP_IMAGE_ARM64" "$DOCKER_APP_IMAGE_X64"

test:
runs-on: ubuntu-24.04
Expand Down Expand Up @@ -143,7 +143,7 @@ jobs:
- name: Run tests
if: ${{ always() }}
run: |
docker compose run app /opt/app/test/run_tests.py
docker compose exec app venv/bin/python test/run_tests.py
env:
WOWZA_LICENSE_KEY: ${{ secrets.WOWZA_LICENSE_KEY }}

Expand All @@ -153,7 +153,8 @@ jobs:
docker compose cp app:/opt/app/artifacts ./
docker compose logs > artifacts/docker-compose-services.log
docker compose config > artifacts/docker-compose.merged.yml

env:
WOWZA_LICENSE_KEY: EZZZZ-INTEN-TIONA-LLYRE-DACT-EDFROM-BUILDLOGS
- name: Upload the test report
if: ${{ always() }}
uses: actions/upload-artifact@v4
Expand Down
53 changes: 41 additions & 12 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
# Target: base
#

FROM wowzamedia/wowza-streaming-engine-linux:4.8.25 AS base
FROM wowzamedia/wowza-streaming-engine-linux:4.9.6 AS base

# =============================================================================
# Ports
Expand All @@ -27,28 +27,34 @@ RUN apt-get update -qq
RUN apt-get install -y --no-install-recommends \
curl \
dnsutils \
iputils-ping \
lsb-core
iputils-ping

# =============================================================================
# Java

# The upstream Wowza image ships with OpenJDK 9.0.4+11, which is not a
# long-term support release and, importantly, doesn't know about containers:
# https://www.wowza.com/community/t/creating-a-production-worthy-docker-image/53957/3
# The upstream Wowza image may ship with an outdated OpenJDK, and
# previously (even as of 4.8.25) did not include an LTS release or
# one that was aware of containers.
#
# Luckily, Wowza supports manually replacing the JRE:
# https://www.wowza.com/docs/manually-install-and-troubleshoot-java-on-wowza-streaming-engine
# ... so this updates to the latest version of OpenJDK 21 (LTS).
#
# (Unfortunately, this by itself isn't enough to get Wowza to properly
# calculate its own max heap size, so we still need to set that explicitly
# in Tune.xml. Possibly a future version of Wowza will be clever enough to
# use -XX:MaxRAMPercentage instead.)

RUN apt-get install -y --no-install-recommends openjdk-11-jre-headless
RUN apt-get install -y --no-install-recommends openjdk-21-jre-headless

RUN rm -rf /usr/local/WowzaStreamingEngine/java
RUN ln -s /usr/lib/jvm/java-11-openjdk-amd64 /usr/local/WowzaStreamingEngine/java

# for some reason, OpenJDK's default directory includes the architecture
# name and does not symlink it to something more straightforward like
# /usr/lib/jvm/java-21-openjdk so we have to detect the architecture

SHELL ["/bin/bash", "-o", "pipefail", "-c"]
RUN arch=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) ln -s "/usr/lib/jvm/java-21-openjdk-${arch}" /usr/local/WowzaStreamingEngine/java

# =============================================================================
# Global configuration
Expand All @@ -66,6 +72,10 @@ RUN usermod -u $APP_UID $APP_USER && \
# transfer now-orphaned files to new wowza user (-h to chown symlinks)
RUN find / -xdev -nouser -exec chown -h $APP_USER:$APP_USER {} \;

# set variables to be used by envsubst to overwrite the default wowza config
ENV SUPERVISORD_PID_FILE=/tmp/supervisord.pid
ENV SUPERVISORD_SOCKET_FILE=/tmp/supervisor.sock

# =============================================================================
# Set working directory

Expand All @@ -74,12 +84,13 @@ WORKDIR /opt/app
# =============================================================================
# Tests

RUN apt-get install -y --no-install-recommends python3-pip
RUN pip3 install unittest-xml-reporting
RUN apt-get install -y --no-install-recommends python3-pip python3-venv
RUN python3 -m venv venv
RUN venv/bin/pip3 install unittest-xml-reporting

COPY --chown=$APP_USER test /opt/app/test

# Put artifacts where Jenkins can get at them
# Put artifacts where Github Actions can get at them
RUN mkdir /opt/app/artifacts && \
chown $APP_USER:$APP_USER /opt/app/artifacts

Expand All @@ -96,8 +107,22 @@ RUN for app in vod live; \
# Copy our scripts, configs, templates, etc. into the container
COPY --chown=$APP_USER WowzaStreamingEngine /usr/local/WowzaStreamingEngine
COPY --chown=$APP_USER log4j-templates /opt/app/log4j-templates
COPY --chown=$APP_USER supervisor_templates /opt/app/supervisor_templates
COPY --chown=$APP_USER bin /opt/app/bin

# create supervisord config files from templates
RUN apt-get install -y --no-install-recommends gettext
RUN envsubst < \
supervisor_templates/supervisord.conf.tmpl > \
/etc/supervisor/supervisord.conf
RUN envsubst < \
supervisor_templates/conf.d/WowzaStreamingEngine.conf.tmpl > \
/etc/supervisor/conf.d/WowzaStreamingEngine.conf
RUN envsubst < \
supervisor_templates/conf.d/WowzaStreamingEngineManager.conf.tmpl > \
/etc/supervisor/conf.d/WowzaStreamingEngineManager.conf


# =============================================================================
# Additional Java libraries

Expand Down Expand Up @@ -138,7 +163,11 @@ RUN apt-get remove -y zip

USER $APP_USER

# =============================================================================
# Healthcheck
HEALTHCHECK --interval=5s --timeout=5s --start-period=10s --retries=10 CMD curl -s http://localhost:8087 > /dev/null || exit 1

# =============================================================================
# Default command

CMD ["/opt/app/bin/docker-entrypoint.sh"]
ENTRYPOINT ["/opt/app/bin/docker-entrypoint.sh"]
65 changes: 65 additions & 0 deletions WowzaStreamingEngine/bin/startup.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/bin/bash
# this is a BerkeleyLibrary modified version of the WSE startup script

# check for root access. If not, put up message and exit
# if [ "$(/usr/bin/id -u)" -ne "0" ] ; then
# echo "The Wowza Streaming Engine requires root access to start. Please run script again using sudo."
# exit
# fi

systemctl >> /dev/null 2>&1
if [ $? -eq 0 ]; then
# Restart XRM service
SERVICE_NAME="xrmd.service"
systemctl list-units --full -all | grep -Fq $SERVICE_NAME

if [ $? -eq 0 ]; then
echo "Restarting XRM service"
systemctl restart $SERVICE_NAME
. /opt/xilinx/xcdr/setup.sh
fi
fi

. /usr/local/WowzaStreamingEngine/bin/setenv.sh
mode=standalone
if [ "$#" -eq 1 ];
then
mode=$1
fi

#chmod 600 /usr/local/WowzaStreamingEngine/conf/jmxremote.password
#chmod 600 /usr/local/WowzaStreamingEngine/conf/jmxremote.access

# NOTE: Here you can configure the JVM's built in JMX interface.
# See the "Server Management Console and Monitoring" chapter
# of the "User's Guide" for more information on how to configure the
# remote JMX interface in the [install-dir]/conf/Server.xml file.

JMXOPTIONS=-Dcom.sun.management.jmxremote=true
#JMXOPTIONS="$JMXOPTIONS -Djava.rmi.server.hostname=192.168.1.7"
#JMXOPTIONS="$JMXOPTIONS -Dcom.sun.management.jmxremote.port=1099"
#JMXOPTIONS="$JMXOPTIONS -Dcom.sun.management.jmxremote.authenticate=true"
#JMXOPTIONS="$JMXOPTIONS -Dcom.sun.management.jmxremote.ssl=false"
#JMXOPTIONS="$JMXOPTIONS -Dcom.sun.management.jmxremote.password.file=$WMSCONFIG_HOME/conf/jmxremote.password"
#JMXOPTIONS="$JMXOPTIONS -Dcom.sun.management.jmxremote.access.file=$WMSCONFIG_HOME/conf/jmxremote.access"

ulimit -n 64000 > /dev/null 2>&1

rc=144
while [ $rc -eq 144 ]
do

WMSTUNE_OPTS=`$WMSAPP_HOME/bin/tune.sh $mode`
export LD_PRELOAD=`$WMSAPP_HOME/bin/ldpreload.sh`

# log interceptor com.wowza.wms.logging.LogNotify - see Javadocs for ILogNotify

$_EXECJAVA $WMSTUNE_OPTS $JMXOPTIONS -Dorg.slf4j.simpleLogger.defaultLogLevel=warn -Dcom.wowza.wms.runmode="$mode" -Dcom.wowza.wms.native.base="linux" -Dlog4j.configurationFile="$WMSCONFIG_HOME/conf/log4j2-config.xml" -Dcom.wowza.wms.AppHome="$WMSAPP_HOME" -Dcom.wowza.wms.ConfigURL="$WMSCONFIG_URL" -Dcom.wowza.wms.ConfigHome="$WMSCONFIG_HOME" -cp $WMSAPP_HOME/bin/wms-bootstrap.jar com.wowza.wms.bootstrap.Bootstrap start

rc=$?
if [ $rc -ge 10 ] && [ $rc -le 15 ] ; then
WSE_EXIT_CODE=$rc
$_EXECJAVA $WMSTUNE_OPTS $JMXOPTIONS -Dcom.wowza.wms.runmode="$mode" -Dcom.wowza.wms.native.base="linux" -Dlog4j.configurationFile="$WMSCONFIG_HOME/conf/log4j2-config.xml" -Dcom.wowza.wms.AppHome="$WMSAPP_HOME" -Dcom.wowza.wms.ConfigURL="$WMSCONFIG_URL" -Dcom.wowza.wms.ConfigHome="$WMSCONFIG_HOME" -cp $WMSAPP_HOME/bin/wms-bootstrap.jar com.wowza.wms.bootstrap.Bootstrap startLicenseUpdateServer
rc=$?
fi
done
65 changes: 10 additions & 55 deletions bin/docker-entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,6 @@
# Streaming Media Engine Manager in subprocesses, and waits
# for them to exit.

# TODO: now that we're running the manager and server in the same container,
# consider getting rid of this (or simplifying it) in favor of the
# upstream container's /sbin/entrypoint.sh, which uses supervisord

BASENAME=$(basename ${BASH_SOURCE})
echo "${BASENAME} running"

Expand All @@ -26,58 +22,17 @@ if [ ! -z "${WOWZA_ENABLE_DOCUMENTATION_SERVER}" ]; then
"${WOWZA_BIN}"/enable-documentation-server.sh
fi

# ########################################
# Start server and manager in background

# shellcheck source=start-server.sh
echo "Invoking ${WOWZA_BIN}"/start-server.sh
"${WOWZA_BIN}"/start-server.sh &
SERVER_PID=$!
echo "SERVER_PID=${SERVER_PID}"

echo "Invoking ${WMSMGR_HOME}"/bin/startmgr.sh
"${WMSMGR_HOME}"/bin/startmgr.sh &
MANAGER_PID=$!
echo "MANAGER_PID=${MANAGER_PID}"

# ########################################
# Make sure child processes exit cleanly

ensure_clean_exit() {
trap - SIGINT SIGTERM # clear the trap
echo "Killing process $$ and all subprocesses"
kill -- -$$
}

sigint_received() {
echo "SIGINT received"
ensure_clean_exit
}

sigterm_received() {
echo "SIGTERM received"
ensure_clean_exit
}
# load secrets into wowza env vars. by default, the Wowza entrypoint
# creates the keyfile in question, which is why we pass the variable
# in using a different name.
. "${WOWZA_BIN}/secrets.sh"

trap sigint_received SIGINT
trap sigterm_received SIGTERM
export WSE_MGR_USER=$WOWZA_MANAGER_USER
export WSE_MGR_PASS=$WOWZA_MANAGER_PASSWORD
export WSE_LIC=$WOWZA_LICENSE_KEY

# ########################################
# Wait for manager or server to exit

wait -n
EXIT_STATUS=$?

# Whichever exited, kill the other one
if ! kill -0 $SERVER_PID 2> /dev/null; then
echo "Wowza Streaming Engine (PID ${SERVER_PID}) exited with ${EXIT_STATUS}"
echo "Stopping Wowza Streaming Engine Manager (PID ${MANAGER_PID})"
kill -- -$MANAGER_PID 2> /dev/null
elif ! kill -0 $MANAGER_PID 2> /dev/null; then
echo "Wowza Streaming Engine Manager (PID ${MANAGER_PID}) exited with ${EXIT_STATUS}"
echo "Stopping Wowza Streaming Engine (PID ${SERVER_PID})"
kill -- -$SERVER_PID 2> /dev/null
fi
# Start server and manager by handing off to Wowza's entrypoint

echo "Exiting with status ${EXIT_STATUS}"
exit $EXIT_STATUS
echo Invoking Wowza\'s /sbin/entrypoint.sh
exec /sbin/entrypoint.sh "$@"
2 changes: 1 addition & 1 deletion docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ services:
- WOWZA_MANAGER_USER=${WOWZA_MANAGER_USER}
- WOWZA_MANAGER_PASSWORD=${WOWZA_MANAGER_PASSWORD}
- WOWZA_ENABLE_DOCUMENTATION_SERVER=yes
# Uncommment these when editing / running tests locally.
# Uncomment these when editing / running tests locally.
# (Note: slows performance on macOS Catalina, for some reason.)
# volumes:
# - ./test:/opt/app/test
Expand Down
Binary file removed lib-ucblit/log4j-api-2.17.0.jar
Binary file not shown.
Binary file removed lib-ucblit/log4j-core-2.17.0.jar
Binary file not shown.
Binary file removed lib-ucblit/log4j-layout-template-json-2.17.0.jar
Binary file not shown.
Binary file added lib-ucblit/log4j-layout-template-json-2.23.1.jar
Binary file not shown.
10 changes: 10 additions & 0 deletions supervisor_templates/conf.d/WowzaStreamingEngine.conf.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[program:WowzaStreamingEngine]
priority=10
directory=/usr/local/WowzaStreamingEngine/bin
command=/usr/local/WowzaStreamingEngine/bin/startup.sh
user=${APP_USER}
autostart=true
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes = 0
redirect_stderr=true
10 changes: 10 additions & 0 deletions supervisor_templates/conf.d/WowzaStreamingEngineManager.conf.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
[program:WowzaStreamingEngineManager]
priority=20
directory=/usr/local/WowzaStreamingEngine/manager/bin
command=/usr/local/WowzaStreamingEngine/manager/bin/startmgr.sh
user=${APP_USER}
autostart=true
autorestart=true
stdout_logfile=/dev/fd/1
stdout_logfile_maxbytes = 0
redirect_stderr=true
30 changes: 30 additions & 0 deletions supervisor_templates/supervisord.conf.tmpl
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
; supervisor config file

[unix_http_server]
file=${SUPERVISORD_SOCKET_FILE} ; (the path to the socket file)
chmod=0700 ; socket file mode (default 0700)

[supervisord]
logfile=/dev/null ; supervisor logs to stdout
logfile_maxbytes = 0 ; forcibly disable log rotation
pidfile=${SUPERVISORD_PID_FILE} ; (supervisord pidfile;default supervisord.pid)
childlogdir=/usr/local/supervisor ; ('AUTO' child log dir, default $TEMP)
user=${APP_USER}

; the below section must remain in the config file for RPC
; (supervisorctl/web interface) to work, additional interfaces may be
; added by defining them in separate rpcinterface: sections
[rpcinterface:supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface:make_main_rpcinterface

[supervisorctl]
serverurl=unix://${SUPERVISORD_SOCKET_FILE} ; use a unix:// URL for a unix socket

; The [include] section can just contain the "files" setting. This
; setting can list multiple files (separated by whitespace or
; newlines). It can also contain wildcards. The filenames are
; interpreted as relative to this file. Included files *cannot*
; include files themselves.

[include]
files = /etc/supervisor/conf.d/*.conf
6 changes: 3 additions & 3 deletions test/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,13 +34,13 @@ From the project root directory, in another terminal, you can:

## Testing in a standalone container

Alternatively, you can run the tests and server in the same container (as the Jenkins build
Alternatively, you can run the tests and server in the same container (as the Github Actions build
does). Note that this does not require exposing any ports to the host.

```sh
docker-compose run wowza /opt/app/test/run_tests.py
docker-compose run app /opt/app/test/run_tests.py
```

In this case, remember to rebuild the `wowza` container before testing, to make sure your latest
In this case, remember to rebuild the `app` container before testing, to make sure your latest
additions to the test suite are included.

Loading