Install STKO in docker and add to supervisord

This commit is contained in:
Nathan Franklin 2019-08-28 09:51:26 -05:00
parent 67121f5fd6
commit 669d0df55b
6 changed files with 481 additions and 8 deletions

View File

@ -105,17 +105,42 @@ FROM system
COPY --from=builder /src/web/dist/ /usr/local/lib/web/frontend/ COPY --from=builder /src/web/dist/ /usr/local/lib/web/frontend/
# Install QGIS # Install STKO
RUN apt update \
&& apt upgrade -y \
&& apt install build-essential -y
RUN apt update \ RUN apt update \
&& apt install -y \ && apt install -y \
xterm \ python3-dev \
&& apt autoclean \ tcl8.6-dev \
&& apt autoremove \ tk8.6-dev \
&& rm -rf /var/lib/apt/lists/* libtogl-dev \
libglu1-mesa-dev \
freeglut3-dev \
mesa-common-dev \
mesa-utils \
libxi-dev \
libxmu-dev \
xterm
# Add our STKO (currently using glxgears as example) RUN apt update \
RUN apt update && apt-get install -y mesa-utils && apt install -y \
libxkbcommon-x11-0
# Add stko executable
ADD STKO-Install /STKO-Install
# Use/overwrite script so that it uses qt libs that will be installed by online installer
COPY STKO.sh /STKO-Install/STKO.sh
# Install qt 5.12.4 using online installer
COPY qt_install_utils/ /qt_temp
ADD http://download.qt.io/official_releases/qt/5.12/5.12.4/qt-opensource-linux-x64-5.12.4.run /qt_temp/qt-opensource-linux-x64-5.12.4.run
RUN chmod +x /qt_temp/qt-opensource-linux-x64-5.12.4.run
RUN /qt_temp/qt-opensource-linux-x64-5.12.4.run --script /qt_temp/qt-installer.qs -platform minimal
RUN rm -rf /qt_temp
COPY image / COPY image /
EXPOSE 6080 EXPOSE 6080

17
README_STKO.md Normal file
View File

@ -0,0 +1,17 @@
STKO app
--------
Here are some notes on this app's image.
Building Docker image
================
Get STKO-Install.zip from developers and unzip into this diretory
```
docker build -t tagname .
```
Other files of interest used in image
=========================
STKO.sh is an edited version of STKO-Install/STKO.sh (provided by STKO devs) which uses a system-installed qt version instead of the libs they provided
`qt_install_utils/qt-installer.qs` is an input script to online qt installer (see Dockerfile for more details on how its used)
`qt_install_utils/extract-qt-installer` can be used to see a list of modules which might be helpful when editing qt-installer.qs (`./extract-qt-installer --list qt-opensource-linux-x64-5.12.4.run`)

25
STKO.sh Executable file
View File

@ -0,0 +1,25 @@
#!/bin/sh
appname=`basename $0 | sed s,\.sh$,,`
dirname=`dirname $0`
tmp="${dirname#?}"
if [ "${dirname%$tmp}" != "/" ]; then
dirname=$PWD/$dirname
fi
core=$dirname/lib/core
coredep=$dirname/lib/coredep
export QTTOOLDIR=/opt/Qt5.12.4/5.12.4/gcc_64/bin
export QTLIBDIR=/opt/Qt5.12.4/5.12.4/gcc_64/lib
LD_LIBRARY_PATH=$dirname:$core:$coredep:$QTLIBDIR:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
#export QT_DEBUG_PLUGINS=1
#echo "$0 = "$0
#echo "appname = "$appname
#echo "dirname = "$dirname
#echo "tmp = "$tmp
echo "LD_LIBRARY_PATH = "$LD_LIBRARY_PATH
$dirname/$appname "$@"

View File

@ -63,7 +63,7 @@ stdout_logfile=/var/log/novnc.log
[program:stko] [program:stko]
priority=35 priority=35
directory=/home/ubuntu/mydata directory=/home/ubuntu/mydata
command=xterm -r -ls -geometry 80x24+10+10 -title '*** Exit this window to kill your QGIS session ***' -e 'xterm' command=xterm -r -ls -geometry 80x24+10+10 -title '*** Exit this window to kill your STKO session ***' -e '/STKO-Install/STKO.sh'
user=ubuntu user=ubuntu
autostart=true autostart=true
autorestart=false autorestart=false

View File

@ -0,0 +1,340 @@
#!/bin/bash
# QT-CI Project
# License: Apache-2.0
# https://github.com/benlau/qtci
function usage() {
echo "Usage:"
echo "extract-qt-installer qt-installer output_path"
echo "extract-qt-installer --list-packages qt-installer"
exit -1
}
LIST_PACKAGES=0
getopt --test > /dev/null 2>&1
GETOPT_RET_CODE=$?
set -e #quit on error
if [ "$GETOPT_RET_CODE" != "4" ]
then
echo "Warning: gnu-getopt is not installed. Long parameter like '--list-package' will not be working. Please install gnu-getopt by 'brew install gnu-getopt'"
else
OPTS=`getopt -o l --long list-packages --long disable-progress-report -n "extract-qt-installer" -- "$@"`
eval set -- "$OPTS"
while true
do
case "$1" in
--list-packages)
LIST_PACKAGES=1
shift;;
--disable-progress-report)
DISABLE_PROGRESS_REPORT=1
shift;;
--) shift;break;;
*) shift;;
esac
done
fi
export PATH=$PATH:$PWD
export WORKDIR=$PWD
INSTALLER=$1
OUTPUT=$2
SCRIPT="$(mktemp /tmp/tmp.XXXXXXXXX)"
PACKAGES=$QT_CI_PACKAGES
if [ $LIST_PACKAGES -gt 0 ]
then
if [ $# -lt 1 ]
then
usage
fi
OUTPUT="/tmp/Qt"
else
if [ $# -lt 2 ]
then
usage
fi
if [[ ! "${OUTPUT:0:1}" = "/" ]]
then
echo output path must be an absolute path
exit -1
fi
fi
cat <<EOF > $SCRIPT
function abortInstaller()
{
installer.setDefaultPageVisible(QInstaller.Introduction, false);
installer.setDefaultPageVisible(QInstaller.TargetDirectory, false);
installer.setDefaultPageVisible(QInstaller.ComponentSelection, false);
installer.setDefaultPageVisible(QInstaller.ReadyForInstallation, false);
installer.setDefaultPageVisible(QInstaller.StartMenuSelection, false);
installer.setDefaultPageVisible(QInstaller.PerformInstallation, false);
installer.setDefaultPageVisible(QInstaller.LicenseCheck, false);
var abortText = "<font color='red' size=3>" + qsTr("Installation failed:") + "</font>";
var error_list = installer.value("component_errors").split(";;;");
abortText += "<ul>";
// ignore the first empty one
for (var i = 0; i < error_list.length; ++i) {
if (error_list[i] !== "") {
log(error_list[i]);
abortText += "<li>" + error_list[i] + "</li>"
}
}
abortText += "</ul>";
installer.setValue("FinishedText", abortText);
}
function log() {
var msg = ["QTCI: "].concat([].slice.call(arguments));
console.log(msg.join(" "));
}
function printObject(object) {
var lines = [];
for (var i in object) {
lines.push([i, object[i]].join(" "));
}
log(lines.join(","));
}
var status = {
widget: null,
finishedPageVisible: false,
installationFinished: false
}
function tryFinish() {
if (status.finishedPageVisible && status.installationFinished) {
if (status.widget.LaunchQtCreatorCheckBoxForm) {
// Disable this checkbox for minimal platform
status.widget.LaunchQtCreatorCheckBoxForm.launchQtCreatorCheckBox.setChecked(false);
}
if (status.widget.RunItCheckBox) {
// LaunchQtCreatorCheckBoxForm may not work for newer versions.
status.widget.RunItCheckBox.setChecked(false);
}
log("Press Finish Button");
gui.clickButton(buttons.FinishButton);
}
}
function Controller() {
installer.installationFinished.connect(function() {
status.installationFinished = true;
gui.clickButton(buttons.NextButton);
tryFinish();
});
installer.setMessageBoxAutomaticAnswer("OverwriteTargetDirectory", QMessageBox.Yes);
installer.setMessageBoxAutomaticAnswer("installationErrorWithRetry", QMessageBox.Ignore);
installer.setMessageBoxAutomaticAnswer("XcodeError", QMessageBox.Ok);
// Allow to cancel installation for arguments --list-packages
installer.setMessageBoxAutomaticAnswer("cancelInstallation", QMessageBox.Yes);
}
Controller.prototype.WelcomePageCallback = function() {
log("Welcome Page");
gui.clickButton(buttons.NextButton);
var widget = gui.currentPageWidget();
/*
Online installer 3.0.6
- It must disconnect the completeChanged callback after used, otherwise it will click the 'next' button on another pages
*/
var callback = function() {
gui.clickButton(buttons.NextButton);
widget.completeChanged.disconnect(callback);
}
widget.completeChanged.connect(callback);
}
Controller.prototype.CredentialsPageCallback = function() {
var login = installer.environmentVariable("QT_CI_LOGIN");
var password = installer.environmentVariable("QT_CI_PASSWORD");
if (login === "" || password === "") {
gui.clickButton(buttons.CommitButton);
}
var widget = gui.currentPageWidget();
widget.loginWidget.EmailLineEdit.setText(login);
widget.loginWidget.PasswordLineEdit.setText(password);
gui.clickButton(buttons.CommitButton);
}
Controller.prototype.ComponentSelectionPageCallback = function() {
log("ComponentSelectionPageCallback");
function list_packages() {
var components = installer.components();
log("Available components: " + components.length);
var packages = ["Packages: "];
for (var i = 0 ; i < components.length ;i++) {
packages.push(components[i].name);
}
log(packages.join(" "));
}
if ($LIST_PACKAGES) {
list_packages();
gui.clickButton(buttons.CancelButton);
return;
}
log("Select components");
function trim(str) {
return str.replace(/^ +/,"").replace(/ *$/,"");
}
var widget = gui.currentPageWidget();
var packages = trim("$PACKAGES").split(",");
if (packages.length > 0 && packages[0] !== "") {
widget.deselectAll();
var components = installer.components();
var allfound = true;
for (var i in packages) {
var pkg = trim(packages[i]);
var found = false;
for (var j in components) {
if (components[j].name === pkg) {
found = true;
break;
}
}
if (!found) {
allfound = false;
log("ERROR: Package " + pkg + " not found.");
} else {
log("Select " + pkg);
widget.selectComponent(pkg);
}
}
if (!allfound) {
list_packages();
// TODO: figure out how to set non-zero exit status.
gui.clickButton(buttons.CancelButton);
return;
}
} else {
log("Use default component list");
}
gui.clickButton(buttons.NextButton);
}
Controller.prototype.IntroductionPageCallback = function() {
log("Introduction Page");
log("Retrieving meta information from remote repository");
/*
Online installer 3.0.6
- Don't click buttons.NextButton directly. It will skip the componenet selection.
*/
if (installer.isOfflineOnly()) {
gui.clickButton(buttons.NextButton);
}
}
Controller.prototype.TargetDirectoryPageCallback = function() {
log("Set target installation page: $OUTPUT");
var widget = gui.currentPageWidget();
if (widget != null) {
widget.TargetDirectoryLineEdit.setText("$OUTPUT");
}
gui.clickButton(buttons.NextButton);
}
Controller.prototype.LicenseAgreementPageCallback = function() {
log("Accept license agreement");
var widget = gui.currentPageWidget();
if (widget != null) {
widget.AcceptLicenseRadioButton.setChecked(true);
}
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ReadyForInstallationPageCallback = function() {
log("Ready to install");
// Bug? If commit button pressed too quickly finished callback might not show the checkbox to disable running qt creator
// Behaviour started around 5.10. You don't actually have to press this button at all with those versions, even though gui.isButtonEnabled() returns true.
gui.clickButton(buttons.CommitButton, 200);
}
Controller.prototype.PerformInstallationPageCallback = function() {
log("PerformInstallationPageCallback");
gui.clickButton(buttons.CommitButton);
}
Controller.prototype.FinishedPageCallback = function() {
log("FinishedPageCallback");
var widget = gui.currentPageWidget();
// Bug? Qt 5.9.5 and Qt 5.9.6 installer show finished page before the installation completed
// Don't press "finishButton" immediately
status.finishedPageVisible = true;
status.widget = widget;
tryFinish();
}
EOF
chmod u+x $1
if [ -n "$QT_CI_DEBUG" ]
then
$INSTALLER -v --script $SCRIPT | grep "\(QTCI\|operation\)"
exit 0
fi
unset DISPLAY
if [ -n "$DISABLE_PROGRESS_REPORT" ]
then
QT_QPA_PLATFORM=minimal $INSTALLER --script $SCRIPT
else
ARGS="-v"
if [ -n "$VERBOSE" ]
then
QT_QPA_PLATFORM=minimal $INSTALLER $ARGS --script $SCRIPT
else
QT_QPA_PLATFORM=minimal $INSTALLER $ARGS --script $SCRIPT | grep "\(QTCI\|operation\)"
fi
fi

View File

@ -0,0 +1,66 @@
// installer script for the Qt installer. Launch with (-platform is for headless)
// ./installer -platform minimal --script path/to/qt-installer.qs
function Controller() {
installer.autoRejectMessageBoxes();
installer.installationFinished.connect(function() {
gui.clickButton(buttons.NextButton);
})
}
Controller.prototype.WelcomePageCallback = function() {
// click delay here because the next button is initially disabled for ~1 second
gui.clickButton(buttons.NextButton, 3000);
}
Controller.prototype.CredentialsPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.IntroductionPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.TargetDirectoryPageCallback = function() {
gui.currentPageWidget().TargetDirectoryLineEdit.setText("/opt/Qt5.12.4");
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ComponentSelectionPageCallback = function() {
var widget = gui.currentPageWidget();
widget.deselectAll();
// Package names are a mystery but can be extracted using the following script with a --list-packages flag:
// https://raw.githubusercontent.com/benlau/qtci/master/bin/extract-qt-installer
// Here is the full list for 5.12:
// qt qt.qt5.5124 qt.tools qt.installer.changelog qt.license.gplv3except qt.license.python qt.license.thirdparty qt.license.lgpl qt.qt5.5124.gcc_64 qt.qt5.5124.android_x86 qt.qt5.5124.android_arm64_v8a qt.qt5.5124.android_armv7 qt.qt5.5124.src qt.qt5.5124.qtcharts qt.qt5.5124.qtdatavis3d qt.qt5.5124.qtpurchasing qt.qt5.5124.qtvirtualkeyboard qt.qt5.5124.qtwebengine qt.qt5.5124.qtnetworkauth qt.qt5.5124.qtwebglplugin qt.qt5.5124.qtscript qt.qt5.5124.examples qt.qt5.5124.doc qt.qt5.5124.qtcharts.android_x86 qt.qt5.5124.qtcharts.android_arm64_v8a qt.qt5.5124.qtcharts.android_armv7 qt.qt5.5124.qtcharts.gcc_64 qt.qt5.5124.qtdatavis3d.android_x86 qt.qt5.5124.qtdatavis3d.android_arm64_v8a qt.qt5.5124.qtdatavis3d.android_armv7 qt.qt5.5124.qtdatavis3d.gcc_64 qt.qt5.5124.qtpurchasing.android_arm64_v8a qt.qt5.5124.qtpurchasing.android_x86 qt.qt5.5124.qtpurchasing.gcc_64 qt.qt5.5124.qtpurchasing.android_armv7 qt.qt5.5124.qtvirtualkeyboard.gcc_64 qt.qt5.5124.qtwebengine.gcc_64 qt.qt5.5124.qtnetworkauth.android_x86 qt.qt5.5124.qtnetworkauth.gcc_64 qt.qt5.5124.qtnetworkauth.android_armv7 qt.qt5.5124.qtnetworkauth.android_arm64_v8a qt.qt5.5124.qtwebglplugin.gcc_64 qt.qt5.5124.qtscript.android_armv7 qt.qt5.5124.qtscript.android_arm64_v8a qt.qt5.5124.qtscript.android_x86 qt.qt5.5124.qtscript.gcc_64 qt.qt5.5124.examples.qtdatavis3d qt.qt5.5124.examples.qtpurchasing qt.qt5.5124.examples.qtcharts qt.qt5.5124.examples.qtwebengine qt.qt5.5124.examples.qtscript qt.qt5.5124.examples.qtnetworkauth qt.qt5.5124.examples.qtvirtualkeyboard qt.qt5.5124.doc.qtwebengine qt.qt5.5124.doc.qtpurchasing qt.qt5.5124.doc.qtdatavis3d qt.qt5.5124.doc.qtcharts qt.qt5.5124.doc.qtvirtualkeyboard qt.qt5.5124.doc.qtnetworkauth qt.qt5.5124.doc.qtscript qt.tools.qtcreator
// qt qt.qt5.5124 qt.tools qt.installer.changelog qt.license.gplv3except qt.license.python qt.license.thirdparty qt.license.lgpl qt.qt5.5124.gcc_64 qt.qt5.5124.android_x86 qt.qt5.5124.android_arm64_v8a qt.qt5.5124.android_armv7 qt.qt5.5124.src qt.qt5.5124.qtcharts qt.qt5.5124.qtdatavis3d qt.qt5.5124.qtpurchasing qt.qt5.5124.qtvirtualkeyboard qt.qt5.5124.qtwebengine qt.qt5.5124.qtnetworkauth qt.qt5.5124.qtwebglplugin qt.qt5.5124.qtscript ...
widget.selectComponent("qt.qt5.5124.gcc_64");
//widget.selectComponent("qt.qt5.5124.qtcharts");
//widget.selectComponent("qt.qt5.5124.qtdatavis3d");
//widget.selectComponent("qt.qt5.5124.qtvirtualkeyboard");
//widget.selectComponent("qt.qt5.5124.qtwebengine");
//widget.selectComponent("qt.qt5.5124.qtnetworkauth");
//widget.selectComponent("qt.qt5.5124.qtwebglplugin");
gui.clickButton(buttons.NextButton);
}
Controller.prototype.LicenseAgreementPageCallback = function() {
gui.currentPageWidget().AcceptLicenseRadioButton.setChecked(true);
gui.clickButton(buttons.NextButton);
}
Controller.prototype.StartMenuDirectoryPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.ReadyForInstallationPageCallback = function() {
gui.clickButton(buttons.NextButton);
}
Controller.prototype.FinishedPageCallback = function() {
var checkBoxForm = gui.currentPageWidget().LaunchQtCreatorCheckBoxForm;
if (checkBoxForm && checkBoxForm.launchQtCreatorCheckBox) {
checkBoxForm.launchQtCreatorCheckBox.checked = false;
}
gui.clickButton(buttons.FinishButton);
}