Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

"Autoupdate" feature. Update S6. Shellcheck. #81

Open
wants to merge 15 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
11 changes: 7 additions & 4 deletions Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ RUN \
xmlstarlet \
uuid-runtime \
unrar \
cron \
&& \
\
# Fetch and extract S6 overlay
Expand Down Expand Up @@ -50,7 +51,12 @@ RUN \
EXPOSE 32400/tcp 8324/tcp 32469/tcp 1900/udp 32410/udp 32412/udp 32413/udp 32414/udp
VOLUME /config /transcode

ENV CHANGE_CONFIG_DIR_OWNERSHIP="true" \
ARG AUTOUPDATE=false
ARG TAG=beta
ARG URL=

ENV TAG=${TAG} \
CHANGE_CONFIG_DIR_OWNERSHIP="true" \
HOME="/config" \
TZ="UTC" \
midzelis marked this conversation as resolved.
Show resolved Hide resolved
\
Expand All @@ -64,9 +70,6 @@ ENV CHANGE_CONFIG_DIR_OWNERSHIP="true" \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
S6_BEHAVIOUR_IF_STAGE2_FAILS=2

ARG TAG=beta
ARG URL=

COPY root/ /

RUN \
Expand Down
11 changes: 7 additions & 4 deletions Dockerfile.arm64
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ RUN \
xmlstarlet \
uuid-runtime \
unrar \
cron \
&& \
\
# Fetch and extract S6 overlay
Expand Down Expand Up @@ -47,7 +48,12 @@ RUN \
EXPOSE 32400/tcp 8324/tcp 32469/tcp 1900/udp 32410/udp 32412/udp 32413/udp 32414/udp
VOLUME /config /transcode

ENV CHANGE_CONFIG_DIR_OWNERSHIP="true" \
ARG AUTOUPDATE=false
ARG TAG=beta
ARG URL=

ENV TAG=${TAG} \
CHANGE_CONFIG_DIR_OWNERSHIP="true" \
HOME="/config" \
TZ="UTC" \
\
Expand All @@ -61,9 +67,6 @@ ENV CHANGE_CONFIG_DIR_OWNERSHIP="true" \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
S6_BEHAVIOUR_IF_STAGE2_FAILS=2

ARG TAG=beta
ARG URL=

COPY root/ /

RUN \
Expand Down
11 changes: 7 additions & 4 deletions Dockerfile.armv7
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ RUN \
xmlstarlet \
uuid-runtime \
unrar \
cron \
&& \
\
# Fetch and extract S6 overlay
Expand Down Expand Up @@ -47,7 +48,12 @@ RUN \
EXPOSE 32400/tcp 8324/tcp 32469/tcp 1900/udp 32410/udp 32412/udp 32413/udp 32414/udp
VOLUME /config /transcode

ENV CHANGE_CONFIG_DIR_OWNERSHIP="true" \
ARG AUTOUPDATE=false
ARG TAG=beta
ARG URL=

ENV TAG=${TAG} \
CHANGE_CONFIG_DIR_OWNERSHIP="true" \
HOME="/config" \
TZ="UTC" \
\
Expand All @@ -61,9 +67,6 @@ ENV CHANGE_CONFIG_DIR_OWNERSHIP="true" \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
S6_BEHAVIOUR_IF_STAGE2_FAILS=2

ARG TAG=beta
ARG URL=

COPY root/ /

RUN \
Expand Down
11 changes: 7 additions & 4 deletions Dockerfile.i386
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ RUN \
xmlstarlet \
uuid-runtime \
unrar \
cron \
&& \
\
# Fetch and extract S6 overlay
Expand Down Expand Up @@ -47,7 +48,12 @@ RUN \
EXPOSE 32400/tcp 8324/tcp 32469/tcp 1900/udp 32410/udp 32412/udp 32413/udp 32414/udp
VOLUME /config /transcode

ENV CHANGE_CONFIG_DIR_OWNERSHIP="true" \
ARG AUTOUPDATE=false
ARG TAG=beta
ARG URL=

ENV TAG=${TAG} \
CHANGE_CONFIG_DIR_OWNERSHIP="true" \
HOME="/config" \
TZ="UTC" \
\
Expand All @@ -61,9 +67,6 @@ ENV CHANGE_CONFIG_DIR_OWNERSHIP="true" \
S6_CMD_WAIT_FOR_SERVICES_MAXTIME=0 \
S6_BEHAVIOUR_IF_STAGE2_FAILS=2

ARG TAG=beta
ARG URL=

COPY root/ /

RUN \
Expand Down
2 changes: 1 addition & 1 deletion dev/README.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
# Dev Helper Scripts

Unless you are making changes to the Dockerfile themselves, please ignore all the files here.
Unless you are making changes to the Dockerfile themselves, please ignore all the files here. In fact, your environment may be very different and these scripts may not work at all. They are provided only as a reference/starting point so you don't have to start from scratch. Heavy customizations are likely.
2 changes: 1 addition & 1 deletion dev/build.386.sh
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,4 @@ IFS=$'\n\t'

# This is just a helper script to quickly test local Dockerfile builds, please run setup-build-env.sh once

docker buildx build -o type=docker,name=pms-386 --load --platform linux/386 -f ../Dockerfile.i386 ..
docker buildx build -o type=docker,name=pms-386 --load --platform linux/386 --build-arg AUTOUPDATE=TRUE -f ../Dockerfile.i386 ..
2 changes: 1 addition & 1 deletion dev/build.amd64.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ IFS=$'\n\t'
# This is just a helper script to quickly test local Dockerfile builds, please run setup-build-env.sh once

# https://github.com/tianon/docker-brew-ubuntu-core/issues/183 explains why need to use --security-opt seccomp:unconfined
docker buildx build --security-opt seccomp:unconfined -o type=docker,name=pms-amd64 --platform linux/amd64 -f ../Dockerfile ..
docker buildx build --security-opt seccomp:unconfined -o type=docker,name=pms-amd64 --platform linux/amd64 --build-arg AUTOUPDATE=TRUE -f ../Dockerfile ..
2 changes: 1 addition & 1 deletion dev/build.arm32v7.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ IFS=$'\n\t'
# This is just a helper script to quickly test local Dockerfile builds, please run setup-build-env.sh once

# https://github.com/tianon/docker-brew-ubuntu-core/issues/183 explains why need to use --security-opt seccomp:unconfined
docker buildx build --security-opt seccomp:unconfined -o type=docker,name=pms-armv7 --load --platform linux/arm/v7 -f ../Dockerfile.armv7 ..
docker buildx build --security-opt seccomp:unconfined -o type=docker,name=pms-armv7 --load --platform linux/arm/v7 --build-arg AUTOUPDATE=TRUE -f ../Dockerfile.armv7 ..
2 changes: 1 addition & 1 deletion dev/build.arm64v8.sh
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,4 @@ IFS=$'\n\t'
# This is just a helper script to quickly test local Dockerfile builds, please run setup-build-env.sh once

# https://github.com/tianon/docker-brew-ubuntu-core/issues/183
docker buildx build --security-opt seccomp:unconfined -o type=docker,name=pms-arm64 --load --platform linux/arm64 -f ../Dockerfile.arm64 ..
docker buildx build --security-opt seccomp:unconfined -o type=docker,name=pms-arm64 --load --platform linux/arm64 --build-arg AUTOUPDATE=TRUE -f ../Dockerfile.arm64 ..
3 changes: 1 addition & 2 deletions dev/debug.arm64v8.sh
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,7 @@ IFS=$'\n\t'
# the container with "-it" rather, run it in background (so we get log output) then
# exec a bash process to enter the container.

trap "trap - SIGTERM && docker stop pms-armv7" SIGINT SIGTERM EXIT
trap "trap - SIGTERM && docker stop pms-arm64" SIGINT SIGTERM EXIT
docker run --rm --name pms-arm64 --platform linux/arm64 -e DEBUG=true pms-arm64:latest &
sleep 5
docker exec -it pms-arm64 bash

Empty file modified dev/setup-build-env.sh
100644 → 100755
Empty file.
23 changes: 23 additions & 0 deletions root/etc/plex/plex-install
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

DEBUG=${DEBUG:-}

# If we are debugging, enable trace
if [ "${DEBUG,,}" = "true" ]; then
set -x
fi

# shellcheck source=../../plex-common.sh
. /plex-common.sh

CACHED_URL=
[[ -r /config/install/plexmediaserver.url ]] && CACHED_URL=$(< /config/install/plexmediaserver.url)
if [ -n "$CACHED_URL" ] && [ -f /config/install/plexmediaserver.deb ]; then
echo "Installing previously downloaded plex version..."
installFromRawUrl "$CACHED_URL"
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this delete the deb file after install so as to not attempt to install it every time?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is by design. Containers lose all of the changes within them unless they are in a volume or mount. In autoupdate images, these will fetch but will not delete the installer, so when the container is restarted it doesn’t need to download it again. Technically, it doesn't NEED to be cached, but it might waste a lot of bandwidth. But, just in case someone wants to actually force an install, I'll add an env var FORCE_UPDATE to ignore the cache.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see what you are getting at. Though, wouldn't this also install the deb if the container is just restarted? In that case, it is likely installing the same version that is already installed. Likely the only way to avoid this is to parse the version out of the deb, compare with the installed version, and skip the install if they are the same.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually, my bad. I've been using docker run --rm for too long - forgot that container images are in fact persisted. Ok, then we don't need to cache the installer at all, and it actually simplifies things a lot.

else
echo "Downloading latest plex version..."
exec /etc/plex/plex-update
fi
33 changes: 19 additions & 14 deletions root/etc/plex/plex-update
Original file line number Diff line number Diff line change
Expand Up @@ -32,20 +32,12 @@ else
installedVersion="none"
fi

# Read set version
readVarFromConf "version" versionToInstall
if [ -z "${versionToInstall}" ]; then
echo "No version specified in install. Broken image"
exit 1
fi

# Short-circuit test of version before remote check to see if it's already installed.
if [ "${versionToInstall}" = "${installedVersion}" ]; then
exit 0
fi
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We have docker images which have a pre-installed PMS version that do not update. The above code effectively maintains that because the version is the full version of the PMS installed in the image (such as 1.32.4.7195-7c8f9d3b6). This behavior must be maintained for those images.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, this is a good call out. I was tripped up by using the version as a TAG and having TAG also be a build-arg.

I switched things up a bit: now, you can build the image with TAG=autoupdate (this obsoletes beta/public - but you can still build the images with public/beta tags - it will behave as if it was 'autoupdate' but it will ignore the AUTO_UPDATE_CHANNEL and will be hardcoded to 'beta' or 'public').


# Get updated version number
getVersionInfo "${versionToInstall}" "${token}" remoteVersion remoteFile
remoteVersion=
remoteFile=
remoteFileHashSha256=
getVersionInfo "${TAG}" "${token}" remoteVersion remoteFile remoteFileHashSha256

if [ -z "${remoteVersion}" ] || [ -z "${remoteFile}" ]; then
echo "Could not get update version"
Expand All @@ -54,9 +46,22 @@ fi

# Check if there's no update required
if [ "${remoteVersion}" = "${installedVersion}" ]; then
echo "$(date) Update check: no updates found."
exit 0
fi

# Do update process
echo "Attempting to upgrade to: ${remoteVersion}"
installFromUrl "${remoteFile}"
wasrunning=false
echo "$(date) Attempting to upgrade to: ${remoteVersion}"
if [ -d "/run/s6/legacy-services/plex" ]; then
wasrunning=true
echo "$(date) Bringing down Plex Media Server..."
s6-svc -wD -d /run/s6/legacy-services/plex
fi
echo "$(date) Downloading and installing..."
installFromUrl "${remoteFile}" "${remoteFileHashSha256}"
if [ "$wasrunning" = true ]; then
echo "$(date) Bringing up Plex Media Server..."
s6-svc -wU -u /run/s6/legacy-services/plex
fi
echo "$(date) Plex Successfully Updated!"
15 changes: 15 additions & 0 deletions root/etc/plex/service.cron.run
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

DEBUG=${DEBUG:-}

# If we are debugging, enable trace
if [ "${DEBUG,,}" = "true" ]; then
set -x
fi

# shellcheck source=../../plex-envvars
. /plex-envvars
printenv > /etc/environment
exec cron -f
midzelis marked this conversation as resolved.
Show resolved Hide resolved
25 changes: 14 additions & 11 deletions root/etc/plex/service.plex.run
Original file line number Diff line number Diff line change
@@ -1,20 +1,23 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

echo "Starting Plex Media Server."
home=~plex
export PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR="${PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR:-${home}/Library/Application Support}"
export PLEX_MEDIA_SERVER_HOME=/usr/lib/plexmediaserver
export PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS=6
export PLEX_MEDIA_SERVER_INFO_VENDOR=Docker
export PLEX_MEDIA_SERVER_INFO_DEVICE="Docker Container"
PLEX_MEDIA_SERVER_INFO_MODEL=$(uname -m)
export PLEX_MEDIA_SERVER_INFO_MODEL
PLEX_MEDIA_SERVER_INFO_PLATFORM_VERSION=$(uname -r)
export PLEX_MEDIA_SERVER_INFO_PLATFORM_VERSION
DEBUG=${DEBUG:-}

# If we are debugging, enable trace
if [ "${DEBUG,,}" = "true" ]; then
set -x
fi

# shellcheck source=../../plex-envvars
. /plex-envvars

if [ ! -d "${PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR}" ]; then
/bin/mkdir -p "${PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR}"
chown plex:plex "${PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR}"
fi

echo "$(date) Starting Plex Media Server $(dpkg-query -W -f='${Version}' plexmediaserver)"
echo

exec s6-setuidgid plex /usr/lib/plexmediaserver/Plex\ Media\ Server
16 changes: 15 additions & 1 deletion root/installBinary.sh
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,20 @@ mkdir -p /etc/cont-init.d
ln -s /etc/plex/plex-first-run /etc/cont-init.d/000-plex-first-run
ln -s /etc/plex/plex-hw-transcode-and-connected-tuner /etc/cont-init.d/010-plex-hw-transcode-and-connected-tuner
ln -s /etc/plex/plex-update /etc/cont-init.d/020-plex-update

if [ "${AUTOUPDATE,,}" = 'true' ]; then
echo "AUTOUPDATE requested, setting up cron service and scheduling plex-update"
mkdir -p /etc/services.d/cron ; ln -s /etc/plex/service.cron.run /etc/services.d/cron/run
# Specify bash as shell, add S6 commands to PATH
echo "SHELL=/bin/bash" > /etc/crontab
echo "$(env | grep PATH):/command" >> /etc/crontab
# Specify cron job: be nice to Plex servers - space out updates at 4:00am over 30m window
echo "0 4 * * * root perl -le 'sleep rand 30' ; /etc/plex/plex-update > /proc/1/fd/1 2>&1" >> /etc/crontab
echo "Removing plex-update from cont-init.d"
rm /etc/cont-init.d/020-plex-update
echo "Adding plex-install to cont-init.d"
ln -s /etc/plex/plex-install /etc/cont-init.d/099-plex-install
exit 0
fi
if [ -n "${URL}" ]; then
echo "Attempting to install from URL: ${URL}"
installFromRawUrl "${URL}"
Expand All @@ -31,4 +44,5 @@ elif [ "${TAG}" != "beta" ] && [ "${TAG}" != "public" ]; then

echo "Attempting to install: ${remoteVersion}"
installFromUrl "${remoteFile}"
rm -rf /config/install
fi
40 changes: 33 additions & 7 deletions root/plex-common.sh
Original file line number Diff line number Diff line change
Expand Up @@ -63,24 +63,50 @@ function getVersionInfo {
getVersionInfo_remoteVersion=$(echo "${versionInfo}" | sed -n 's/.*Release.*version="\([^"]*\)".*/\1/p')
# shellcheck disable=SC2034
getVersionInfo_remoteFile=$(echo "${versionInfo}" | sed -n 's/.*file="\([^"]*\)".*/\1/p')
# shellcheck disable=SC2034
getVersionInfo_remoteFileHashSha256=$(echo "${versionInfo}" | sed -n 's/.*fileHashSha256="\([^"]*\)".*/\1/p')
}


function installFromUrl {
installFromRawUrl "https://plex.tv/${1}"
installFromRawUrl "https://plex.tv/${1}" "${2}"
}

function installFromRawUrl {
local remoteFile="$1"
curl -J -L -o /tmp/plexmediaserver.deb "${remoteFile}"
local last=$?
local expectedSha256="${2:-}"

# if download url matches and donwload is cached, then install it without download
[[ -r /config/install/plexmediaserver.url ]] && oldurl=$(< /config/install/plexmediaserver.url)
if [ "$remoteFile" = "${oldurl:-}" ] && [ -f /config/install/plexmediaserver.deb ]; then
install "$remoteFile"
return $?
fi

curl --create-dirs -J -L -o /config/install/tmp/plexmediaserver.deb "${remoteFile}"
local last=$?
local sha256;
sha256=$(sha256sum /config/install/tmp/plexmediaserver.deb | awk '{ print $1 }')
echo "$sha256" > /config/install/tmp/plexmediaserver.sha256
echo "$remoteFile" > /config/install/tmp/plexmediaserver.url
# test if deb file size is ok, or if download failed
if [[ "$last" -gt "0" ]] || [[ $(stat -c %s /tmp/plexmediaserver.deb) -lt 10000 ]]; then
echo "Failed to fetch update"
if [[ "$last" -gt "0" ]] || [[ $(stat -c %s /config/install/tmp/plexmediaserver.deb) -lt 10000 ]]; then
rm -rf /config/install/tmp
echo "Failed to fetch update: curl returned $last"
exit 1
fi
# compare sha256, if provided
if [ -n "$expectedSha256" ] && [ ! "$expectedSha256" = "$sha256" ]; then
rm -rf /config/install/tmp
echo "Failed to fetch update: sha256sum does not match: expected=$expectedSha256 actual=$sha256"
exit 1
fi

dpkg -i --force-confold --force-architecture /tmp/plexmediaserver.deb
rm -f /tmp/plexmediaserver.deb
# looks good, move tmp into position
mv /config/install/tmp/* /config/install && rm -rf /config/install/tmp
install "$remoteFile"
}

function install {
dpkg -i --force-confold --force-architecture /config/install/plexmediaserver.deb
}
midzelis marked this conversation as resolved.
Show resolved Hide resolved
14 changes: 14 additions & 0 deletions root/plex-envvars
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/bash
set -euo pipefail
IFS=$'\n\t'

home=~plex
model=$(uname -m)
version=$(uname -r)
export PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR="${PLEX_MEDIA_SERVER_APPLICATION_SUPPORT_DIR:-${home}/Library/Application Support}"
export PLEX_MEDIA_SERVER_HOME=/usr/lib/plexmediaserver
export PLEX_MEDIA_SERVER_MAX_PLUGIN_PROCS=6
export PLEX_MEDIA_SERVER_INFO_VENDOR=Docker
export PLEX_MEDIA_SERVER_INFO_DEVICE="Docker Container"
export PLEX_MEDIA_SERVER_INFO_MODEL="$model"
export PLEX_MEDIA_SERVER_INFO_PLATFORM_VERSION="$version"
midzelis marked this conversation as resolved.
Show resolved Hide resolved
Loading