├── .gitattributes ├── .gitignore ├── CHANGELOG.md ├── LICENSE ├── README.md ├── builder.sh ├── ci-builder.sh ├── docker ├── .dockerignore ├── Dockerfile ├── Dockerfile.xfce.20-04 ├── Dockerfile.xfce.22-04 ├── Dockerfile.xfce.24-04 ├── README.md ├── doc │ └── images │ │ ├── Dockerfile.xfce.png │ │ ├── animation-ubuntu-vnc-xfce-chromium-g3.gif │ │ ├── animation-ubuntu-vnc-xfce-firefox-g3.gif │ │ └── animation-ubuntu-vnc-xfce-g3.gif ├── hooks │ ├── build │ ├── cache │ ├── env.rc │ ├── helper │ ├── post_push │ ├── pre_build │ ├── push │ ├── release_of │ └── util.rc ├── src │ ├── home │ │ └── .bashrc │ ├── tests │ │ └── test-01.sh │ └── xfce-startup │ │ ├── help.rc │ │ ├── parser.rc │ │ ├── set_user_permissions.sh │ │ ├── startup.sh │ │ ├── user_generator.rc │ │ ├── version_of.sh │ │ ├── version_sticker.sh │ │ └── vnc_startup.rc ├── xfce-chromium │ ├── README-dockerhub.md │ ├── README.md │ ├── readme-append.template │ └── src │ │ └── home │ │ ├── Desktop │ │ └── chromium-browser.desktop │ │ └── readme-chromium.md ├── xfce-firefox │ ├── README-dockerhub.md │ ├── README.md │ ├── readme-append.template │ └── src │ │ ├── firefox.plus │ │ ├── home │ │ │ ├── Desktop │ │ │ │ ├── Copy FF Preferences.desktop │ │ │ │ └── FF Profile Manager.desktop │ │ │ └── readme-firefox-plus.md │ │ └── resources │ │ │ ├── accetto.svg │ │ │ ├── copy_firefox_user_preferences.sh │ │ │ └── user.js │ │ └── home │ │ └── Desktop │ │ └── firefox.desktop └── xfce │ ├── README-dockerhub.md │ ├── README.md │ ├── readme-append.template │ └── src │ └── home │ ├── Desktop │ └── versionsticker.desktop │ ├── config │ └── xfce4 │ │ ├── terminal │ │ └── terminalrc │ │ └── xfconf │ │ └── xfce-perchannel-xml │ │ ├── keyboard-layout.xml │ │ ├── thunar.xml │ │ └── xfwm4.xml │ └── readme.md ├── examples ├── Dockerfile.extend ├── example-override-envv.rc ├── example-secrets.rc └── example.yml ├── readme-builder.md ├── readme-ci-builder.md ├── readme-g3-cache.md ├── readme-local-building-example.md └── utils ├── readme-util-readme-examples.md └── util-readme.sh /.gitattributes: -------------------------------------------------------------------------------- 1 | # GitHub language detection 2 | # linguist-language, linguist-vendored, linguist-documentation, linguist-generated, linguist-detectable 3 | * linguist-documentation=true 4 | Dockerfile linguist-documentation=false 5 | Dockerfile linguist-language=Dockerfile 6 | Dockerfile linguist-detectable=true 7 | 8 | # Set default behaviour, in case users don't have core.autocrlf set. 9 | * text=auto 10 | 11 | # Explicitly declare text files we want to always be normalized and converted 12 | # to native line endings on checkout. 13 | *.c text 14 | *.h text 15 | *.sah text 16 | *.suite text 17 | *.inc text 18 | *.js text 19 | *.json text 20 | 21 | # Declare files that will always have CRLF line endings on checkout. 22 | *.sln text eol=crlf 23 | 24 | # Denote all files that are truly binary and should not be modified. 25 | *.png binary 26 | *.jpg binary 27 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # blank lines are ignored 2 | # lines starting with '#' are ignored 3 | # starting patterns with '/' disables recursivity 4 | # ending patterns with '/' specifies directories 5 | # starting patterns with '!' negates them 6 | # standard glob patterns (shell patterns) work: 7 | # '*' matches zero oro more characters 8 | # '?' matches a single characters 9 | # '[abc]' matches the characters inside the brackets 10 | # '[0-9]' matches the characters inside the brackets 11 | # '**' matches nested directories (e.g. 'a/**/z') 12 | # recommended files on 'https://github.com/github/gitignore' 13 | 14 | .vscode 15 | .cache* 16 | .g3-cache* 17 | .secret* 18 | .util* 19 | .vscode 20 | scrap* 21 | secret* 22 | TODO* 23 | *.log 24 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 accetto 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /builder.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | ### depends on the hook scripts 4 | ### set the environment variables first, e.g. 'source .secrets' 5 | 6 | ### usage: './ [build-options]' 7 | 8 | die() { 9 | local message="${1:-(unknown)}" 10 | local -i code=${2:-1} 11 | local place="${3:-$0}" 12 | 13 | echo -e "EXITING at line "${BASH_LINENO[0]}" in '${place}' with code ${code}: ${message}" >&2 14 | exit ${code} 15 | } 16 | 17 | clear_log() { 18 | 19 | ### just for debugging 20 | # cp -f "${_ci_builder_log}" "${_ci_builder_log}_copy" 21 | 22 | >"${_builder_log}" 23 | echo -e "\n==> EXECUTING @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 24 | } 25 | 26 | show_error() { 27 | 28 | echo -e "\nERROR in ${0}: ${@:-(unknown)}\n" >&2 29 | } 30 | 31 | show_unlogged_help() { 32 | 33 | # help is never logged 34 | exec 1>&- 35 | { 36 | cat < [] 44 | 45 | blend := (latest|noble|24.04|jammy|22.04|focal|20.04)[-chromium|-firefox] 46 | command := (all|all-no-push)|(pre_build|build|push|post_push|cache) 47 | 48 | The (e.g. '--no-cache') are passed to the Docker CLI commands used internally. 49 | 50 | The script creates a complete execution log. 51 | EOT 52 | } >&3 53 | } 54 | 55 | main() { 56 | 57 | if [[ $# -eq 0 ]]; then 58 | 59 | show_unlogged_help 60 | return 0 61 | fi 62 | 63 | if [[ "${1}" == "-h" || "${1}" =~ help ]]; then 64 | 65 | show_unlogged_help 66 | return 0 67 | fi 68 | 69 | local blend=${1} 70 | local cmd=${2} 71 | 72 | if [[ $# -ge 2 ]]; then shift 2; fi 73 | 74 | local -a all_pipeline 75 | local -i exit_code=0 76 | 77 | case "${cmd}" in 78 | 79 | pre_build | build | push | post_push | cache) 80 | 81 | clear_log 82 | "${_build_context}"/hooks/"${cmd}" dev "${blend}" $@ 83 | exit_code=$? 84 | if [[ ${exit_code} -ne 0 ]]; then 85 | die "Hook script '${cmd}' failed with code ${exit_code}." ${exit_code} 86 | fi 87 | ;; 88 | 89 | all | all-no-push) 90 | 91 | clear_log 92 | "${_build_context}"/hooks/pre_build dev "${blend}" $@ 93 | exit_code=$? 94 | if [[ ${exit_code} -ne 0 ]]; then 95 | die "Hook script 'pre_build' failed with code ${exit_code}." ${exit_code} 96 | fi 97 | 98 | if [[ ! -f "${_build_context}"/scrap-demand-stop-building ]]; then 99 | 100 | case "${cmd}" in 101 | all-no-push) all_pipeline=("build") ;; 102 | all) all_pipeline=("build" "push" "post_push") ;; 103 | 104 | *) 105 | show_error "Unknown command: '${cmd}'" 106 | ;; 107 | esac 108 | 109 | for c in ${all_pipeline[@]}; do 110 | 111 | echo 112 | echo "==> ${c} '${blend}'" 113 | echo 114 | 115 | "${_build_context}"/hooks/"${c}" dev "${blend}" $@ 116 | exit_code=$? 117 | if [[ ${exit_code} -ne 0 ]]; then 118 | die "Hook script '${c}' failed with code ${exit_code}." ${exit_code} 119 | fi 120 | done 121 | 122 | echo 123 | case "${cmd}" in 124 | 125 | all-no-push) 126 | echo "==> Built '${blend}'" 127 | ;; 128 | all) 129 | echo "==> Published '${blend}'" 130 | ;; 131 | *) 132 | show_error "Unknown command: '${cmd}'" 133 | ;; 134 | esac 135 | echo 136 | 137 | else 138 | echo 139 | echo "==> No build needed for '${blend}'" 140 | echo 141 | fi 142 | ;; 143 | 144 | *) 145 | show_error "Invalid arguments '${blend}' '${cmd}'" 146 | ;; 147 | esac 148 | 149 | echo -e "\n==> FINISHED @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 150 | } 151 | 152 | declare _build_context="./docker" 153 | 154 | declare _builder_log="scrap_builder.log" 155 | 156 | ### duplicate 'stdout' so we can close it when displaying help 157 | exec 3>&1 158 | 159 | ### main entry point 160 | declare -i __exit_code=0 161 | main $@ 2>&1 | tee -a "${_builder_log}" 162 | __exit_code=${PIPESTATUS[0]} 163 | 164 | exit ${__exit_code} 165 | -------------------------------------------------------------------------------- /docker/.dockerignore: -------------------------------------------------------------------------------- 1 | * 2 | !src 3 | !xfce* 4 | !.g3-cache 5 | -------------------------------------------------------------------------------- /docker/Dockerfile: -------------------------------------------------------------------------------- 1 | # This is just a placeholder. The actual Dockerfile will be set by the hook scripts. 2 | # Having this file allows to keep the default 'Dockerfile' value in the build rules on Docker Hub. 3 | 4 | FROM scratch 5 | -------------------------------------------------------------------------------- /docker/README.md: -------------------------------------------------------------------------------- 1 | # README placeholder 2 | 3 | This is only a README placeholder, which will be replaced by the image deployment workflow. 4 | 5 | Useful links from **this project's** GitHub repository [accetto/ubuntu-vnc-xfce-g3][this-home]: 6 | 7 | - project [Readme][this-readme], [Changelog][this-changelog], [Issues][this-issues], [Wiki][this-wiki] and [Discussions][this-discussions] 8 | - base images **Ubuntu/Xfce/VNC/noVNC** 9 | - [full Readme][this-readme-image-base] file on GitHub 10 | - [image repository][this-dockerhub-image-base] on Docker Hub 11 | - Dockerfiles [22.04][this-dockerfile-22-04] and [20.04][this-dockerfile-20-04] (common for all images) on GitHub 12 | - [Dockerfile stages diagram][this-diagram-dockerfile-stages] on GitHub (common for all images) 13 | - images with **Chromium** 14 | - [full Readme][this-readme-image-chromium] file on GitHub 15 | - [image repository][this-dockerhub-image-chromium] on Docker Hub 16 | - images with **Firefox** 17 | - [full Readme][this-readme-image-firefox] file on GitHub 18 | - [image repository][this-dockerhub-image-firefox] on Docker Hub 19 | 20 | *** 21 | 22 | [this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/CHANGELOG.md 23 | [this-discussions]: https://github.com/accetto/ubuntu-vnc-xfce-g3/discussions 24 | [this-dockerfile-22-04]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/Dockerfile.xfce.22-04 25 | [this-dockerfile-20-04]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/Dockerfile.xfce.20-04 26 | 27 | [this-home]: https://github.com/accetto/ubuntu-vnc-xfce-g3 28 | [this-issues]: https://github.com/accetto/ubuntu-vnc-xfce-g3/issues 29 | [this-readme]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/README.md 30 | [this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki 31 | 32 | [this-diagram-dockerfile-stages]: https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/master/docker/doc/images/Dockerfile.xfce.png 33 | 34 | [this-dockerhub-image-base]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-g3 35 | [this-readme-image-base]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/xfce/README.md 36 | 37 | [this-dockerhub-image-chromium]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-chromium-g3 38 | [this-readme-image-chromium]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/xfce-chromium/README.md 39 | 40 | [this-dockerhub-image-firefox]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-firefox-g3 41 | [this-readme-image-firefox]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/xfce-firefox/README.md 42 | -------------------------------------------------------------------------------- /docker/doc/images/Dockerfile.xfce.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/7940ff8338f2e6de1a99466731ec91bcbc2d3940/docker/doc/images/Dockerfile.xfce.png -------------------------------------------------------------------------------- /docker/doc/images/animation-ubuntu-vnc-xfce-chromium-g3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/7940ff8338f2e6de1a99466731ec91bcbc2d3940/docker/doc/images/animation-ubuntu-vnc-xfce-chromium-g3.gif -------------------------------------------------------------------------------- /docker/doc/images/animation-ubuntu-vnc-xfce-firefox-g3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/7940ff8338f2e6de1a99466731ec91bcbc2d3940/docker/doc/images/animation-ubuntu-vnc-xfce-firefox-g3.gif -------------------------------------------------------------------------------- /docker/doc/images/animation-ubuntu-vnc-xfce-g3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/7940ff8338f2e6de1a99466731ec91bcbc2d3940/docker/doc/images/animation-ubuntu-vnc-xfce-g3.gif -------------------------------------------------------------------------------- /docker/hooks/build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo -e "\n==> EXECUTING @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 4 | 5 | declare _mydir=$(dirname $0) 6 | source "${_mydir}"/env.rc 7 | source "${_mydir}"/util.rc 8 | 9 | main() { 10 | local params=$@ 11 | local now 12 | local version_sticker 13 | local cache_script="cache" 14 | local -i exit_code=0 15 | local target_stage 16 | 17 | ### helper image is also used as a cache and therefore it must not use a tag 18 | local helper_image="${DOCKER_REPO}"_"${DOCKER_TAG}${helper_suffix}" 19 | 20 | if [[ -f "${_build_context}/${_scrap_demand_stop_building}" ]]; then 21 | 22 | echo "Skipping build on demand." 23 | else 24 | 25 | ### refresh local cache for the case the 'pre_build' was not run 26 | "${_mydir}/${cache_script}" "${_branch}" "${_blend}" 27 | exit_code=$? 28 | if [[ ${exit_code} -ne 0 ]]; then 29 | die "Script '${cache_script}' failed with code ${exit_code}." ${exit_code} 30 | fi 31 | 32 | ### get current version sticker 33 | if [[ -f "${_build_context}/${_scrap_version_sticker_current}" ]]; then 34 | 35 | version_sticker="$(cat ${_build_context}/${_scrap_version_sticker_current})" 36 | else 37 | version_sticker="null" 38 | fi 39 | 40 | ### check for the '--target' parameter 41 | if [[ $# -gt 0 ]]; then 42 | 43 | ### no quotes around 'params' 44 | for i in ${params}; do 45 | if [[ "${i}" == "--target" ]]; then 46 | 47 | target_stage="${i}" 48 | 49 | elif [[ -n "${target_stage}" ]]; then 50 | 51 | ### only if '--target' is followed by a value 52 | if [[ ! "${i}" =~ ^- ]]; then 53 | target_stage="${i}" 54 | fi 55 | break 56 | fi 57 | done 58 | 59 | ### remove the orphaned '--target' (missing value) 60 | if [[ "${target_stage}" == "--target" ]]; then 61 | params="${params/--target/}" 62 | target_stage="" 63 | fi 64 | fi 65 | 66 | now="$(date --utc +%FT%TZ)" 67 | echo "Current timestamp: ${now}" 68 | echo 69 | 70 | ### no quotes around ${params}! 71 | set -x 72 | docker build ${params} \ 73 | --cache-from=${helper_image} \ 74 | -f "${DOCKERFILE_PATH}" \ 75 | --build-arg BASEIMAGE="${BASEIMAGE}" \ 76 | --build-arg BASETAG="${BASETAG}" \ 77 | --build-arg ARG_CREATED="${now}" \ 78 | --build-arg ARG_DOCKER_TAG=${DOCKER_TAG} \ 79 | --build-arg ARG_VERSION_STICKER="${version_sticker}" \ 80 | --build-arg ARG_VCS_REF="$(git rev-parse --short HEAD)" \ 81 | \ 82 | ${FEATURES_BUILD_SLIM:+--build-arg ARG_APT_NO_RECOMMENDS=1} \ 83 | ${FEATURES_OVERRIDING_ENVV:+--build-arg ARG_FEATURES_OVERRIDING_ENVV=1} \ 84 | ${FEATURES_SCREENSHOOTING:+--build-arg ARG_FEATURES_SCREENSHOOTING=1} \ 85 | ${FEATURES_THUMBNAILING:+--build-arg ARG_FEATURES_THUMBNAILING=1} \ 86 | \ 87 | ${FEATURES_VNC:+--build-arg ARG_TIGERVNC_DISTRO=${TIGERVNC_DISTRO}} \ 88 | ${FEATURES_VNC:+--build-arg ARG_TIGERVNC_VERSION=${TIGERVNC_VERSION}} \ 89 | \ 90 | ${FEATURES_NOVNC:+--build-arg ARG_NOVNC_VERSION=${NOVNC_VERSION}} \ 91 | ${FEATURES_NOVNC:+--build-arg ARG_WEBSOCKIFY_VERSION=${WEBSOCKIFY_VERSION}} \ 92 | ${FEATURES_NOVNC:+--build-arg ARG_MERGE_STAGE_VNC_BASE="stage_novnc"} \ 93 | \ 94 | ${FEATURES_CHROMIUM:+--build-arg ARG_CHROMIUM_DISTRO=${CHROMIUM_DISTRO}} \ 95 | ${FEATURES_CHROMIUM:+--build-arg ARG_CHROMIUM_VERSION=${CHROMIUM_VERSION}} \ 96 | ${FEATURES_CHROMIUM:+--build-arg ARG_MERGE_STAGE_BROWSER_BASE="stage_chromium"} \ 97 | \ 98 | ${FEATURES_FIREFOX:+--build-arg ARG_MERGE_STAGE_BROWSER_BASE="stage_firefox"} \ 99 | ${FEATURES_FIREFOX_PLUS:+--build-arg ARG_MERGE_STAGE_BROWSER_BASE="stage_firefox_plus"} \ 100 | \ 101 | -t "${DOCKER_REPO}:${DOCKER_TAG}${target_stage:+_${target_stage}}" "${_build_context}" 102 | 103 | exit_code=$? 104 | set +x 105 | fi 106 | 107 | ### delete the helper image in any case 108 | ensure_image "${helper_image}" 109 | if [[ $? -eq 0 ]]; then 110 | echo 111 | echo "Removing helper image" 112 | docker rmi "${helper_image}" 113 | fi 114 | 115 | if [[ ${exit_code} -ne 0 ]]; then 116 | die "Failed to build image '${DOCKER_REPO}:${DOCKER_TAG}'" ${exit_code} 117 | fi 118 | } 119 | 120 | main $@ 121 | 122 | echo -e "\n==> FINISHED @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 123 | -------------------------------------------------------------------------------- /docker/hooks/cache: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo -e "\n==> EXECUTING @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 4 | 5 | declare _mydir=$(dirname $0) 6 | 7 | source "${_mydir}"/env.rc 8 | source "${_mydir}"/util.rc 9 | 10 | ensure_wget() { 11 | local -i error_code=0 12 | local -i enforced_error_code=1 13 | 14 | ### checking can be disabled by passing 'enforced_error_code=0' 15 | if [[ "${IGNORE_MISSING_WGET:-0}" == "0" ]] ; then 16 | enforced_error_code=1 17 | else 18 | enforced_error_code=0 19 | fi 20 | ensure_utility wget ${enforced_error_code} 21 | 22 | error_code=$? 23 | if [[ ${error_code} -ne 0 ]] ; then 24 | echo 25 | echo "WARNING! Utility 'wget' not found." 26 | echo "It's recommended to install the utility or to switch to an environment where it's available (e.g. WSL)." 27 | echo "Otherwise set the environment variable IGNORE_MISSING_WGET=1 to ignore this checking." 28 | echo "The selected packages still will be downloaded into a temporary image layer, but not into the project's" 29 | echo "'.g3-cache' folder nor the shared one, defined by the variable SHARED_G3_CACHE_PATH." 30 | echo 31 | 32 | die "Utility 'wget' not found." ${error_code} 33 | fi 34 | } 35 | 36 | use_wget() { 37 | local section="${1?Expected section name}" 38 | local file=${2?Expected file name} 39 | local source=${3?Expected source path} 40 | local target=${4?Expected target path} 41 | local -i error_code=0 42 | 43 | ### try-catch 44 | ( 45 | ### this is a subshell block, so no changes to outside variables will persist 46 | set -o pipefail 47 | set -ex 48 | 49 | ### Warning, do not enclose '${_quiet:+-q}' into quotes, otherwise it'll cause the message 50 | ### 'http://: Invalid host name.' and the error code '1'. 51 | ### However, the download would proceed. 52 | wget --show-progress --progress=bar:force:noscroll ${_quiet:+-q} -O "${target}" "${source}" 53 | 54 | ) ; { 55 | 56 | ### catch - this block is entered only by errors in the try-block 57 | error_code=$? 58 | 59 | if [[ ${error_code} -ne 0 ]] ; then 60 | 61 | echo -e "${_mark} error '${error_code}' by downloading file '${file}' in section '${section}'" >&2 62 | 63 | echo -e "${_mark} renaming file '${file}' to '${file}_failed' in section '${section}'" >&2 64 | 65 | mv -f "${target}" "${target}_failed" 66 | fi 67 | } 68 | 69 | ### This procedure reports the 'wget' errors, but it does not fail on them. 70 | ### However, the created target file will be renamed with the suffix '_failed'. 71 | return 0 72 | } 73 | 74 | refresh_file() { 75 | local section="${1?Expected section name}" 76 | local file=${2?Expected file name} 77 | local source_url=${3?Expected source URL} 78 | local target=${4?Expected target path} 79 | 80 | local source="${_shared_cache_path}/${section}/${file}" 81 | 82 | if [[ ! -s "${target}" ]] ; then 83 | 84 | ### first try to copy the file from the shared cache 85 | if [[ -s "${source}" ]] ; then 86 | 87 | echo -e "${_mark} refreshing section '${section}' by copying shared file '${file}'\n" 88 | cp "${source}" "${target}" 89 | 90 | else 91 | ### otherwise download the file from the Internet 92 | 93 | echo -e "${_mark} refreshing section '${section}' by downloading file '${file}'\n" 94 | use_wget "${section}" "${file}" "${source_url}" "${target}" 95 | 96 | ### ensure the shared G3-CACHE directory 97 | if [[ -z "${SHARED_G3_CACHE_PATH}" ]]; then 98 | 99 | echo "WARNING! Environment variable 'SHARED_G3_CACHE_PATH' is not set." 100 | 101 | elif [[ ! -d "${_shared_cache_path}" ]]; then 102 | 103 | echo "WARNING! Shared G3-CACHE directory not found: ${_shared_cache_path}" 104 | 105 | elif [[ ! -w "${_shared_cache_path}" ]]; then 106 | 107 | echo "WARNING! Shared G3-CACHE directory is not writable: ${_shared_cache_path}" 108 | 109 | elif [[ ! -s "${target}" ]]; then 110 | 111 | echo "WARNING! Downloaded file in local G3-CACHE intended for the shared G3-CACHE is empty: ${target}" 112 | 113 | else 114 | ### copy the downloaded file to the shared cache 115 | echo -e "${_mark} refreshing shared section '${section}' by copying downloaded file '${file}'\n" 116 | 117 | mkdir -p "${_shared_cache_path}/${section}" 118 | 119 | cp "${target}" "${source}" 120 | fi 121 | fi 122 | else 123 | echo -e "${_mark} hit file '${file}' in section '${section}'" 124 | fi 125 | } 126 | 127 | cache_tigervnc() { 128 | local section="tigervnc" 129 | local source_base_url="https://sourceforge.net/projects/tigervnc/files/stable" 130 | local target_path="${_cache}/${section}" 131 | local target="" 132 | local file="" 133 | 134 | mkdir -p "${target_path}" 135 | 136 | file="tigervnc-${TIGERVNC_VERSION}.${TIGERVNC_DISTRO}.tar.gz" 137 | source_url="${source_base_url}/${TIGERVNC_VERSION}/${file}" 138 | target="${target_path}/${file}" 139 | 140 | refresh_file "${section}" "${file}" "${source_url}" "${target}" 141 | } 142 | 143 | cache_novnc() { 144 | local section="novnc" 145 | local source_base_url="https://github.com/novnc/noVNC/archive/" 146 | local target_path="${_cache}/${section}" 147 | local target="" 148 | local file="" 149 | 150 | mkdir -p "${target_path}" 151 | 152 | file="v${NOVNC_VERSION}.tar.gz" 153 | source_url="${source_base_url}/${file}" 154 | target="${target_path}/${file}" 155 | 156 | refresh_file "${section}" "${file}" "${source_url}" "${target}" 157 | } 158 | 159 | cache_websockify() { 160 | local section="websockify" 161 | local source_base_url="https://github.com/novnc/websockify/archive" 162 | local target_path="${_cache}/${section}" 163 | local target="" 164 | local file="" 165 | 166 | mkdir -p "${target_path}" 167 | 168 | file="v${WEBSOCKIFY_VERSION}.tar.gz" 169 | source_url="${source_base_url}/${file}" 170 | target="${target_path}/${file}" 171 | 172 | refresh_file "${section}" "${file}" "${source_url}" "${target}" 173 | } 174 | 175 | cache_chromium() { 176 | local section="chromium" 177 | local source_base_url="http://archive.ubuntu.com/ubuntu/pool/universe/c/chromium-browser" 178 | local target_path="${_cache}/${section}" 179 | local file="" 180 | local target="" 181 | 182 | mkdir -p "${target_path}" 183 | 184 | file="chromium-browser_${CHROMIUM_VERSION}_${CHROMIUM_DISTRO}.deb" 185 | source_url="${source_base_url}/${file}" 186 | target="${target_path}/${file}" 187 | 188 | refresh_file "${section}" "${file}" "${source_url}" "${target}" 189 | 190 | file="chromium-codecs-ffmpeg_${CHROMIUM_VERSION}_${CHROMIUM_DISTRO}.deb" 191 | source_url="${source_base_url}/${file}" 192 | target="${target_path}/${file}" 193 | 194 | refresh_file "${section}" "${file}" "${source_url}" "${target}" 195 | 196 | file="chromium-browser-l10n_${CHROMIUM_VERSION}_all.deb" 197 | source_url="${source_base_url}/${file}" 198 | target="${target_path}/${file}" 199 | 200 | refresh_file "${section}" "${file}" "${source_url}" "${target}" 201 | } 202 | 203 | ### ========== 204 | ### cache_main 205 | ### ========== 206 | 207 | ### usage: 208 | ### PWD= 209 | ### ./docker/hooks/cache [-q|--quiet] 210 | 211 | main() { 212 | 213 | ensure_wget 214 | 215 | if [[ "${FEATURES_VNC}" == "1" ]] ; then 216 | 217 | cache_tigervnc 218 | if [[ $? -ne 0 ]] ; then return 1 ; fi 219 | fi 220 | 221 | if [[ "${FEATURES_NOVNC}" == "1" ]] ; then 222 | 223 | cache_novnc 224 | if [[ $? -ne 0 ]] ; then return 1 ; fi 225 | 226 | cache_websockify 227 | if [[ $? -ne 0 ]] ; then return 1 ; fi 228 | fi 229 | 230 | if [[ "${FEATURES_CHROMIUM}" == "1" ]] ; then 231 | 232 | cache_chromium 233 | if [[ $? -ne 0 ]] ; then return 1 ; fi 234 | fi 235 | 236 | echo 237 | } 238 | 239 | declare _quiet="" 240 | declare _mark="\n==> G3-CACHE" 241 | declare _cache="${_build_context}/.g3-cache" 242 | declare _shared_cache_path="${SHARED_G3_CACHE_PATH}" 243 | 244 | if [[ $# -gt 0 && "${1}" =~ -q|--quiet ]] ; then 245 | 246 | _quiet="q" 247 | shift 248 | fi 249 | 250 | ### main entry point 251 | declare -i __exit_code=0 252 | main $@ 253 | 254 | __exit_code=$? 255 | 256 | echo -e "\n==> FINISHED @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 257 | 258 | exit ${__exit_code} 259 | -------------------------------------------------------------------------------- /docker/hooks/env.rc: -------------------------------------------------------------------------------- 1 | ### All variables in capitals can be set also from the same name environment variables. 2 | 3 | die() { 4 | local message="${1:-(unknown)}" 5 | local -i code=${2:-1} 6 | local place="${3:-$0}" 7 | 8 | echo -e "EXITING at line "${BASH_LINENO[0]}" in '${place}' with code ${code}: ${message}" >&2 9 | exit ${code} 10 | } 11 | 12 | ### build context is the path to the Dockerfile 13 | ### it is expected that '_mydir' is already set by the calling script 14 | declare _build_context="$(dirname ${_mydir})" 15 | 16 | ### be careful with moving this block 17 | ### supporting development and testing 18 | if [[ -f "${_build_context}/hooks/secrets.rc" ]]; then 19 | 20 | source "${_build_context}/hooks/secrets.rc" 21 | fi 22 | 23 | ### Docker Hub: GitHub source branch to use 24 | ### local: virtual source branch (technically always the current git branch) 25 | declare _branch="${SOURCE_BRANCH:-$1}" 26 | 27 | ### which image variation to build (feature blend) 28 | declare _blend="${DOCKER_TAG:-$2}" 29 | 30 | ### owner of the builder and deployment repositories must be the same 31 | declare _owner="${REPO_OWNER_NAME:?Need repo owner name}" 32 | 33 | ### utility scripts 34 | declare _script_release_of="release_of" 35 | 36 | ### using this repository name will prohibit the publishing 37 | declare _prohibited_repo_name="void" 38 | 39 | ### Originally (generation G3) this was the name of the Docker Hub repository 40 | ### where the images have been built (the builder repository). 41 | ### It has been initialized by the environment on the Docker Hub. 42 | ### Since the generation G3v2, the builder repository is optional, because the images 43 | ### are built outside the Docker Hub. However, it can be used as a secondary 44 | ### deployment repository, even if it still be referenced as a 'builder repository'. 45 | ### The images in this secondary deployment repository will be distinguished by their tags. 46 | ### Publishing to the builder repository is controlled by the variable 'FORCE_PUBLISHING_BUILDER_REPO'. 47 | ### Note that using the prohibited repository name ('void' by default) will prohibit the publishing. 48 | DOCKER_REPO="${_owner}/${BUILDER_REPO:?Need builder repo name}" 49 | 50 | declare _deploy_repo 51 | 52 | ### arrays of the image tags to be deployed 53 | declare -a _deploy_builder_tags 54 | declare -a _deploy_tags 55 | declare _deploytag 56 | 57 | ### relative path to the readme file resources (relative to the project root) 58 | declare _readme_context 59 | 60 | ### examples 61 | # VERSION_STICKER_PREFIX=${VERSION_STICKER_SUFFIX:-"BETA-"} 62 | # VERSION_STICKER_SUFFIX=${VERSION_STICKER_SUFFIX:-"-BETA"} 63 | 64 | ### suffix added to the helper image name 65 | declare helper_suffix="-helper" 66 | 67 | ### be careful with moving this statement 68 | ### remove the first two command line arguments ( ) 69 | if [[ $# -ge 2 ]]; then shift 2; fi 70 | 71 | ### Features can be enabled or disabled by setting the related variables. 72 | ### Setting it to "0" disables the feature. 73 | ### Setting it to "1" enforces the feature. 74 | ### Anything else, including null and empty string, does not change the feature's default value. 75 | ### NOTE: They are also other feature environment variables that are set directly in the Dockerfile. 76 | ### FEATURES_BUILD_SLIM: if to add '--no-install-recommends' to 'apt-get install' 77 | ### FEATURES_NOVNC: if 'noVNC' and 'websockify' should be included 78 | ### FEATURES_SCREENSHOOTING: if 'xfce4-screenshooter' and 'ristretto' should be included 79 | ### FEATURES_THUMBNAILING: if 'tumbler' should be included 80 | ### FEATURES_OVERRIDING_ENVV: if overriding environment variables at container startup time should be enabled 81 | ### Remark: There are also 'FEATURES_*' variables that are always set, e.g. 'FEATURES_VERSION_STICKER=1'. 82 | 83 | ### These features influence the content of almost all stages: 84 | ### Warning! Anything except '0' means '1', even unset or empty. 85 | if [[ "${FEATURES_BUILD_SLIM}" == "0" ]]; then FEATURES_BUILD_SLIM=""; else FEATURES_BUILD_SLIM=1; fi 86 | 87 | ### These features influence the content of the related stages: 88 | if [[ "${FEATURES_SCREENSHOOTING}" == "1" ]]; then FEATURES_SCREENSHOOTING=1; else FEATURES_SCREENSHOOTING=""; fi 89 | if [[ "${FEATURES_THUMBNAILING}" == "1" ]]; then FEATURES_THUMBNAILING=1; else FEATURES_THUMBNAILING=""; fi 90 | 91 | ### These features influence the building graph: 92 | if [[ "${FEATURES_CHROMIUM}" == "1" ]]; then FEATURES_CHROMIUM=1; else FEATURES_CHROMIUM=""; fi 93 | if [[ "${FEATURES_FIREFOX}" == "1" ]]; then FEATURES_FIREFOX=1; else FEATURES_FIREFOX=""; fi 94 | 95 | ### These features influence container behaviour at startup time 96 | ### Warning! Anything except '0' means '1', even unset or empty. 97 | if [[ "${FEATURES_OVERRIDING_ENVV}" == "0" ]]; then FEATURES_OVERRIDING_ENVV=""; else FEATURES_OVERRIDING_ENVV=1; fi 98 | 99 | ### These features are always enabled and cannot be disabled via environment variables 100 | FEATURES_VNC=1 101 | 102 | ### These features are enabled by default but can be disabled via environment variables (see below) 103 | ### however, they can be disabled via environment variables (see below) 104 | # if [[ "${FEATURES_NOVNC}" == "1" ]] ; then FEATURES_NOVNC=1 ; else FEATURES_NOVNC="" ; fi 105 | # if [[ "${FEATURES_FIREFOX_PLUS}" == "1" ]] ; then FEATURES_FIREFOX_PLUS=1 ; else FEATURES_FIREFOX_PLUS="" ; fi 106 | 107 | ### The reason for this 'case' is to support some special branches/builds if required. 108 | case "${_branch}" in 109 | 110 | ### default (master), developer (dev, dev-*) and release (v*) builds 111 | master | dev | dev-* | v*) 112 | 113 | ### fallback to defaults if not provided 114 | BASEIMAGE="${BASEIMAGE:-ubuntu}" 115 | 116 | ### hardcoded settings 117 | TIGERVNC_VERSION="1.13.1" # overridden bellow 118 | TIGERVNC_DISTRO="x86_64" 119 | NOVNC_VERSION="1.6.0" 120 | WEBSOCKIFY_VERSION="0.13.0" 121 | CHROMIUM_DISTRO="amd64" 122 | 123 | ### --------------------------- 124 | ### ubuntu-vnc-xfce-g3 125 | ### ubuntu-vnc-xfce-firefox-g3 126 | ### ubuntu-vnc-xfce-chromium-g3 127 | ### --------------------------- 128 | 129 | ### choose the Dockerfile 130 | case "${_blend}" in 131 | 132 | latest | latest-chromium | latest-firefox | noble | noble-chromium | noble-firefox | \ 133 | 24.04 | 24.04-chromium | 24.04-firefox) 134 | 135 | BASETAG="24.04" 136 | DOCKERFILE_PATH="${_build_context}/Dockerfile.xfce.24-04" 137 | TIGERVNC_VERSION="1.15.0" 138 | ;; 139 | 140 | jammy | jammy-chromium | jammy-firefox | 22.04 | 22.04-chromium | 22.04-firefox) 141 | 142 | BASETAG="22.04" 143 | DOCKERFILE_PATH="${_build_context}/Dockerfile.xfce.22-04" 144 | ;; 145 | 146 | focal | focal-chromium | focal-firefox | 20.04 | 20.04-chromium | 20.04-firefox) 147 | 148 | BASETAG="20.04" 149 | DOCKERFILE_PATH="${_build_context}/Dockerfile.xfce.20-04" 150 | ;; 151 | 152 | any) 153 | # just allowing 'any' blend 154 | ;; 155 | 156 | *) 157 | die "Unsupported blend '${_blend}'" -1 'env.rc' 158 | ;; 159 | esac 160 | 161 | ### set the building parameters 162 | case "${_blend}" in 163 | 164 | latest | latest-chromium | latest-firefox | \ 165 | noble | noble-chromium | noble-firefox | 24.04 | 24.04-chromium | 24.04-firefox | \ 166 | jammy | jammy-chromium | jammy-firefox | 22.04 | 22.04-chromium | 22.04-firefox | \ 167 | focal | focal-chromium | focal-firefox | 20.04 | 20.04-chromium | 20.04-firefox ) 168 | 169 | ### this feature is enabled by default 170 | ### however, it can be disabled via environment variables (export FEATURES_NOVNC=0) 171 | if [[ "${FEATURES_NOVNC}" == "0" ]]; then 172 | FEATURES_NOVNC="" 173 | else 174 | FEATURES_NOVNC="1" 175 | fi 176 | 177 | ### images with chromium 178 | if [[ "${_blend}" =~ chromium ]]; then 179 | 180 | FEATURES_CHROMIUM=1 181 | 182 | CHROMIUM_VERSION=$("${_mydir}"/${_script_release_of} 'chromium-1804') 183 | 184 | if [[ $? -ne 0 ]]; then 185 | echo "${CHROMIUM_VERSION}" 186 | exit 1 187 | fi 188 | 189 | _deploy_repo="${_owner}/${DEPLOYMENT_REPO_CHROMIUM}" 190 | _readme_context="docker/xfce-chromium" 191 | else 192 | FEATURES_CHROMIUM="" 193 | fi 194 | 195 | ### images with firefox 196 | if [[ "${_blend}" =~ firefox ]]; then 197 | 198 | FEATURES_FIREFOX=1 199 | 200 | ### this feature is enabled by default 201 | ### however, it can be disabled via environment variables (export FEATURES_FIREFOX_PLUS=0) 202 | if [[ "${FEATURES_FIREFOX_PLUS}" == "0" ]]; then 203 | FEATURES_FIREFOX_PLUS="" 204 | else 205 | FEATURES_FIREFOX_PLUS="1" 206 | fi 207 | 208 | _deploy_repo="${_owner}/${DEPLOYMENT_REPO_FIREFOX}" 209 | _readme_context="docker/xfce-firefox" 210 | else 211 | FEATURES_FIREFOX="" 212 | FEATURES_FIREFOX_PLUS="" 213 | fi 214 | 215 | ### base images 216 | if [[ ! "${_blend}" =~ chromium|firefox ]]; then 217 | 218 | ### be sure to reset these features 219 | FEATURES_CHROMIUM="" 220 | FEATURES_FIREFOX="" 221 | FEATURES_FIREFOX_PLUS="" 222 | 223 | _deploy_repo="${_owner}/${DEPLOYMENT_REPO}" 224 | _readme_context="docker/xfce" 225 | fi 226 | 227 | ### normalize deployment tags 228 | case "${_blend}" in 229 | 230 | latest | latest-* | 24.04 | 24.04-* ) 231 | 232 | ### latest -> 24.04 233 | DOCKER_TAG="${_blend}" 234 | _deploy_tags=("latest" "24.04") 235 | _deploy_builder_tags=("${_blend}" "${_blend/latest/24.04}") 236 | ;; 237 | 238 | noble | noble-* | 24.04 | 24.04-* ) 239 | 240 | ### noble -> 24.04 241 | DOCKER_TAG="${_blend/noble/24.04}" 242 | _deploy_tags=("latest" "24.04") 243 | _deploy_builder_tags=("${_blend/noble/latest}" "${_blend/noble/24.04}") 244 | ;; 245 | 246 | jammy | jammy-* | 22.04 | 22.04-* ) 247 | ### jammy -> 22.04 248 | DOCKER_TAG="${_blend/jammy/22.04}" 249 | _deploy_tags=("22.04") 250 | _deploy_builder_tags=("${_blend/jammy/22.04}") 251 | ;; 252 | 253 | focal | focal-* | 20.04 | 20.04-* ) 254 | ### focal -> 20.04 255 | DOCKER_TAG="${_blend/focal/20.04}" 256 | _deploy_tags=("20.04") 257 | _deploy_builder_tags=("${_blend/focal/20.04}") 258 | ;; 259 | 260 | any) 261 | # just allowing 'any' blend 262 | echo "Warning from 'env.rc': Allowing 'any' blend!" 263 | ;; 264 | 265 | *) 266 | die "Unsupported blend '${_blend}'" -1 'env.rc' 267 | ;; 268 | 269 | esac 270 | 271 | ### add optional suffixes to deployment tags 272 | 273 | if [[ "${FEATURES_FIREFOX}" == "1" && -z "${FEATURES_FIREFOX_PLUS}" ]]; then 274 | 275 | DOCKER_TAG="${DOCKER_TAG}-default" 276 | for i in "${!_deploy_tags[@]}"; do 277 | _deploy_tags[$i]="${_deploy_tags[$i]}-default" 278 | done 279 | fi 280 | 281 | if [[ -z "${FEATURES_NOVNC}" ]]; then 282 | 283 | DOCKER_TAG="${DOCKER_TAG}-vnc" 284 | for i in "${!_deploy_tags[@]}"; do 285 | _deploy_tags[$i]="${_deploy_tags[$i]}-vnc" 286 | done 287 | fi 288 | ;; 289 | 290 | any) 291 | # just allowing 'any' blend 292 | echo "Warning from 'env.rc': Allowing 'any' blend!" 293 | ;; 294 | 295 | *) 296 | die "Unsupported blend '${_blend}'" -1 'env.rc' 297 | ;; 298 | 299 | esac 300 | ;; 301 | 302 | any) 303 | # just allowing 'any' branch 304 | echo "Warning from 'env.rc': Allowing 'any' branch!" 305 | ;; 306 | 307 | *) 308 | die "Unsupported branch '${_branch}'" -1 'env.rc' 309 | ;; 310 | 311 | esac 312 | -------------------------------------------------------------------------------- /docker/hooks/helper: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # echo -e "\n==> EXECUTING @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 4 | 5 | declare _mydir=$(dirname $0) 6 | source "${_mydir}"/env.rc 7 | 8 | get_builder_image_name() { 9 | echo "${DOCKER_REPO}:${_deploy_builder_tags[0]}" 10 | } 11 | 12 | get_deployment_image_name() { 13 | echo "${_deploy_repo}:${_deploy_tags[0]}" 14 | } 15 | 16 | main() { 17 | local cmd="${1?Need command}" 18 | 19 | if [[ "${cmd}" == "help" ]]; then 20 | 21 | cat < 26 | 27 | := (any|dev|(or see 'env.rc')) 28 | (any|(or see 'env.rc')) 29 | := (help|--help|-h) 30 | (list-target|list-build-target|list-deploy-target) 31 | (pull|pull-deploy-target|pull-build-target) 32 | EOT 33 | 34 | return 0 35 | fi 36 | 37 | case "${cmd}" in 38 | list | list-targets) 39 | echo "Build target => $(get_builder_image_name)" 40 | echo "Deploy target => $(get_deployment_image_name)" 41 | # echo "Build image: $(get_builder_image_name)" 42 | # echo "Deploy image: $(get_deployment_image_name)" 43 | ;; 44 | 45 | list-build-target) 46 | echo "Build target => $(get_builder_image_name)" 47 | ;; 48 | 49 | list-deploy-target) 50 | echo "Deploy target => $(get_deployment_image_name)" 51 | ;; 52 | 53 | pull | pull-deploy-target) 54 | echo 55 | echo "Pulling deploy targets... $(get_deployment_image_name)" 56 | docker pull "$(get_deployment_image_name)" 57 | ;; 58 | 59 | pull-build-target) 60 | echo 61 | echo "Pulling build targets... $(get_builder_image_name)" 62 | echo docker pull "$(get_builder_image_name)" 63 | ;; 64 | 65 | *) 66 | die "Unknown command '${cmd}'." 67 | ;; 68 | esac 69 | } 70 | 71 | main $@ 72 | 73 | # echo -e "\n==> FINISHED @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 74 | -------------------------------------------------------------------------------- /docker/hooks/post_push: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### 2022-09-11 Warning 4 | ### It seems like the README publishing is currently not always working. 5 | ### Some changes on the Docker Hub side seem to be the reason. 6 | ### However, you can always copy the content generated by the utility 7 | ### 'util-readme.sh' ('preview' command) to the Docker Hub manually. 8 | 9 | echo -e "\n==> EXECUTING @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 10 | 11 | declare _mydir=$(dirname $0) 12 | source "${_mydir}"/env.rc 13 | source "${_mydir}"/util.rc 14 | 15 | main() { 16 | ### There is a GitHub Gist containing the endpoints for the badges. 17 | ### Updating the GitHub Gist can be skipped by *not* setting the environment variable GIST_TOKEN. 18 | ### Warning! The value of the GIST_TOKEN is a real secret. 19 | ### The personal access token (PAT) should be created on the GitHub and it requires the 'gist' scope. 20 | 21 | local created 22 | local version_sticker 23 | local version_sticker_verbose 24 | local repo_building="${DOCKER_REPO##*/}" 25 | local repo_deploy="${_deploy_repo##*/}" 26 | local keeper_repo_tag="${_deploy_builder_tags[0]}" 27 | 28 | if [[ ! -f "${_build_context}/${_scrap_demand_stop_building}" ]]; then 29 | 30 | ### essential environment variables must be already set 31 | if [[ -n "${GIST_TOKEN}" && -n "${GIST_ID}" && -n "${DEPLOY_GIST_ID}" ]]; then 32 | 33 | if [[ (-n "${repo_deploy}" && "${repo_deploy}" != "${_prohibited_repo_name}") || 34 | ("${FORCE_PUBLISHING_BUILDER_REPO:-0}" == "1" && -n "${repo_building}" && "${repo_building}" != "${_prohibited_repo_name}") ]]; then 35 | 36 | ### get values for badges from the image metadata (labels) - try the builder image first 37 | ensure_image "${DOCKER_REPO}:${keeper_repo_tag}" 38 | if [[ $? -eq 0 ]]; then 39 | 40 | ### builder image found 41 | echo "Getting badge values from builder image '${DOCKER_REPO}:${keeper_repo_tag}'." 42 | 43 | created=$(get_label "${DOCKER_REPO}:${keeper_repo_tag}" "org.opencontainers.image.created") 44 | version_sticker=$(get_label "${DOCKER_REPO}:${keeper_repo_tag}" "any.accetto.version-sticker") 45 | 46 | echo Wait... generating verbose sticker file "'${_build_context}/${_scrap_version_sticker_verbose_current}'" 47 | docker run --rm "${DOCKER_REPO}:${keeper_repo_tag}" --version-sticker-verbose >"${_build_context}/${_scrap_version_sticker_verbose_current}" 48 | 49 | else 50 | echo "Missing builder image '${DOCKER_REPO}:${keeper_repo_tag}'." 51 | 52 | ### try the deployment image instead (e.g. it could be downloaded manually) 53 | ensure_image "${_deploy_repo}:${_deploy_tags[0]}" 54 | if [[ $? -eq 0 ]]; then 55 | 56 | ### deployment image found 57 | echo "Getting badge values from deployment image '${DOCKER_REPO}:${_deploy_tags[0]}'." 58 | 59 | created=$(get_label "${_deploy_repo}:${_deploy_tags[0]}" "org.opencontainers.image.created") 60 | version_sticker=$(get_label "${_deploy_repo}:${_deploy_tags[0]}" "any.accetto.version-sticker") 61 | 62 | echo Wait... generating current verbose sticker file "'${_build_context}/${_scrap_version_sticker_verbose_current}'" 63 | docker run --rm "${_deploy_repo}:${_deploy_tags[0]}" --version-sticker-verbose >"${_build_context}/${_scrap_version_sticker_verbose_current}" 64 | else 65 | ### no suitable image found - unable to update badge endpoints 66 | echo "Missing deployment image '${_deploy_repo}:${_deploy_tags[0]}'." 67 | 68 | echo "Skipping gist update. Unable to get values for badges." 69 | fi 70 | fi 71 | 72 | if [[ -n "${created}" ]]; then 73 | 74 | version_sticker_verbose=$(cat "${_build_context}/${_scrap_version_sticker_verbose_current}") 75 | 76 | # echo 77 | echo "Badge 'created': ${created}" 78 | echo "Badge 'version_sticker': ${version_sticker}" 79 | echo "Badge 'version_sticker_verbose':" 80 | echo "${version_sticker_verbose}" 81 | echo 82 | 83 | ### update badge endpoints in the builder repository gist 84 | for t in "${_deploy_builder_tags[@]}"; do 85 | 86 | echo 87 | echo "Updating builder gists for '${DOCKER_REPO}:${t}'" 88 | 89 | update_gist "${GIST_ID}" "${_gist_key_created}" "${DOCKER_REPO}" "${t}" "${created}" 90 | update_gist "${GIST_ID}" "${_gist_key_version_sticker}" "${DOCKER_REPO}" "${t}" "${version_sticker}" 91 | update_gist "${GIST_ID}" "${_gist_key_version_sticker_verbose}" "${DOCKER_REPO}" "${t}" "${version_sticker_verbose}" 92 | done 93 | fi 94 | else 95 | echo "Skipping builder gist update because of null or prohibited target repositories." 96 | fi 97 | 98 | ### update badge endpoints for all tags in the deployment repository 99 | if [[ -n "${created}" ]]; then 100 | 101 | if [[ -n "${repo_deploy}" && "${repo_deploy}" != "${_prohibited_repo_name}" ]]; then 102 | 103 | for t in "${_deploy_tags[@]}"; do 104 | 105 | ### note that the builder and deployment repositories could be identical 106 | ### in that case skip the tag which has been already published above 107 | if [[ "${DOCKER_REPO}" != "${_deploy_repo}" || "${keeper_repo_tag}" != "${t}" ]]; then 108 | 109 | echo 110 | echo "Updating deployment gists for '${_deploy_repo}:${t}'" 111 | 112 | update_gist "${DEPLOY_GIST_ID}" "${_gist_key_created}" "${_deploy_repo}" "${t}" "${created}" 113 | update_gist "${DEPLOY_GIST_ID}" "${_gist_key_version_sticker}" "${_deploy_repo}" "${t}" "${version_sticker}" 114 | update_gist "${DEPLOY_GIST_ID}" "${_gist_key_version_sticker_verbose}" "${_deploy_repo}" "${t}" "${version_sticker_verbose}" 115 | fi 116 | done 117 | else 118 | echo -e "\nSkipping update of deployment gist because of null or prohibited deployment repository.\n" 119 | fi 120 | fi 121 | else 122 | echo "Skipping gist update. Required variables not set." 123 | fi 124 | fi 125 | 126 | if [[ "${KEEP_HELPER_FILES}" != "1" ]]; then 127 | 128 | echo "Removing helper files" 129 | cleanup_scrap_files 130 | fi 131 | } 132 | 133 | main $@ 134 | 135 | echo -e "\n==> FINISHED @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 136 | -------------------------------------------------------------------------------- /docker/hooks/pre_build: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo -e "\n==> EXECUTING @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 4 | 5 | declare _mydir=$(dirname $0) 6 | source "${_mydir}"/env.rc 7 | source "${_mydir}"/util.rc 8 | 9 | main() { 10 | local params=$@ 11 | local now 12 | local version_sticker 13 | local -i exit_code=0 14 | 15 | local should_build=${FORCE_BUILDING:-0} 16 | local build_prohibited=${PROHIBIT_BUILDING} 17 | local cache_script="cache" 18 | 19 | ### helper image will be also used as a cache and therefore it must not use a tag 20 | local helper_image="${DOCKER_REPO}"_"${DOCKER_TAG}${helper_suffix}" 21 | 22 | ### refresh local cache 23 | "${_mydir}/${cache_script}" "${_branch}" "${_blend}" 24 | exit_code=$? 25 | if [[ ${exit_code} -ne 0 ]]; then 26 | die "Script '${cache_script}' failed with code ${exit_code}." ${exit_code} 27 | fi 28 | 29 | echo -e "\nRemoving helper files\n" 30 | cleanup_scrap_files 31 | 32 | ### check for the '--target' parameter 33 | if [[ $# -gt 0 ]]; then 34 | 35 | ### no quotes around 'params' 36 | for i in ${params}; do 37 | if [[ "${i}" == "--target" ]]; then 38 | 39 | target_stage="${i}" 40 | 41 | elif [[ -n "${target_stage}" ]]; then 42 | 43 | ### only if '--target' is followed by a value 44 | if [[ ! "${i}" =~ ^- ]]; then 45 | 46 | ### remove the '--target' with its value 47 | params="${params/--target ${i}/}" 48 | fi 49 | break 50 | fi 51 | done 52 | 53 | ### remove the orphaned '--target' (missing value) 54 | if [[ "${target_stage}" == "--target" ]]; then 55 | params="${params/--target/}" 56 | target_stage="" 57 | fi 58 | fi 59 | 60 | ### build a temporary helper image for getting the current version sticker values 61 | 62 | ### no quotes around ${params}! 63 | set -x 64 | docker build ${params} \ 65 | -f "${DOCKERFILE_PATH}" \ 66 | --build-arg BASEIMAGE="${BASEIMAGE}" \ 67 | --build-arg BASETAG="${BASETAG}" \ 68 | \ 69 | ${FEATURES_BUILD_SLIM:+--build-arg ARG_APT_NO_RECOMMENDS=1} \ 70 | ${FEATURES_OVERRIDING_ENVV:+--build-arg ARG_FEATURES_OVERRIDING_ENVV=1} \ 71 | ${FEATURES_SCREENSHOOTING:+--build-arg ARG_FEATURES_SCREENSHOOTING=1} \ 72 | ${FEATURES_THUMBNAILING:+--build-arg ARG_FEATURES_THUMBNAILING=1} \ 73 | \ 74 | ${FEATURES_VNC:+--build-arg ARG_TIGERVNC_DISTRO=${TIGERVNC_DISTRO}} \ 75 | ${FEATURES_VNC:+--build-arg ARG_TIGERVNC_VERSION=${TIGERVNC_VERSION}} \ 76 | \ 77 | ${FEATURES_NOVNC:+--build-arg ARG_NOVNC_VERSION=${NOVNC_VERSION}} \ 78 | ${FEATURES_NOVNC:+--build-arg ARG_WEBSOCKIFY_VERSION=${WEBSOCKIFY_VERSION}} \ 79 | ${FEATURES_NOVNC:+--build-arg ARG_MERGE_STAGE_VNC_BASE="stage_novnc"} \ 80 | \ 81 | ${FEATURES_CHROMIUM:+--build-arg ARG_CHROMIUM_DISTRO=${CHROMIUM_DISTRO}} \ 82 | ${FEATURES_CHROMIUM:+--build-arg ARG_CHROMIUM_VERSION=${CHROMIUM_VERSION}} \ 83 | ${FEATURES_CHROMIUM:+--build-arg ARG_MERGE_STAGE_BROWSER_BASE="stage_chromium"} \ 84 | \ 85 | ${FEATURES_FIREFOX:+--build-arg ARG_MERGE_STAGE_BROWSER_BASE="stage_firefox"} \ 86 | ${FEATURES_FIREFOX_PLUS:+--build-arg ARG_MERGE_STAGE_BROWSER_BASE="stage_firefox_plus"} \ 87 | \ 88 | -t "${helper_image}" "${_build_context}" 89 | 90 | exit_code=$? 91 | set +x 92 | 93 | if [[ ${exit_code} -ne 0 ]]; then 94 | set +x 95 | 96 | die "Failed to build helper image '${helper_image}'" ${exit_code} 97 | fi 98 | 99 | ### get the actual verbose version sticker value from the helper image and store it as the current one 100 | ### note that some apps require display to report their versions correctly (e.g. Ristretto or Screenshooter) 101 | version_sticker="$(docker run --rm ${helper_image} --version-sticker-verbose)" 102 | echo "${version_sticker}" >"${_build_context}/${_scrap_version_sticker_verbose_current}" 103 | echo -e "Current verbose version sticker:\n$(cat ${_build_context}/${_scrap_version_sticker_verbose_current})" 104 | 105 | if [[ "${should_build}" == "1" ]]; then 106 | 107 | echo 108 | echo "Building of new image has been forced." 109 | else 110 | echo 111 | echo "Building of new image has not been forced." 112 | 113 | echo "Getting the previous verbose version sticker value from the builder gist '${GIST_ID}'" 114 | if [[ -n "${GIST_ID}" ]]; then 115 | 116 | get_gist_file "${GIST_ID}" "${DOCKER_REPO}" "${DOCKER_TAG}" "version-sticker-verbose.txt" "${_build_context}/${_scrap_version_sticker_verbose_previous}" 117 | else 118 | ### create an empty file instead 119 | echo -n "" >"${_build_context}/${_scrap_version_sticker_verbose_previous}" 120 | fi 121 | 122 | echo "Comparing verbose version stickers" 123 | if cmp -s "${_build_context}/${_scrap_version_sticker_verbose_current}" "${_build_context}/${_scrap_version_sticker_verbose_previous}"; then 124 | 125 | ### verbose version sticker hasn't changed since the last build - stop building 126 | echo "Verbose version sticker has not changed since the last build, no need for building and deploying a new image." 127 | echo 128 | 129 | ### if this file is present, the building will not continue 130 | echo "Demanding building stop" 131 | touch "${_build_context}/${_scrap_demand_stop_building}" 132 | 133 | else 134 | ### verbose version sticker has changed since the last build - a new image should be built 135 | echo "Verbose version sticker has changed, a new image should be built and deployed." 136 | should_build="1" 137 | fi 138 | fi 139 | 140 | ### get also the actual short version sticker value from the helper image and store it as the current one 141 | ### note that some apps require display to report their versions correctly (e.g. Ristretto or Screenshooter) 142 | version_sticker="$(docker run --rm ${helper_image} --version-sticker)" 143 | 144 | ### save the current short version sticker in any case 145 | ### this allows to delete the blocking file manually and continue building 146 | ### metadata label value 'any.accetto.version-sticker' is filled from this file 147 | echo -n "${VERSION_STICKER_PREFIX}${version_sticker}${VERSION_STICKER_SUFFIX}" >"${_build_context}/${_scrap_version_sticker_current}" 148 | 149 | ### building prohibited by environment variable 150 | ### useful for testing the autobuilding on DockerHub before release 151 | if [[ "${should_build}" == "1" && "${build_prohibited}" == "1" ]]; then 152 | 153 | ### if this file is present, the building will not continue 154 | echo "Building has been prohibited. Demanding building stop" 155 | echo 156 | touch "${_build_context}/${_scrap_demand_stop_building}" 157 | fi 158 | 159 | ### display the actual short version sticker 160 | echo "Current version sticker of '${helper_image}': ${VERSION_STICKER_PREFIX}${version_sticker}${VERSION_STICKER_SUFFIX}" 161 | 162 | ### moved to the 'build' script where the helper image is used as a cache 163 | ### however, there could be also no 'build' call 164 | if [[ -f "${_build_context}/${_scrap_demand_stop_building}" ]]; then 165 | echo; echo "Removing helper image because no 'build' is needed" 166 | docker rmi "${helper_image}" 167 | fi 168 | } 169 | 170 | main $@ 171 | 172 | echo -e "\n==> FINISHED @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 173 | -------------------------------------------------------------------------------- /docker/hooks/push: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo -e "\n==> EXECUTING @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 4 | 5 | declare _mydir=$(dirname $0) 6 | source "${_mydir}"/env.rc 7 | source "${_mydir}"/util.rc 8 | 9 | deployment_push() { 10 | local target 11 | local repo="${_deploy_repo##*/}" 12 | local keeper_repo_tag="${_deploy_builder_tags[0]}" 13 | local -i exit_code=0 14 | 15 | if [[ -n "${repo}" && "${repo}" != "${_prohibited_repo_name}" ]] ; then 16 | 17 | ### push all target tags into the deployment repository 18 | for t in "${_deploy_tags[@]}" ; do 19 | 20 | ### note that the builder and deployment repositories could be identical 21 | ### in that case skip the tag which has been already published above 22 | if [[ "${DOCKER_REPO}" != "${_deploy_repo}" || "${keeper_repo_tag}" != "${t}" ]] ; then 23 | 24 | target="${_deploy_repo}:${t}" 25 | 26 | echo ; echo "Deploying image '${target}'" 27 | docker tag "${DOCKER_REPO}:${keeper_repo_tag}" "${target}" 28 | docker push "${target}" 29 | exit_code=$? 30 | docker rmi "${target}" 31 | 32 | if [[ ${exit_code} -ne 0 ]] ; then 33 | docker logout 34 | die "Unable to push image '${target}'" ${exit_code} 35 | fi 36 | fi 37 | done 38 | 39 | else 40 | echo "Skipping deployment repo push because of null or prohibited deployment repository '${repo}'." 41 | fi 42 | } 43 | 44 | main() { 45 | local target 46 | local repo="${DOCKER_REPO##*/}" 47 | local keeper_repo_tag="${_deploy_builder_tags[0]}" 48 | local -i exit_code=0 49 | 50 | if [[ -f "${_build_context}/${_scrap_demand_stop_building}" ]] ; then 51 | echo "Skipping push on demand." 52 | return 0 53 | fi 54 | 55 | ### Docker Hub log-in 56 | if [[ -n "${DOCKERHUB_USERNAME}" && -n "${DOCKERHUB_PASSWORD}" ]] ; then 57 | 58 | echo "Logging-in on Docker Hub" 59 | echo "${DOCKERHUB_PASSWORD}" | docker login -u "${DOCKERHUB_USERNAME}" --password-stdin 60 | 61 | if [[ ! $? ]] ; then 62 | 63 | echo "Docker Hub login failed" 64 | return 1 65 | fi 66 | 67 | else 68 | echo "Push requires Docker Hub login." 69 | echo "However, your environment does not provide required authentication data." 70 | return 1 71 | fi 72 | 73 | ### push images into the builder repository 74 | if [[ "${FORCE_PUBLISHING_BUILDER_REPO:-0}" == "1" ]] ; then 75 | 76 | if [[ -n "${repo}" && "${repo}" != "${_prohibited_repo_name}" ]] ; then 77 | 78 | ### push all target tags into the builder repository 79 | for t in "${_deploy_builder_tags[@]}" ; do 80 | 81 | echo ; echo "Pushing builder image ${DOCKER_REPO}:${t}" 82 | 83 | if [[ "${t}" == "${keeper_repo_tag}" ]] ; then 84 | 85 | # first element is the master repo (a keeper) 86 | docker push "${DOCKER_REPO}:${t}" 87 | exit_code=$? 88 | 89 | if [[ ${exit_code} -ne 0 ]] ; then 90 | docker logout 91 | die "Unable to push image '${DOCKER_REPO}:${t}'" ${exit_code} 92 | fi 93 | else 94 | target="${DOCKER_REPO}:${t}" 95 | 96 | docker tag "${DOCKER_REPO}:${keeper_repo_tag}" "${target}" 97 | docker push "${target}" 98 | exit_code=$? 99 | docker rmi "${target}" 100 | 101 | if [[ ${exit_code} -ne 0 ]] ; then 102 | docker logout 103 | die "Unable to push image '${target}'" ${exit_code} 104 | fi 105 | fi 106 | done 107 | 108 | else 109 | echo "Skipping forced builder repo push because of null or prohibited builder repository '${repo}'." 110 | fi 111 | fi 112 | 113 | ### push images into the deployment repository 114 | deployment_push 115 | 116 | ### Docker Hub log-out 117 | docker logout 118 | } 119 | 120 | main $@ 121 | 122 | echo -e "\n==> FINISHED @$(date -u +'%Y-%m-%d_%H-%M-%S'): ${0} $@\n" 123 | -------------------------------------------------------------------------------- /docker/hooks/release_of: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | main() { 4 | local result="" 5 | local response="" 6 | local truncateMax=1000 7 | 8 | case "$1" in 9 | 10 | chromium-1804 ) 11 | # result=$(wget -qO- \ 12 | # result=$(curl -sLN \ 13 | # http://archive.ubuntu.com/ubuntu/pool/universe/c/chromium-browser/ \ 14 | # | grep -Po -m1 '(?<=href=")[^_]*_([0-9.]+-0ubuntu\d+\.18\.04\.[^_"]*)_[^"]*' \ 15 | # | cut -d _ -f 2 \ 16 | # ) 17 | response=$(curl -sLN http://archive.ubuntu.com/ubuntu/pool/universe/c/chromium-browser/) 18 | if [[ -n "${response}" ]] ; then 19 | result=$(echo "${response}" | grep -Po -m1 '(?<=href=")[^_]*_([0-9.]+-0ubuntu\d+\.18\.04\.[^_"]*)_[^"]*' | cut -d _ -f 2) 20 | fi 21 | ;; 22 | 23 | * ) 24 | echo "Exiting '${0}' with code '1' because of unknown key '${1}'" 25 | return 1 26 | ;; 27 | 28 | esac 29 | 30 | if [[ -n "${result}" ]] ; then 31 | 32 | echo "${result}" 33 | else 34 | echo "ERROR: Exiting '${0}' with code '1' because unable to get version of '$1'" 35 | echo "ERROR: Unexpected HTTPS response (truncated to $truncateMax):" 36 | ### don't use quotes here 37 | echo ${response:0:truncateMax} 38 | return 1 39 | fi 40 | } 41 | 42 | main $@ 43 | -------------------------------------------------------------------------------- /docker/hooks/util.rc: -------------------------------------------------------------------------------- 1 | ### prefix for temporary scrap files 2 | declare _scrap_prefix=${SCRAP_PREFIX:-scrap-} 3 | 4 | ### temporary scrap helper files 5 | declare _scrap_version_sticker_current="${_scrap_prefix}version_sticker_current.tmp" 6 | declare _scrap_version_sticker_verbose_current="${_scrap_prefix}version_sticker-verbose_current.tmp" 7 | declare _scrap_version_sticker_verbose_previous="${_scrap_prefix}version_sticker-verbose_previous.tmp" 8 | declare _scrap_demand_stop_building="${_scrap_prefix}demand-stop-building" 9 | 10 | ### gist file keys 11 | declare _gist_key_created="created.json" 12 | declare _gist_key_version_sticker="version-sticker.json" 13 | declare _gist_key_version_sticker_verbose="version-sticker-verbose.txt" 14 | 15 | log() { 16 | ### Function to log messages with timestamps and log levels 17 | 18 | local level="$1" 19 | local message="$2" 20 | echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $message" 21 | } 22 | 23 | validate_gist_token() { 24 | ### Function to check if GIST_TOKEN is set and has valid scope 25 | if [[ -z "${GIST_TOKEN:-}" ]]; then 26 | log "ERROR" "GIST_TOKEN is not set. Skipping gist update." 27 | exit 1 28 | fi 29 | 30 | # Test token scope 31 | local test_result 32 | test_result=$(curl -s -H "Authorization: token ${GIST_TOKEN}" https://api.github.com/rate_limit || echo "invalid") 33 | if [[ "${test_result}" == "invalid" ]]; then 34 | log "ERROR" "Invalid GIST_TOKEN or insufficient permissions." 35 | exit 1 36 | fi 37 | } 38 | 39 | cleanup_scrap_files() { 40 | rm -f "${_build_context}/${_scrap_prefix}"* 41 | } 42 | 43 | encode_json_quotes() { 44 | ### Encode double-quotes for use in JSON 45 | echo "${1//\"/\\\"}" 46 | } 47 | 48 | encode_json_newlines() { 49 | ### Encodes new-lines for use in JSON 50 | echo $(echo -e "${1}" | sed -z 's/\n/\\n/g') 51 | } 52 | 53 | ensure_image() { 54 | ### Checks if the given image exists. 55 | 56 | local image=${1?Need image} 57 | 58 | if [[ -n "$(docker image ls -q ${image})" ]]; then 59 | return 0 60 | else 61 | return 1 62 | fi 63 | } 64 | 65 | ensure_utility() { 66 | ### Checks availability of the given utility. 67 | ### It can be effectively disabled by providing 'enforced_error_code=0'. 68 | 69 | local util_name="${1?Need utility name}" 70 | local enforced_error_code=${2?Need enforced error code} 71 | 72 | if command -v "${util_name}" >/dev/null; then 73 | return 0 74 | else 75 | return ${enforced_error_code} 76 | fi 77 | } 78 | 79 | get_label() { 80 | ### Returning the given label value via the predefined global variable. 81 | 82 | local repotag="$1" 83 | local label="$2" 84 | 85 | echo $(docker inspect "${repotag}" --format='{{ index .Config.Labels "'${label}'" }}') 86 | } 87 | 88 | make_gist_filename() { 89 | ### Returns correctly formatted gist member file name 90 | 91 | local repo="${1?Need repo}" 92 | local tag="${2?Need repo tag}" 93 | local filename="${3?Need file name}" 94 | 95 | echo "$(basename ${repo})"@"${tag}"@"${filename}" 96 | } 97 | 98 | get_gist_file() { 99 | ### Gets the specified file from the secret gist. 100 | 101 | local gist=${1?Need gist ID} 102 | local repo="${2?Need repo}" 103 | local tag="${3?Need repo tag}" 104 | local filename="${4?Need file name}" 105 | local output_file="${5?Need output file}" 106 | 107 | local gist_filename 108 | local result 109 | 110 | gist_filename=$(make_gist_filename "${repo}" "${tag}" "${filename}") 111 | 112 | ### assumption: 'output_file' is the full file name correctly composed by the caller 113 | ### note that the dummy parameter '?$(date +%s)' is added to the URL to avoid caching 114 | # set -x 115 | result=$(curl -s \ 116 | -X GET \ 117 | --write-out "%{http_code}" \ 118 | -o "${output_file}" \ 119 | -H "Accept: application/vnd.github.v3+json" \ 120 | "https://gist.githubusercontent.com/${_owner}/${gist}/raw/${gist_filename}/?$(date +%s)") 121 | # set +x 122 | 123 | if [[ "${result}" == "200" ]]; then 124 | echo "Gist file '${gist_filename}' saved as '${output_file}'." 125 | return 0 126 | elif [[ "${result}" == "404" ]]; then 127 | echo 128 | echo "Gist file '${gist_filename}' not found." 129 | return 0 130 | else 131 | echo "Getting gist file '${gist_filename}' failed: ${result}" 132 | return 2 133 | fi 134 | } 135 | 136 | list_labels() { 137 | ### Listing all image labels. 138 | ### Just debugging support. 139 | 140 | local repotag="$1" 141 | 142 | # docker inspect "${repotag}" --format='{{println}} {{ range $k, $v := .Config.Labels -}} {{ $k }}={{ $v }} {{println}} {{end -}}' 143 | 144 | docker inspect "${repotag}" --format=' 145 | {{ range $k, $v := .Config.Labels -}} 146 | {{ $k }}={{ $v }} 147 | {{end -}}' 148 | } 149 | 150 | update_gist() { 151 | ### Updating the secret GitHub gist containing data (e.g. badge endpoints). 152 | ### 'GIST_TOKEN' secret (PAT) with the 'gist' scope is required 153 | local gist=${1?Need gist ID} 154 | local gist_key="${2?Need gist key}" 155 | local repo="${3?Need repo}" 156 | local tag="${4?Need repo tag}" 157 | local content="${5?Need content}" 158 | 159 | local data 160 | local envelope 161 | local gist_filename 162 | local result 163 | 164 | if [[ -z "${GIST_TOKEN}" ]]; then 165 | 166 | echo "Skipping gist update. Required variables not set." 167 | return 0 168 | fi 169 | 170 | case "${gist_key}" in 171 | "${_gist_key_created}") 172 | 173 | envelope='{"schemaVersion": 1,"label":"created","message":"'${content}'","color":"blue"}' 174 | ;; 175 | 176 | "${_gist_key_version_sticker}") 177 | 178 | envelope='{"schemaVersion": 1,"label":"version sticker","message":"'${content}'","color":"blue"}' 179 | ;; 180 | 181 | "${_gist_key_version_sticker_verbose}") 182 | 183 | envelope="${content}" 184 | ;; 185 | *) 186 | echo "Skipping gist update. Unsupported gist key '${gist_key}'." 187 | return 0 188 | ;; 189 | esac 190 | 191 | gist_filename=$(make_gist_filename "${repo}" "${tag}" "${gist_key}") 192 | 193 | ### encode double-quotes 194 | # envelope="${envelope//\"/\\\"}" 195 | envelope=$(encode_json_quotes "${envelope}") 196 | 197 | ### encode new-lines 198 | # envelope=$( echo "${envelope}" | sed -z 's/\n/\\n/g' ) 199 | ### be careful with quotes! 200 | envelope=$(encode_json_newlines "${envelope}") 201 | 202 | data='{ "files": { "'${gist_filename}'": { "filename": "'${gist_filename}'", "content": "'${envelope}'" } } }' 203 | 204 | echo "Updating gist '${gist_filename}'" 205 | 206 | local max_retries=3 207 | local retry_delay=5 # seconds 208 | 209 | ### required 'GIST_TOKEN' (PAT) scope is 'gist' 210 | 211 | for attempt in $(seq 1 ${max_retries}); do 212 | echo "Attempt ${attempt} of ${max_retries}..." 213 | 214 | result=$(curl -s \ 215 | -X PATCH \ 216 | -o /dev/null \ 217 | --write-out "%{http_code}" \ 218 | -H "Authorization: token ${GIST_TOKEN}" \ 219 | -H "Accept: application/vnd.github.v3+json" \ 220 | https://api.github.com/gists/${gist} \ 221 | -d "${data}") 222 | 223 | if [[ "${result}" == "200" ]]; then 224 | echo "Gist '${gist_filename}' updated successfully on attempt ${attempt}" 225 | return 0 226 | fi 227 | 228 | echo "Attempt '${attempt}' failed with HTTP code: ${result}. Retrying in ${retry_delay} seconds..." 229 | sleep ${retry_delay} 230 | done 231 | 232 | echo "ERROR: Gist update failed after ${max_retries} attempts." 233 | return 1 234 | } 235 | -------------------------------------------------------------------------------- /docker/src/home/.bashrc: -------------------------------------------------------------------------------- 1 | ### some examples of custom aliases 2 | 3 | alias ll="ls -l" 4 | 5 | ### clear terminal window 6 | alias cls='printf "\033c"' 7 | 8 | ### change terminal prompt text 9 | fn_ps1() { 10 | if [ $# -gt 0 ] ; then 11 | ### given value in bold green 12 | PS1="\[\033[01;32m\]$1\[\033[00m\]> " 13 | else 14 | ### basename of the current working directory in bold blue 15 | PS1='\[\033[01;34m\]\W\[\033[00m\]> ' 16 | fi 17 | } 18 | alias ps1='fn_ps1' 19 | -------------------------------------------------------------------------------- /docker/src/tests/test-01.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | main () { 3 | local -a list=() 4 | list+=("id") 5 | list+=("ls -l /etc/passwd /etc/group") 6 | list+=("tail -n2 /etc/passwd") 7 | list+=("tail -n2 /etc/group") 8 | list+=("ls -ld ${STARTUPDIR} /home ${HOME}") 9 | list+=("ls -l ${STARTUPDIR}") 10 | list+=("mkdir -p ${HOME}/new-dir") 11 | list+=("touch ${HOME}/new-file") 12 | list+=("ls -l ${HOME}") 13 | for t in "${list[@]}" ; do 14 | echo -e "+ ${t}" 15 | ${t} 16 | done 17 | } 18 | main | tee test-01.log 19 | -------------------------------------------------------------------------------- /docker/src/xfce-startup/help.rc: -------------------------------------------------------------------------------- 1 | print_usage() { 2 | local readonly github_repo_url="https://github.com/accetto/ubuntu-vnc-xfce-g3" 3 | 4 | echo " 5 | CONTAINER USAGE: 6 | docker run [] accetto/: [] [] 7 | 8 | POSITIONAL ARGUMENTS: 9 | command 10 | Optional command with optional arguments. 11 | It will be executed during startup before going waiting, tailing or asleep. 12 | It is necessary to use the quotes correctly or the 'bash -c \"\"' pattern. 13 | 14 | STARTUP OPTIONS: 15 | 16 | --wait, or no options, or unknown option, or empty input 17 | Default background execution mode. 18 | Starts the VNC and noVNC servers, if available, then executes the command 19 | and waits until the VNC server process exits or goes asleep infinitely. 20 | Container keeps running in the background. 21 | 22 | --skip-startup 23 | Default foreground execution mode. 24 | Skips the startup procedure, executes the command and exits. 25 | Be aware that the container user generator will be also skipped. 26 | Container does not keep running in the background. 27 | 28 | --tail-null 29 | Alternative background execution mode. 30 | Similar to '--wait', but tails the null device instead of going asleep. 31 | Container keeps running in the background. 32 | 33 | --tail-vnc 34 | Alternative background execution mode. 35 | Similar to '--wait', but tails the VNC log instead of waiting until the VNC process exits. 36 | Falls back to '--tail-null' if the VNC server has not been started. 37 | Container keeps running in the background. 38 | 39 | --version-sticker 40 | Alternative foreground execution mode. 41 | Prints out the version sticker info. 42 | The VNC server is also started by default, if available, because some applications 43 | need a display to report their versions correctly. It can be suppressed by providing 44 | also '--skip-vnc'. The '--skip-novnc' option is always enforced automatically. 45 | Container does not keep running in the background. 46 | 47 | --version-sticker-verbose 48 | Alternative foreground execution mode. 49 | Similar to '--version-sticker', but prints out the verbose version sticker info and features list. 50 | Container does not keep running in the background. 51 | 52 | --skip-vnc 53 | Startup process modifier. 54 | If VNC and noVNC startup should be skipped. 55 | It also enforces '--skip-novnc'. 56 | 57 | --skip-novnc 58 | Startup process modifier. 59 | If noVNC startup should be skipped. 60 | It is also enforced by '--skip-vnc'. 61 | 62 | --debug 63 | Startup process modifier. 64 | If additional debugging info should be displayed during startup. 65 | It also enforces option '--verbose'. 66 | 67 | --verbose 68 | Startup process modifier. 69 | If startup progress messages should be displayed. 70 | It is also enforced by '--debug'. 71 | 72 | --help-usage, -H 73 | Prints out this extended container usage help and exits. 74 | The rest of the input is ignored. 75 | 76 | --help, -h 77 | Prints out the short startup script help and exits. 78 | The rest of the input is ignored. 79 | 80 | --version, -v 81 | Prints out the version of the startup script and exits. 82 | The rest of the input is ignored. 83 | 84 | Use '-h' or '--help' for short startup script help. 85 | Fore more information visit ${github_repo_url} 86 | " 87 | } 88 | -------------------------------------------------------------------------------- /docker/src/xfce-startup/parser.rc: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### If using 'accetto/argbash-docker' image, then rebuild as 'argbash parser.rc --strip user-content' 4 | ### Then test it as './startup.sh -v' or './startup.sh -h' or './startup.sh -H' 5 | 6 | # Created by argbash-init v2.8.1 7 | # ARG_VERSION([echo $(basename $0) v20.12.06]) 8 | # ARG_HELP([Container startup script],[Use '-H' or '--help-usage' for extended container usage help.\nFor more information visit https://github.com/accetto/ubuntu-vnc-xfce-g3]) 9 | # ARG_OPTIONAL_ACTION([help-usage],[H],[Extended container usage help.],[print_usage]) 10 | # 11 | # ARG_POSITIONAL_INF([command],[Optional command with optional arguments. It is executed during startup.]) 12 | # 13 | # ARG_POSITIONAL_DOUBLEDASH([]) 14 | # 15 | # ARG_OPTIONAL_BOOLEAN([wait],[],[Default background execution mode],[on]) 16 | # ARG_OPTIONAL_BOOLEAN([skip-startup],[],[Default foreground execution mode]) 17 | # 18 | # ARG_OPTIONAL_BOOLEAN([tail-null],[],[Alternative background execution mode]) 19 | # ARG_OPTIONAL_BOOLEAN([tail-vnc],[],[Alternative background execution mode]) 20 | # 21 | # ARG_OPTIONAL_BOOLEAN([version-sticker],[],[Alternative foreground execution mode]) 22 | # ARG_OPTIONAL_BOOLEAN([version-sticker-verbose],[],[Alternative foreground execution mode]) 23 | # 24 | # ARG_OPTIONAL_BOOLEAN([skip-vnc],[],[Startup process modifier]) 25 | # ARG_OPTIONAL_BOOLEAN([skip-novnc],[],[Startup process modifier]) 26 | # ARG_OPTIONAL_BOOLEAN([debug],[],[Startup process modifier]) 27 | # ARG_OPTIONAL_BOOLEAN([verbose],[],[Startup process modifier]) 28 | # 29 | # ARGBASH_GO() 30 | # needed because of Argbash --> m4_ignore([ 31 | ### START OF CODE GENERATED BY Argbash v2.8.1 one line above ### 32 | # Argbash is a bash code generator used to get arguments parsing right. 33 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info 34 | 35 | 36 | die() 37 | { 38 | local _ret="${2:-1}" 39 | test "${_PRINT_HELP:-no}" = yes && print_help >&2 40 | echo "$1" >&2 41 | exit "${_ret}" 42 | } 43 | 44 | 45 | begins_with_short_option() 46 | { 47 | local first_option all_short_options='vhH' 48 | first_option="${1:0:1}" 49 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 50 | } 51 | 52 | # THE DEFAULTS INITIALIZATION - POSITIONALS 53 | _positionals=() 54 | _arg_command=() 55 | # THE DEFAULTS INITIALIZATION - OPTIONALS 56 | _arg_wait="on" 57 | _arg_skip_startup="off" 58 | _arg_tail_null="off" 59 | _arg_tail_vnc="off" 60 | _arg_version_sticker="off" 61 | _arg_version_sticker_verbose="off" 62 | _arg_skip_vnc="off" 63 | _arg_skip_novnc="off" 64 | _arg_debug="off" 65 | _arg_verbose="off" 66 | 67 | 68 | print_help() 69 | { 70 | printf '%s\n' "Container startup script" 71 | printf 'Usage: %s [-v|--version] [-h|--help] [-H|--help-usage] [--(no-)wait] [--(no-)skip-startup] [--(no-)tail-null] [--(no-)tail-vnc] [--(no-)version-sticker] [--(no-)version-sticker-verbose] [--(no-)skip-vnc] [--(no-)skip-novnc] [--(no-)debug] [--(no-)verbose] [--] [] ... [] ...\n' "$0" 72 | printf '\t%s\n' ": Optional command with optional arguments. It is executed during startup." 73 | printf '\t%s\n' "-v, --version: Prints version" 74 | printf '\t%s\n' "-h, --help: Prints help" 75 | printf '\t%s\n' "-H, --help-usage: Extended container usage help." 76 | printf '\t%s\n' "--wait, --no-wait: Default background execution mode (on by default)" 77 | printf '\t%s\n' "--skip-startup, --no-skip-startup: Default foreground execution mode (off by default)" 78 | printf '\t%s\n' "--tail-null, --no-tail-null: Alternative background execution mode (off by default)" 79 | printf '\t%s\n' "--tail-vnc, --no-tail-vnc: Alternative background execution mode (off by default)" 80 | printf '\t%s\n' "--version-sticker, --no-version-sticker: Alternative foreground execution mode (off by default)" 81 | printf '\t%s\n' "--version-sticker-verbose, --no-version-sticker-verbose: Alternative foreground execution mode (off by default)" 82 | printf '\t%s\n' "--skip-vnc, --no-skip-vnc: Startup process modifier (off by default)" 83 | printf '\t%s\n' "--skip-novnc, --no-skip-novnc: Startup process modifier (off by default)" 84 | printf '\t%s\n' "--debug, --no-debug: Startup process modifier (off by default)" 85 | printf '\t%s\n' "--verbose, --no-verbose: Startup process modifier (off by default)" 86 | printf '\n%s\n' "Use '-H' or '--help-usage' for extended container usage help. 87 | For more information visit https://github.com/accetto/ubuntu-vnc-xfce-g3" 88 | } 89 | 90 | 91 | parse_commandline() 92 | { 93 | _positionals_count=0 94 | while test $# -gt 0 95 | do 96 | _key="$1" 97 | if test "$_key" = '--' 98 | then 99 | shift 100 | test $# -gt 0 || break 101 | _positionals+=("$@") 102 | _positionals_count=$((_positionals_count + $#)) 103 | shift $(($# - 1)) 104 | _last_positional="$1" 105 | break 106 | fi 107 | case "$_key" in 108 | -v|--version) 109 | echo $(basename $0) v20.12.06 110 | exit 0 111 | ;; 112 | -v*) 113 | echo $(basename $0) v20.12.06 114 | exit 0 115 | ;; 116 | -h|--help) 117 | print_help 118 | exit 0 119 | ;; 120 | -h*) 121 | print_help 122 | exit 0 123 | ;; 124 | -H|--help-usage) 125 | print_usage 126 | exit 0 127 | ;; 128 | -H*) 129 | print_usage 130 | exit 0 131 | ;; 132 | --no-wait|--wait) 133 | _arg_wait="on" 134 | test "${1:0:5}" = "--no-" && _arg_wait="off" 135 | ;; 136 | --no-skip-startup|--skip-startup) 137 | _arg_skip_startup="on" 138 | test "${1:0:5}" = "--no-" && _arg_skip_startup="off" 139 | ;; 140 | --no-tail-null|--tail-null) 141 | _arg_tail_null="on" 142 | test "${1:0:5}" = "--no-" && _arg_tail_null="off" 143 | ;; 144 | --no-tail-vnc|--tail-vnc) 145 | _arg_tail_vnc="on" 146 | test "${1:0:5}" = "--no-" && _arg_tail_vnc="off" 147 | ;; 148 | --no-version-sticker|--version-sticker) 149 | _arg_version_sticker="on" 150 | test "${1:0:5}" = "--no-" && _arg_version_sticker="off" 151 | ;; 152 | --no-version-sticker-verbose|--version-sticker-verbose) 153 | _arg_version_sticker_verbose="on" 154 | test "${1:0:5}" = "--no-" && _arg_version_sticker_verbose="off" 155 | ;; 156 | --no-skip-vnc|--skip-vnc) 157 | _arg_skip_vnc="on" 158 | test "${1:0:5}" = "--no-" && _arg_skip_vnc="off" 159 | ;; 160 | --no-skip-novnc|--skip-novnc) 161 | _arg_skip_novnc="on" 162 | test "${1:0:5}" = "--no-" && _arg_skip_novnc="off" 163 | ;; 164 | --no-debug|--debug) 165 | _arg_debug="on" 166 | test "${1:0:5}" = "--no-" && _arg_debug="off" 167 | ;; 168 | --no-verbose|--verbose) 169 | _arg_verbose="on" 170 | test "${1:0:5}" = "--no-" && _arg_verbose="off" 171 | ;; 172 | *) 173 | _last_positional="$1" 174 | _positionals+=("$_last_positional") 175 | _positionals_count=$((_positionals_count + 1)) 176 | ;; 177 | esac 178 | shift 179 | done 180 | } 181 | 182 | 183 | assign_positional_args() 184 | { 185 | local _positional_name _shift_for=$1 186 | _positional_names="" 187 | _our_args=$((${#_positionals[@]} - 0)) 188 | for ((ii = 0; ii < _our_args; ii++)) 189 | do 190 | _positional_names="$_positional_names _arg_command[$((ii + 0))]" 191 | done 192 | 193 | shift "$_shift_for" 194 | for _positional_name in ${_positional_names} 195 | do 196 | test $# -gt 0 || break 197 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1 198 | shift 199 | done 200 | } 201 | 202 | parse_commandline "$@" 203 | assign_positional_args 1 "${_positionals[@]}" 204 | 205 | # OTHER STUFF GENERATED BY Argbash 206 | 207 | ### END OF CODE GENERATED BY Argbash (sortof) ### ]) 208 | -------------------------------------------------------------------------------- /docker/src/xfce-startup/set_user_permissions.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | #set -e # do not use 3 | #set -u # do not use 4 | 5 | main() { 6 | local verbose="" 7 | 8 | if [[ -n "${DEBUG}" ]] ; then 9 | echo "Current user: $(id -u):$(id -g)" 10 | verbose="-v" 11 | fi 12 | 13 | ### Fix file permissions 14 | for i in "$@" ; do 15 | 16 | if [[ -n "${verbose}" ]] ; then 17 | 18 | echo "Fixing permissions for: ${i}" 19 | fi 20 | 21 | ### set directory permissions 22 | ### recursively, but skipping dot-directories in $HOME 23 | find "$i" -type d -not -path "${HOME}/.*" -exec chmod ${verbose} 755 {} + 24 | 25 | ### set file permissions 26 | ### recursively, but skipping dot-files and dot-directories in $HOME 27 | find "$i" -type f -not -path "${HOME}/.*" -exec chmod ${verbose} 644 {} + 28 | 29 | ### specific file permissions 30 | ### recursively, but skipping dot-directories in $HOME 31 | find "$i"/ -type f -not -path "${HOME}/.*" -name '*.sh' -exec chmod ${verbose} 744 {} + 32 | find "$i"/ -type f -not -path "${HOME}/.*" -name '*.desktop' -exec chmod ${verbose} 744 {} + 33 | done 34 | 35 | ### startup script is special 36 | chmod 755 "${STARTUPDIR}"/startup.sh 37 | } 38 | 39 | main $@ 40 | -------------------------------------------------------------------------------- /docker/src/xfce-startup/startup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | #set -e ### do not use this 4 | 5 | declare _mydir=$(dirname $0) 6 | 7 | source "${_mydir}"/help.rc 8 | source "${_mydir}"/parser.rc 9 | source "${_mydir}"/user_generator.rc 10 | source "${_mydir}"/vnc_startup.rc 11 | 12 | cleanup () { 13 | local readonly last_pid=$! 14 | 15 | ### also forwarding of shutdown signal 16 | if [[ -n "${last_pid}" || -n "${_wait_pid}" ]] ; then 17 | 18 | if [[ "${last_pid}" != "${_wait_pid}" ]] ; then 19 | 20 | if [[ -n "${_verbose}" ]] ; then 21 | 22 | echo "Killing last background PID '${last_pid}'" 23 | fi 24 | 25 | kill -s SIGTERM "${last_pid}" 26 | fi 27 | 28 | ### kill the PID the container is waiting on 29 | if [[ -n "${_wait_pid}" ]] ; then 30 | 31 | if [[ -n "${_verbose}" ]] ; then 32 | 33 | echo "Killing blocking PID '${_wait_pid}'" 34 | fi 35 | 36 | ### ignore the errors if not alive any more 37 | kill -s SIGTERM "${_wait_pid}" > /dev/null 2>&1 38 | fi 39 | fi 40 | 41 | die "$1" 0 42 | } 43 | 44 | execute_command() { 45 | 46 | if [[ -n "$@" ]] ; then 47 | 48 | if [[ -n "${_verbose}" ]] ; then 49 | 50 | echo "Executing startup command: $@" 51 | fi 52 | 53 | ### use 'eval' not 'exec' 54 | ### note the single space before the command! 55 | eval " $@" 56 | 57 | if [[ $? -ne 0 ]] ; then 58 | 59 | cleanup 60 | fi 61 | fi 62 | } 63 | 64 | envv_override() { 65 | 66 | local envv_override_file="${HOME}"/.override/.override_envv.rc 67 | local tmp="" 68 | 69 | ### only if the file is not empty 70 | if [[ -s "${envv_override_file}" ]] ; then 71 | 72 | tmp=$( mktemp ) 73 | 74 | ### only lines that begin with 'export ' and contain '=' 75 | ( grep -E '^export\s[^=]+[=]{1}' "${envv_override_file}" 2>/dev/null 1>"${tmp}" ) 76 | 77 | if [[ "${_verbose}" == "1" ]] ; then 78 | 79 | echo "Sourcing from file '${envv_override_file}'" 80 | cat "${tmp}" 81 | echo "End of file '${envv_override_file}'" 82 | fi 83 | 84 | source "${tmp}" 85 | rm -f "${tmp}" 86 | fi 87 | } 88 | 89 | main() { 90 | 91 | ### option interdependencies 92 | if [[ "${_arg_verbose}" == "on" || "${_arg_debug}" == "on" ]] ; then 93 | 94 | _verbose=1 95 | fi 96 | 97 | if [[ "${_arg_skip_vnc}" == "on" ]] ; then 98 | 99 | _arg_skip_novnc="on" 100 | fi 101 | 102 | if [[ "${_verbose}" == "1" ]] ; then 103 | 104 | echo -e "\nContainer '$(hostname)' started @$(date -u +'%Y-%m-%d_%H-%M-%S')" 105 | fi 106 | 107 | ### option "--debug" 108 | if [[ "${_arg_debug}" == "on" ]] ; then 109 | 110 | echo "Script: $0" 111 | echo "\${HOME}=${HOME}" 112 | 113 | echo "ls -la /" ; ls -la / 114 | echo "ls -ls /etc/passwd /etc/group" ; ls -ls /etc/passwd /etc/group 115 | echo "ls -la /home" ; ls -la /home 116 | echo "ls -la ${HOME}" ; ls -la "${HOME}" 117 | echo "ls -la ." ; ls -la . 118 | fi 119 | 120 | ### override environment variables only if enabled 121 | if [[ "${FEATURES_OVERRIDING_ENVV}" == "1" ]] ; then 122 | 123 | envv_override 124 | fi 125 | 126 | ### create container user 127 | if [[ -s "${STARTUPDIR}"/.initial_sudo_password ]] ; then 128 | 129 | generate_container_user 130 | fi 131 | 132 | if [[ "$?" != "0" ]] ; then 133 | 134 | echo "ERROR: Unable to generate user '$(id -u):$(id -g)'." 135 | cleanup 136 | fi 137 | 138 | ### options '--version-sticker' and '--version-sticker-verbose' 139 | if [[ "${_arg_version_sticker}" == "on" || "${_arg_version_sticker_verbose}" == "on" ]] ; then 140 | 141 | ### this handles also '--skip-vnc' and '--skip-novnc' options 142 | start_vnc 143 | 144 | ### do not use '_verbose' which can be forced by '--debug' 145 | if [[ "${_arg_version_sticker_verbose}" == "off" ]] ; then 146 | 147 | ### print out default version sticker 148 | "${STARTUPDIR}"/version_sticker.sh 149 | cleanup 150 | 151 | else 152 | ### print out verbose version sticker 153 | ### be sure to use capital '-V' 154 | "${STARTUPDIR}"/version_sticker.sh -f -V 155 | cleanup 156 | fi 157 | fi 158 | 159 | ### options '--tail-vnc' and '--tail-null' 160 | if [[ "${_arg_tail_vnc}" == "on" || ${_arg_tail_null} == "on" ]] ; then 161 | 162 | ### this handles also '--skip-vnc' and '--skip-novnc' options 163 | start_vnc 164 | 165 | ### command array expands to all elements quoted as a whole 166 | execute_command "${_arg_command[*]}" 167 | 168 | ### option '--tail-vnc' and VNC has been started 169 | if [[ ${_arg_tail_vnc} == "on" && -n "${_wait_pid}" ]] ; then 170 | 171 | ### tail the VNC log infinitely 172 | echo "Tailing VNC log '${_vnc_log}'" 173 | tail -f "${_vnc_log}" 174 | cleanup 175 | 176 | else 177 | 178 | ### tail the null device infinitely 179 | if [[ -n $"{_verbose}" ]] ; then 180 | 181 | echo "Tailing '/dev/null'" 182 | fi 183 | 184 | tail -f /dev/null 185 | cleanup 186 | fi 187 | fi 188 | 189 | ### default background execution mode 190 | ### be sure to end all previous branches by calling 'cleanup' 191 | ### option '--wait' is purely because of the parser 192 | 193 | ### this handles also '--skip-vnc' and '--skip-novnc' options 194 | start_vnc 195 | 196 | ### command array expands to all elements quoted as a whole 197 | execute_command "${_arg_command[*]}" 198 | 199 | if [[ -n "${_wait_pid}" ]] ; then 200 | 201 | ### VNC has been started - wait on its PID 202 | wait ${_wait_pid} 203 | else 204 | 205 | ### VNC not started - go asleep infinitely 206 | sleep infinity 207 | fi 208 | } 209 | 210 | ### MAIN ENTRY POINT 211 | 212 | if [[ -z "${DEBUGGER}" ]] ; then 213 | 214 | trap cleanup SIGINT SIGTERM ERR 215 | : ${HOME?} ${STARTUPDIR?} 216 | fi 217 | 218 | declare _novnc_log="${STARTUPDIR}"/novnc.log 219 | declare _verbose="" 220 | declare _vnc_log="${STARTUPDIR}"/vnc.log 221 | declare _wait_pid="" 222 | 223 | ### option '--skip-startup' 224 | if [[ "${_arg_skip_startup}" == "on" ]] ; then 225 | 226 | ### command array expands to all elements quoted as a whole 227 | execute_command "${_arg_command[*]}" 228 | 229 | else 230 | 231 | main $@ 232 | 233 | fi 234 | 235 | cleanup 236 | -------------------------------------------------------------------------------- /docker/src/xfce-startup/user_generator.rc: -------------------------------------------------------------------------------- 1 | generate_container_user() { 2 | 3 | ### Adjusts the '/etc/passwd' and '/etc/group' files to cope with the randomly assigned IDs using 'docker run --user x:y'. 4 | ### Note that this code will be executed only once by the first start-up (see the if-condition and the end of the outer if-block). 5 | 6 | local user_id 7 | local group_id 8 | local headless_user_name 9 | local headless_group_name 10 | 11 | ### note that this block will be executed only once (see the end of the if-block) 12 | if [[ -w /etc/passwd ]] ; then 13 | 14 | user_id="$(id -u)" 15 | group_id="$(id -g)" 16 | headless_user_name="${HEADLESS_USER_NAME}" 17 | headless_group_name="${HEADLESS_USER_GROUP_NAME}" 18 | 19 | ### add the new group if the same GID does not exist yet 20 | if [[ "${group_id}" != "0" && "${group_id}" != "${HEADLESS_USER_GROUP_ID}" ]] ; then 21 | 22 | ### rename the existing 'headless_group_name' into 'g3builder' 23 | if [[ $( grep -c "${headless_group_name}:x:${HEADLESS_USER_GROUP_ID}:" /etc/group ) -ne 0 ]]; then 24 | 25 | cat /etc/group | sed -e "s/^${headless_group_name}:x:${HEADLESS_USER_GROUP_ID}:/g3builder:x:${HEADLESS_USER_GROUP_ID}:/" > /tmp/group 26 | 27 | cp /tmp/group /etc/ 28 | rm /tmp/group 29 | 30 | if [[ -n "${_verbose}" ]] ; then 31 | echo "Default user group '${headless_group_name}(${HEADLESS_USER_GROUP_ID})' renamed into 'g3builder(${HEADLESS_USER_GROUP_ID})' in '/etc/group'" 32 | fi 33 | fi 34 | 35 | ### add the current default user group ID as a new 'headless_group_name' if it does not exist yet 36 | if [[ $( grep -c -E ":x:${group_id}:$" /etc/group ) -eq 0 ]] ; then 37 | 38 | cat /etc/group > /tmp/group 39 | echo "${headless_group_name}:x:${group_id}:" >> /tmp/group 40 | 41 | cp /tmp/group /etc/ 42 | rm /tmp/group 43 | 44 | if [[ -n "${_verbose}" ]] ; then 45 | echo "Default user group '${headless_group_name}(${group_id})' added into '/etc/group'" 46 | fi 47 | fi 48 | fi 49 | 50 | ### user 'root (0)' is always created by default 51 | ### user 'headless_user_name' is created by Dockerfile 52 | if [[ "${user_id}" != "0" && "${user_id}" != "${HEADLESS_USER_ID}" ]] ; then 53 | 54 | ### rename the existing 'headless_user_name' into 'g3builder' 55 | if [[ $( grep -c "${headless_user_name}:x:${HEADLESS_USER_ID}:" /etc/passwd ) -ne 0 ]]; then 56 | 57 | cat /etc/passwd | sed -e "s/^${headless_user_name}:x:${HEADLESS_USER_ID}:${HEADLESS_USER_GROUP_ID}:Default:/g3builder:x:${HEADLESS_USER_ID}:${HEADLESS_USER_GROUP_ID}:G3Builder:/" > /tmp/passwd 58 | 59 | cp /tmp/passwd /etc/ 60 | rm /tmp/passwd 61 | 62 | if [[ -n "${_verbose}" ]] ; then 63 | echo "Default user '${headless_user_name}(${HEADLESS_USER_ID}:${HEADLESS_USER_GROUP_ID})' renamed into 'g3builder(${HEADLESS_USER_ID}:${HEADLESS_USER_GROUP_ID})' in '/etc/passwd'" 64 | fi 65 | fi 66 | 67 | ### add the current default user ID as a new 'headless_user_name' if it does not exist yet 68 | if [[ $( grep -c "${headless_user_name}:x:${user_id}:" /etc/passwd ) -eq 0 ]] ; then 69 | 70 | cat /etc/passwd > /tmp/passwd 71 | echo "${headless_user_name}:x:${user_id}:${group_id}:Default:${HOME}:/bin/bash" >> /tmp/passwd 72 | 73 | cp /tmp/passwd /etc/ 74 | rm /tmp/passwd 75 | 76 | if [[ -n "${_verbose}" ]] ; then 77 | echo "Default user '${headless_user_name}(${user_id}:${group_id})' added into '/etc/passwd'" 78 | fi 79 | 80 | ### update the environment variables 81 | export HEADLESS_USER_ID=${user_id} 82 | export HEADLESS_USER_GROUP_ID=${group_id} 83 | fi 84 | fi 85 | 86 | if [[ -s "${STARTUPDIR}"/.initial_sudo_password ]] ; then 87 | 88 | ### make the newly created user the owner of the following folders including their content 89 | cat "${STARTUPDIR}"/.initial_sudo_password | sudo -S chown -R "${user_id}:${group_id}" "${STARTUPDIR}" "${HOME}" 2>/dev/null 90 | 91 | ### set the file permissions of the following to the system default and 92 | ### note that this will also disable this user generator for the future runs (see the outer if-condition above) 93 | cat "${STARTUPDIR}"/.initial_sudo_password | sudo -S chmod 644 /etc/passwd /etc/group 2>/dev/null 94 | 95 | ### remove the file containing the initial sudo password 96 | ### be aware that the initial sudo password is still part of the Docker image (see the image history and ARG_SUDO_PW) 97 | ### however, you can change it afterwards inside the container 98 | cat "${STARTUPDIR}"/.initial_sudo_password | sudo -S echo -n "" > "${STARTUPDIR}"/.initial_sudo_password 99 | fi 100 | fi 101 | } 102 | -------------------------------------------------------------------------------- /docker/src/xfce-startup/version_of.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # cSpell:disable 4 | 5 | case "$1" in 6 | angular | angular-cli | angularcli | ng ) 7 | ### source example: Angular CLI: 8.3.2 8 | echo $(ng --version 2>/dev/null | grep -Po -m1 '(?<=Angular CLI:\s)[0-9.]+') 9 | ;; 10 | chromium | chromium-browser | chromiumbrowser ) 11 | ### source example: Chromium 76.0.3809.100 Built on Ubuntu , running on Ubuntu 18.04 12 | echo $(chromium-browser --version 2>/dev/null | grep -Po -m1 '(?<=Chromium\s)[0-9.]+') 13 | ;; 14 | code | vsc | vscode | visual-studio-code | visualstudiocode ) 15 | ### source example: 1.37.1 16 | echo $(code --version 2>/dev/null | grep -Po -m1 '^[0-9.]+$') 17 | ;; 18 | curl ) 19 | ### source example: curl 7.58.0 (x86_64-pc-linux-gnu) libcurl/7.58.0 OpenSSL/1.1.1 zlib/1.2.11 libidn2/2.0.4 libpsl/0.19.1 (+libidn2/2.0.4) nghttp2/1.30.0 librtmp/2.3 20 | echo $(curl --version 2>/dev/null | grep -Po -m1 '(?<=curl\s)[0-9.]+') 21 | ;; 22 | dconf-editor ) 23 | ### source example: dconf-editor 3.36.0 24 | echo $(dconf-editor --version 2>/dev/null | grep -Po -m1 '[0-9.]+$') 25 | ;; 26 | drawio | drawio-desktop ) 27 | ### source example: 12.2.2 28 | echo $(drawio --no-sandbox --version 2>/dev/null | grep -Po -m1 '^[0-9.]+$') 29 | ;; 30 | firefox ) 31 | ### source example: Mozilla Firefox 68.0.2 32 | echo $(firefox -v 2>/dev/null | grep -Po -m1 '(?<=Firefox\s)[0-9a-zA-Z.-]+') 33 | ;; 34 | gimp ) 35 | ### source example: GNU Image Manipulation Program version 2.8.22 36 | echo $(gimp --version 2>/dev/null | grep -Po -m1 '[0-9.]+$') 37 | ;; 38 | gdebi ) 39 | ### source example: 0.9.5.7+nmu2 40 | echo $(gdebi --version 2>/dev/null | grep -Po -m1 '^[0-9.]+') 41 | ;; 42 | git ) 43 | ### source example: git version 2.17.1 44 | echo $(git --version 2>/dev/null | grep -Po -m1 '[0-9.]+$') 45 | ;; 46 | heroku | heroku-cli | herokucli ) 47 | ### source sample: heroku/7.29.0 linux-x64 node-v11.14.0 48 | echo $(heroku --version 2>/dev/null | grep -Po -m1 '(?<=heroku/)[0-9.]+') 49 | ;; 50 | inkscape ) 51 | ### Inkscape requires display! 52 | ### source sample: Inkscape 0.92.3 (2405546, 2018-03-11) 53 | echo $(inkscape --version 2>/dev/null | grep -Po -m1 '(?<=Inkscape\s)[0-9.]+') 54 | ;; 55 | jq ) 56 | ### source sample: jq-1.5-1-a5b5cbe 57 | echo $(jq --version 2>/dev/null | grep -Po -m1 '(?<=jq\-)[0-9.]+') 58 | ;; 59 | mousepad ) 60 | ### Mousepad requires display! 61 | ### source example: Mousepad 0.4.0 62 | echo $(mousepad --version 2>/dev/null | grep -Po -m1 '(?<=Mousepad\s)[0-9.]+') 63 | ;; 64 | nano ) 65 | ### source example: GNU nano, version 4.8 66 | echo $(nano --version 2>/dev/null | grep -Po -m1 '(?<=version\s)[0-9.]+') 67 | ;; 68 | nodejs | node-js | node ) 69 | ### source example: v10.16.3 70 | echo $(node --version 2>/dev/null | grep -Po -m1 '[0-9.]+$') 71 | ;; 72 | novnc | no-vnc ) 73 | ### source example: 1.1.0 74 | #echo $(cat "${NOVNC_HOME}"/VERSION 2>/dev/null | grep -Po '^[0-9.]+$') 75 | echo $(cat "${NOVNC_HOME}"/package.json 2>/dev/null | grep -Po -m1 '(?<=\s"version":\s")[0-9.]+') 76 | ;; 77 | npm ) 78 | ### source example: 6.9.0 79 | echo $(npm --version 2>/dev/null | grep -Po -m1 '[0-9.]+$') 80 | ;; 81 | psql | postgresql | postgre-sql | postgre ) 82 | ### source example: psql (PostgreSQL) 10.10 (Ubuntu 10.10-0ubuntu0.18.04.1) 83 | echo $(psql --version 2>/dev/null | grep -Po -m1 '(?<=psql \(PostgreSQL\)\s)[0-9.]+') 84 | ;; 85 | python3 ) 86 | ## source example: Python 3.8.5 87 | echo $(python3 --version 2>/dev/null | grep -Po -m1 '[0-9.]+$') 88 | ;; 89 | ristretto ) 90 | ### source example: ristretto 0.8.2 91 | echo $(ristretto --version 2>/dev/null | grep -Po -m1 '[0-9.]+$') 92 | ;; 93 | tigervnc | tiger-vnc | vncserver | vnc-server | vnc ) 94 | ### till TigerVNC 1.10.1 95 | ### source example: Xvnc TigerVNC 1.9.0 - built Jul 16 2018 14:18:04 96 | # echo $(vncserver -version 2>/dev/null | grep -Po '(?<=Xvnc TigerVNC\s)[0-9.]+') 97 | ### since TigerVNC 1.11.0 (it's coming out on the stderr stream!) 98 | ### source example: Xvnc TigerVNC 1.11.0 - built Sep 8 2020 12:27:03 99 | echo $(Xvnc -version 2>&1 | grep -Po -m1 '(?<=Xvnc TigerVNC\s)[0-9.]+') 100 | ;; 101 | tsc | typescript | type-script ) 102 | ### source example: Version 3.6.2 103 | echo $(tsc --version 2>/dev/null | grep -Po -m1 '[0-9.]+$') 104 | ;; 105 | ubuntu | xubuntu ) 106 | ### source example: Ubuntu 18.04.3 LTS 107 | echo $(cat /etc/os-release 2>/dev/null | grep -Po -m1 '(?<=VERSION\=")[0-9.]+') 108 | ;; 109 | vim ) 110 | ### source example: VIM - Vi IMproved 8.0 (2016 Sep 12, compiled Jun 06 2019 17:31:41) 111 | echo $(vim --version 2>/dev/null | grep -Po -m1 '(?<=VIM - Vi IMproved\s)[0-9.]+') 112 | ;; 113 | websockify ) 114 | ### source example: 0.8.0 115 | echo $(cat "${NOVNC_HOME}"/utils/websockify/CHANGES.txt 2>/dev/null | grep -Po -m1 '^[0-9.]+') 116 | ;; 117 | xfce4-screenshooter | screenshooter | screenshot ) 118 | ### source example: xfce4-screenshooter 1.8.2 119 | echo $(xfce4-screenshooter --version 2>/dev/null | grep -Po -m1 '[0-9.]+$') 120 | ;; 121 | esac 122 | -------------------------------------------------------------------------------- /docker/src/xfce-startup/version_sticker.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ### resolve also symlinks 4 | _current_dir="$(dirname "$(readlink -f "$0")")" 5 | 6 | ubuntu=$("${_current_dir}/version_of.sh" ubuntu) 7 | chromium=$("${STARTUPDIR}/version_of.sh" chromium) 8 | firefox=$("${STARTUPDIR}/version_of.sh" firefox) 9 | 10 | main() { 11 | local key 12 | 13 | if [[ $# -gt 0 ]] ; then 14 | 15 | while [[ $# -gt 0 ]] ; do 16 | 17 | key="$1" 18 | 19 | if [[ "${key}" = '--' ]] ; then 20 | 21 | shift 22 | fi 23 | 24 | case "${key}" in 25 | 26 | -h ) 27 | echo "Usage: version_sticker [-h] [-v] [-V] [-f]" 28 | echo "-h help" 29 | echo "-v short version sticker" 30 | echo "-V verbose version sticker" 31 | echo "-f features" 32 | ;; 33 | 34 | -f ) 35 | env | grep "FEATURES_" | sort 36 | ;; 37 | 38 | -v ) 39 | if [[ -n "${chromium}" ]] ; then echo "Chromium ${chromium}" ; fi 40 | if [[ -n "${firefox}" ]] ; then echo "Firefox ${firefox}" ; fi 41 | echo "Ubuntu ${ubuntu}" 42 | ;; 43 | 44 | -V ) 45 | if [[ -n "${chromium}" ]] ; then echo "Chromium ${chromium}" ; fi 46 | 47 | # version=$("${_current_dir}/version_of.sh" dconf-editor) 48 | # if [[ -n "${version}" ]] ; then echo "dconf-editor ${version}" ; fi 49 | 50 | if [[ -n "${firefox}" ]] ; then echo "Firefox ${firefox}" ; fi 51 | 52 | version=$("${_current_dir}/version_of.sh" jq) 53 | if [[ -n "${version}" ]] ; then echo "jq ${version}" ; fi 54 | 55 | version=$("${_current_dir}/version_of.sh" mousepad) 56 | if [[ -n "${version}" ]] ; then echo "Mousepad ${version}" ; fi 57 | 58 | version=$("${_current_dir}/version_of.sh" nano) 59 | if [[ -n "${version}" ]] ; then echo "nano ${version}" ; fi 60 | 61 | version=$("${_current_dir}/version_of.sh" novnc) 62 | if [[ -n "${version}" ]] ; then echo "noVNC ${version}" ; fi 63 | 64 | version=$("${_current_dir}/version_of.sh" python3) 65 | if [[ -n "${version}" ]] ; then echo "Python ${version}" ; fi 66 | 67 | version=$("${_current_dir}/version_of.sh" ristretto) 68 | if [[ -n "${version}" ]] ; then echo "Ristretto ${version}" ; fi 69 | 70 | version=$("${_current_dir}/version_of.sh" screenshooter) 71 | if [[ -n "${version}" ]] ; then echo "Screenshooter ${version}" ; fi 72 | 73 | version=$("${_current_dir}/version_of.sh" tigervnc) 74 | if [[ -n "${version}" ]] ; then echo "TigerVNC ${version}" ; fi 75 | 76 | echo "Ubuntu ${ubuntu}" 77 | 78 | version=$("${_current_dir}/version_of.sh" websockify) 79 | if [[ -n "${version}" ]] ; then echo "websockify ${version}" ; fi 80 | ;; 81 | esac 82 | shift 83 | done 84 | else 85 | sticker="ubuntu${ubuntu}" 86 | 87 | if [[ -n "${chromium}" ]] ; then 88 | 89 | sticker="${sticker}-chromium${chromium}" 90 | 91 | elif [[ -n "${firefox}" ]]; then 92 | 93 | sticker="${sticker}-firefox${firefox}" 94 | fi 95 | 96 | echo "${sticker}" 97 | fi 98 | } 99 | 100 | main $@ 101 | -------------------------------------------------------------------------------- /docker/src/xfce-startup/vnc_startup.rc: -------------------------------------------------------------------------------- 1 | start_vnc () { 2 | local vnc_ip 3 | local passwd_path 4 | local xinit_pid 5 | 6 | ### option '--skip-vnc' 7 | if [[ "${_arg_skip_vnc}" == "on" ]] ; then 8 | 9 | if [[ -n "${_verbose}" ]] ; then 10 | 11 | echo "INFO: VNC/noVNC startup skipped as requested." 12 | fi 13 | 14 | return 0 15 | fi 16 | 17 | if [[ -z "$(which vncserver)" ]] ; then 18 | 19 | if [[ -n "${_verbose}" ]] ; then 20 | echo "WARNING: No 'vncserver' is available." 21 | fi 22 | 23 | return 0 24 | fi 25 | 26 | ### VNC requirements 27 | ### VNC password not enforced any more, so it can be set to an empty string by 'docker run -e VNC_PW=""'. 28 | ### If you still want to enforce it, bring the following line back: 29 | ### || [[ -z "${VNC_PW}" ]] \ 30 | if [[ -z "${DISPLAY}" \ 31 | || -z "${VNC_PORT}" \ 32 | || -z "${VNC_COL_DEPTH}" \ 33 | || -z "${VNC_RESOLUTION}" ]] ; then 34 | 35 | # cleanup "ERROR: Not all required environment variables are set: DISPLAY, VNC_PORT, VNC_PW, VNC_COL_DEPTH, VNC_RESOLUTION" 36 | cleanup "ERROR: Not all required environment variables are set: DISPLAY, VNC_PORT, VNC_COL_DEPTH, VNC_RESOLUTION" 37 | fi 38 | 39 | passwd_path="${HOME}"/.vnc/passwd 40 | 41 | if [[ ! -d "${HOME}"/.vnc ]] ; then 42 | 43 | mkdir "${HOME}"/.vnc 44 | fi 45 | 46 | if [[ "${VNC_VIEW_ONLY,,}" == "true" ]] ; then 47 | 48 | if [[ -n "${_verbose}" ]] ; then 49 | 50 | echo "Starting VNC server in view-only mode" 51 | fi 52 | 53 | ### create random pw to prevent access 54 | echo $(head /dev/urandom | tr -dc A-Za-z0-9 | head -c 20) | vncpasswd -f > "${passwd_path}" 55 | fi 56 | 57 | echo "${VNC_PW}" | vncpasswd -f > "${passwd_path}" 58 | chmod 600 "${passwd_path}" 59 | 60 | ### create VNC configuration file 61 | echo " 62 | rfbport=${VNC_PORT} 63 | depth=${VNC_COL_DEPTH} 64 | geometry=${VNC_RESOLUTION} 65 | " > "${HOME}"/.vnc/config 66 | 67 | ### get container IP address 68 | vnc_ip=$(hostname -i) 69 | 70 | ### removing old VNC locks to be a re-attachable container 71 | xinit_pid="$(pidof xinit)" 72 | 73 | if [[ -n "${xinit_pid}" ]] ; then 74 | 75 | if [[ -n "${_verbose}" ]] ; then 76 | echo "Killing xinit PID ${xinit_pid}" 77 | fi 78 | 79 | ### ignore the errors if not alive any more 80 | kill "${xinit_pid}" > /dev/null 2>&1 81 | fi 82 | if [[ -n $(compgen -G /tmp/.X*-lock) || -n $(compgen -G /tmp/.X11-unix) ]] ; then 83 | 84 | if [[ -n "${_verbose}" ]] ; then 85 | 86 | echo "Removing old VNC locks to be a re-attachable container" 87 | fi 88 | 89 | rm -rfv /tmp/.X*-lock /tmp/.X11-unix &> "${_vnc_log}" 90 | fi 91 | 92 | if [[ -n "${_verbose}" ]] ; then 93 | 94 | echo "Starting VNC" 95 | echo "vncserver ${DISPLAY} &> ${_vnc_log}" 96 | fi 97 | 98 | ### VNC startup (in the background) 99 | vncserver "${DISPLAY}" &> "${_vnc_log}" & 100 | 101 | ### container will wait on this VNC server PID 102 | _wait_pid=$! 103 | 104 | if [[ -n "${_verbose}" ]] ; then 105 | 106 | echo "VNC server started on display '${DISPLAY}' and TCP port '${VNC_PORT}'" 107 | echo "Connect via VNC viewer with ${vnc_ip}:${VNC_PORT}" 108 | fi 109 | 110 | ### option '--skip-novnc' 111 | if [[ "${_arg_skip_novnc}" == "off" ]] ; then 112 | 113 | ### noVNC is not necessarily installed 114 | if [[ -n "${NOVNC_HOME}" || -d "${NOVNC_HOME}/utils/websockify" ]] ; then 115 | 116 | ### noVNC requirements 117 | if [[ -n "${NOVNC_PORT}" ]] ; then 118 | 119 | if [[ -n "${_verbose}" ]] ; then 120 | 121 | echo "Starting noVNC" 122 | echo "${NOVNC_HOME}/utils/novnc_proxy --vnc localhost:${VNC_PORT} --listen ${NOVNC_PORT} ${NOVNC_HEARTBEAT:+--heartbeat ${NOVNC_HEARTBEAT}} &> ${_novnc_log}" 123 | fi 124 | 125 | ### noVNC startup (in the background) 126 | "${NOVNC_HOME}"/utils/novnc_proxy \ 127 | --vnc localhost:${VNC_PORT} \ 128 | --listen ${NOVNC_PORT} \ 129 | ${NOVNC_HEARTBEAT:+--heartbeat ${NOVNC_HEARTBEAT}} \ 130 | &> "${_novnc_log}" & 131 | 132 | if [[ -n "${_verbose}" ]] ; then 133 | 134 | echo "noVNC started on TCP port '${NOVNC_PORT}' ${NOVNC_HEARTBEAT:+with heartbeat ${NOVNC_HEARTBEAT} seconds}" 135 | echo "Connect via web browser" 136 | fi 137 | else 138 | cleanup "ERROR: Environment variable 'NOVNC_PORT' is not set." 139 | fi 140 | else 141 | if [[ -n "${_verbose}" ]] ; then 142 | 143 | echo "WARNING: noVNC is not available." 144 | fi 145 | fi 146 | else 147 | if [[ -n "${_verbose}" ]] ; then 148 | 149 | echo "INFO: noVNC startup skipped as requested." 150 | fi 151 | fi 152 | } 153 | -------------------------------------------------------------------------------- /docker/xfce-chromium/README-dockerhub.md: -------------------------------------------------------------------------------- 1 | # Headless Ubuntu/Xfce container with VNC/noVNC and Chromium Browser 2 | 3 | ## accetto/ubuntu-vnc-xfce-chromium-g3 4 | 5 | [User Guide][this-user-guide] - [GitHub][this-github] - [Dockerfile][this-dockerfile] - [Readme][this-readme-full] - [Changelog][this-changelog] 6 | 7 | 8 | ![badge-github-release][badge-github-release]` ` 9 | ![badge-docker-pulls][badge-docker-pulls]` ` 10 | ![badge-docker-stars][badge-docker-stars] 11 | 12 | *** 13 | 14 | This Docker Hub repository contains Docker images for headless working. 15 | 16 | The images are based on [Ubuntu 24.04, 22.04 and 20.04 LTS][docker-ubuntu] and include [Xfce][xfce] desktop, [TigerVNC][tigervnc] server and [noVNC][novnc] client. 17 | The popular web browser [Chromium][chromium] is also included. 18 | 19 | This [User guide][this-user-guide] describes the images and how to use them. 20 | 21 | The related [GitHub project][this-github] contains image generators that image users generally don’t need, unless they want to build the images themselves. 22 | 23 | ### Tags 24 | 25 | The following image tags are regularly built and published on Docker Hub: 26 | 27 | 28 | 29 | - `latest` (also as `24.04`) based on `Ubuntu 24.04 LTS` 30 | 31 | ![badge_latest_created][badge_latest_created]` ` 32 | [![badge_latest_version-sticker][badge_latest_version-sticker]][link_latest_version-sticker-verbose] 33 | 34 | - `22.04` based on `Ubuntu 22.04 LTS` 35 | 36 | ![badge_22-04_created][badge_22-04_created]` ` 37 | [![badge_22-04_version-sticker][badge_22-04_version-sticker]][link_22-04_version-sticker-verbose] 38 | 39 | - `20.04` based on `Ubuntu 20.04 LTS` 40 | 41 | ![badge_20-04_created][badge_20-04_created]` ` 42 | [![badge_20-04_version-sticker][badge_20-04_version-sticker]][link_20-04_version-sticker-verbose] 43 | 44 | 45 | 46 | **Hint:** Clicking the version sticker badge reveals more information about the particular build. 47 | 48 | ### Features 49 | 50 | The main features and components of the images in the default configuration are: 51 | 52 | - light-weight [Xfce][xfce] desktop environment (Ubuntu distribution) 53 | - [sudo][sudo] support 54 | - current version of JSON processor [jq][jq] 55 | - current version of high-performance [TigerVNC][tigervnc] server and client 56 | - current version of [noVNC][novnc] HTML5 clients (full and lite) (TCP port **6901**) 57 | - popular text editor [nano][nano] (Ubuntu distribution) 58 | - lite but advanced graphical editor [mousepad][mousepad] (Ubuntu distribution) 59 | - current version of [tini][tini] as the entry-point initial process (PID 1) 60 | - support for overriding environment variables, VNC parameters, user and group (see [User guide][this-user-guide-using-containers]) 61 | - support of **version sticker** (see [User guide][this-user-guide-version-sticker]) 62 | - current version of [Chromium Browser][chromium] open-source web browser (from `Ubuntu 18.04 LTS` distribution) 63 | 64 | The following **TCP** ports are exposed by default: 65 | 66 | - **5901** for access over **VNC** (using VNC viewer) 67 | - **6901** for access over [noVNC][novnc] (using web browser) 68 | 69 | ![container-screenshot][this-screenshot-container] 70 | 71 | ### Remarks 72 | 73 | There is also a similar sibling image [accetto/debian-vnc-xfce-chromium-g3][accetto-dockerhub-debian-vnc-xfce-chromium-g3] based on [Debian][docker-debian]. 74 | 75 | This is the **third generation** (G3) of my headless images. 76 | The **second generation** (G2) contains the GitHub repository [accetto/xubuntu-vnc-novnc][accetto-github-xubuntu-vnc-novnc]. 77 | The **first generation** (G1) contains the GitHub repository [accetto/ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce]. 78 | 79 | The images contain the current Chromium Browser from the `Ubuntu 18.04 LTS` distribution. 80 | This is because the versions for `Ubuntu 24.04, 22.04 and 20.04 LTS` depend on `snap`, which is currently not supported in Docker containers. 81 | 82 | The [Chromium Browser][chromium] in these images runs in the `--no-sandbox` mode. 83 | You should be aware of the implications. 84 | The images are intended for testing and development. 85 | 86 | ### Getting help 87 | 88 | If you've found a problem or you just have a question, please check the [User guide][this-user-guide], [Issues][this-issues] and [Wiki][this-wiki] first. 89 | Please do not overlook the closed issues. 90 | 91 | If you do not find a solution, you can file a new issue. 92 | The better you describe the problem, the bigger the chance it'll be solved soon. 93 | 94 | If you have a question or an idea and you don't want to open an issue, you can also use the [Discussions][this-discussions]. 95 | 96 | *** 97 | 98 | [this-user-guide]: https://accetto.github.io/user-guide-g3/ 99 | 100 | [this-user-guide-version-sticker]: https://accetto.github.io/user-guide-g3/version-sticker/ 101 | 102 | [this-user-guide-using-containers]: https://accetto.github.io/user-guide-g3/using-containers/ 103 | 104 | [this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/CHANGELOG.md 105 | 106 | [this-discussions]: https://github.com/accetto/ubuntu-vnc-xfce-g3/discussions 107 | 108 | [this-github]: https://github.com/accetto/ubuntu-vnc-xfce-g3/ 109 | 110 | [this-issues]: https://github.com/accetto/ubuntu-vnc-xfce-g3/issues 111 | 112 | [this-readme-full]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/xfce-chromium/README.md 113 | 114 | [this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki 115 | 116 | [this-dockerfile]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/Dockerfile.xfce.24-04 117 | 118 | [this-screenshot-container]: https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/master/docker/doc/images/animation-ubuntu-vnc-xfce-chromium-g3.gif 119 | 120 | [accetto-dockerhub-debian-vnc-xfce-chromium-g3]: https://hub.docker.com/r/accetto/debian-vnc-xfce-chromium-g3 121 | 122 | [accetto-github-xubuntu-vnc-novnc]: https://github.com/accetto/xubuntu-vnc-novnc/ 123 | 124 | [accetto-github-ubuntu-vnc-xfce]: https://github.com/accetto/ubuntu-vnc-xfce 125 | 126 | [docker-ubuntu]: https://hub.docker.com/_/ubuntu/ 127 | [docker-debian]: https://hub.docker.com/_/debian/ 128 | 129 | [chromium]: https://www.chromium.org/Home 130 | [jq]: https://stedolan.github.io/jq/ 131 | [mousepad]: https://github.com/codebrainz/mousepad 132 | [nano]: https://www.nano-editor.org/ 133 | [novnc]: https://github.com/kanaka/noVNC 134 | [sudo]: https://www.sudo.ws/ 135 | [tigervnc]: http://tigervnc.org 136 | [tini]: https://github.com/krallin/tini 137 | [xfce]: http://www.xfce.org 138 | 139 | [badge-github-release]: https://img.shields.io/github/v/release/accetto/ubuntu-vnc-xfce-g3 140 | 141 | [badge-docker-pulls]: https://img.shields.io/docker/pulls/accetto/ubuntu-vnc-xfce-chromium-g3 142 | 143 | [badge-docker-stars]: https://img.shields.io/docker/stars/accetto/ubuntu-vnc-xfce-chromium-g3 144 | 145 | 146 | -------------------------------------------------------------------------------- /docker/xfce-chromium/README.md: -------------------------------------------------------------------------------- 1 | # Headless Ubuntu/Xfce container with VNC/noVNC and Chromium Browser 2 | 3 | ## accetto/ubuntu-vnc-xfce-chromium-g3 4 | 5 | [User Guide][this-user-guide] - [Docker Hub][this-docker] - [Dockerfile][this-dockerfile] - [Readme][this-readme] - [Changelog][this-changelog] 6 | 7 | *** 8 | 9 | This GitHub project folder contains resources used by building Ubuntu images available on Docker Hub in the repository [accetto/ubuntu-vnc-xfce-chromium-g3][this-docker]. 10 | 11 | This [User guide][this-user-guide] describes the images and how to use them. 12 | 13 | ### Building images 14 | 15 | ```shell 16 | ### PWD = project root 17 | ### prepare and source the 'secrets.rc' file first (see 'example-secrets.rc') 18 | 19 | ### examples of building and publishing the individual images 20 | ./builder.sh latest-chromium all 21 | 22 | ### just building the image, skipping the publishing and the version sticker update 23 | ./builder.sh latest-chromium build 24 | 25 | ### examples of building and publishing the images as a group 26 | ./ci-builder.sh all group latest-chromium 27 | ``` 28 | 29 | Refer to the main [README][this-readme] file for more information about the building subject. 30 | 31 | ### Remarks 32 | 33 | There is also a sibling project [accetto/debian-vnc-xfce-g3][accetto-github-debian-vnc-xfce-g3] containing similar images based on [Debian][docker-debian]. 34 | 35 | This is the **third generation** (G3) of my headless images. 36 | The **second generation** (G2) contains the GitHub repository [accetto/xubuntu-vnc-novnc][accetto-github-xubuntu-vnc-novnc]. 37 | The **first generation** (G1) contains the GitHub repository [accetto/ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce]. 38 | 39 | The images contain the current Chromium Browser from the `Ubuntu 18.04 LTS` distribution. 40 | This is because the versions for `Ubuntu 24.04, 22.04 and 20.04 LTS` depend on `snap`, which is currently not supported in Docker containers. 41 | 42 | The [Chromium Browser][chromium] in these images runs in the `--no-sandbox` mode. 43 | You should be aware of the implications. 44 | The images are intended for testing and development. 45 | 46 | ### Getting help 47 | 48 | If you've found a problem or you just have a question, please check the [User guide][this-user-guide], [Issues][this-issues] and [Wiki][this-wiki] first. 49 | Please do not overlook the closed issues. 50 | 51 | If you do not find a solution, you can file a new issue. 52 | The better you describe the problem, the bigger the chance it'll be solved soon. 53 | 54 | If you have a question or an idea and you don't want to open an issue, you can also use the [Discussions][this-discussions]. 55 | 56 | ### Diagrams 57 | 58 | Diagram of the multi-staged Dockerfile used for building multiple images. 59 | 60 | The actual content of a particular image build is controlled by the *feature variables*. 61 | 62 | ![Dockerfile.xfce stages][this-diagram-dockerfile-stages] 63 | 64 | *** 65 | 66 | [this-user-guide]: https://accetto.github.io/user-guide-g3/ 67 | 68 | [this-readme]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/README.md 69 | 70 | [this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/CHANGELOG.md 71 | 72 | [this-discussions]: https://github.com/accetto/ubuntu-vnc-xfce-g3/discussions 73 | 74 | [this-issues]: https://github.com/accetto/ubuntu-vnc-xfce-g3/issues 75 | 76 | [this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki 77 | 78 | [this-docker]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-chromium-g3/ 79 | 80 | [this-dockerfile]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/Dockerfile.xfce.24-04 81 | 82 | [this-diagram-dockerfile-stages]: https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/master/docker/doc/images/Dockerfile.xfce.png 83 | 84 | [accetto-github-debian-vnc-xfce-g3]: https://github.com/accetto/debian-vnc-xfce-g3 85 | 86 | [accetto-github-xubuntu-vnc-novnc]: https://github.com/accetto/xubuntu-vnc-novnc/ 87 | 88 | [accetto-github-ubuntu-vnc-xfce]: https://github.com/accetto/ubuntu-vnc-xfce 89 | 90 | [docker-debian]: https://hub.docker.com/_/debian/ 91 | 92 | [chromium]: https://www.chromium.org/Home 93 | -------------------------------------------------------------------------------- /docker/xfce-chromium/readme-append.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | [badge_latest_created]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@created.json 7 | 8 | [badge_latest_version-sticker]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@version-sticker.json 9 | 10 | [link_latest_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@version-sticker-verbose.txt 11 | 12 | 13 | 14 | [badge_22-04_created]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@22.04@created.json 15 | 16 | [badge_22-04_version-sticker]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@22.04@version-sticker.json 17 | 18 | [link_22-04_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@22.04@version-sticker-verbose.txt 19 | 20 | 21 | 22 | [badge_20-04_created]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@20.04@created.json 23 | 24 | [badge_20-04_version-sticker]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@20.04@version-sticker.json 25 | 26 | [link_20-04_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@20.04@version-sticker-verbose.txt 27 | -------------------------------------------------------------------------------- /docker/xfce-chromium/src/home/Desktop/chromium-browser.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Name=Chromium Web Browser 4 | Name[ast]=Restolador web Chromium 5 | Name[bg]=Уеб четец Chromium 6 | Name[bn]=ক্রোমিয়াম ওয়েব ব্রাউজার 7 | Name[bs]=Chromium web preglednik 8 | Name[ca]=Navegador web Chromium 9 | Name[ca@valencia]=Navegador web Chromium 10 | Name[da]=Chromium netbrowser 11 | Name[de]=Chromium-Webbrowser 12 | Name[en_AU]=Chromium Web Browser 13 | Name[eo]=Kromiumo retfoliumilo 14 | Name[es]=Navegador web Chromium 15 | Name[et]=Chromiumi veebibrauser 16 | Name[eu]=Chromium web-nabigatzailea 17 | Name[fi]=Chromium-selain 18 | Name[fr]=Navigateur Web Chromium 19 | Name[gl]=Navegador web Chromium 20 | Name[he]=דפדפן האינטרנט כרומיום 21 | Name[hr]=Chromium web preglednik 22 | Name[hu]=Chromium webböngésző 23 | Name[hy]=Chromium ոստայն զննարկիչ 24 | Name[ia]=Navigator del web Chromium 25 | Name[id]=Peramban Web Chromium 26 | Name[it]=Browser web Chromium 27 | Name[ja]=Chromium ウェブ・ブラウザ 28 | Name[ka]=ვებ ბრაუზერი Chromium 29 | Name[ko]=Chromium 웹 브라우저 30 | Name[kw]=Peurel wias Chromium 31 | Name[ms]=Pelayar Web Chromium 32 | Name[nb]=Chromium nettleser 33 | Name[nl]=Chromium webbrowser 34 | Name[pt_BR]=Navegador de Internet Chromium 35 | Name[ro]=Navigator Internet Chromium 36 | Name[ru]=Веб-браузер Chromium 37 | Name[sl]=Chromium spletni brskalnik 38 | Name[sv]=Webbläsaren Chromium 39 | Name[ug]=Chromium توركۆرگۈ 40 | Name[vi]=Trình duyệt Web Chromium 41 | Name[zh_CN]=Chromium 网页浏览器 42 | Name[zh_HK]=Chromium 網頁瀏覽器 43 | Name[zh_TW]=Chromium 網頁瀏覽器 44 | GenericName=Web Browser 45 | GenericName[ar]=متصفح الشبكة 46 | GenericName[ast]=Restolador web 47 | GenericName[bg]=Уеб браузър 48 | GenericName[bn]=ওয়েব ব্রাউজার 49 | GenericName[bs]=Web preglednik 50 | GenericName[ca]=Navegador web 51 | GenericName[ca@valencia]=Navegador web 52 | GenericName[cs]=WWW prohlížeč 53 | GenericName[da]=Browser 54 | GenericName[de]=Web-Browser 55 | GenericName[el]=Περιηγητής ιστού 56 | GenericName[en_AU]=Web Browser 57 | GenericName[en_GB]=Web Browser 58 | GenericName[eo]=Retfoliumilo 59 | GenericName[es]=Navegador web 60 | GenericName[et]=Veebibrauser 61 | GenericName[eu]=Web-nabigatzailea 62 | GenericName[fi]=WWW-selain 63 | GenericName[fil]=Web Browser 64 | GenericName[fr]=Navigateur Web 65 | GenericName[gl]=Navegador web 66 | GenericName[gu]=વેબ બ્રાઉઝર 67 | GenericName[he]=דפדפן אינטרנט 68 | GenericName[hi]=वेब ब्राउज़र 69 | GenericName[hr]=Web preglednik 70 | GenericName[hu]=Webböngésző 71 | GenericName[hy]=Ոստայն զննարկիչ 72 | GenericName[ia]=Navigator del Web 73 | GenericName[id]=Peramban Web 74 | GenericName[it]=Browser web 75 | GenericName[ja]=ウェブ・ブラウザ 76 | GenericName[ka]=ვებ ბრაუზერი 77 | GenericName[kn]=ಜಾಲ ವೀಕ್ಷಕ 78 | GenericName[ko]=웹 브라우저 79 | GenericName[kw]=Peurel wias 80 | GenericName[lt]=Žiniatinklio naršyklė 81 | GenericName[lv]=Tīmekļa pārlūks 82 | GenericName[ml]=വെബ് ബ്രൌസര്‍ 83 | GenericName[mr]=वेब ब्राऊजर 84 | GenericName[ms]=Pelayar Web 85 | GenericName[nb]=Nettleser 86 | GenericName[nl]=Webbrowser 87 | GenericName[or]=ଓ୍ବେବ ବ୍ରାଉଜର 88 | GenericName[pl]=Przeglądarka WWW 89 | GenericName[pt]=Navegador Web 90 | GenericName[pt_BR]=Navegador web 91 | GenericName[ro]=Navigator de Internet 92 | GenericName[ru]=Веб-браузер 93 | GenericName[sk]=WWW prehliadač 94 | GenericName[sl]=Spletni brskalnik 95 | GenericName[sr]=Интернет прегледник 96 | GenericName[sv]=Webbläsare 97 | GenericName[ta]=இணைய உலாவி 98 | GenericName[te]=మహాతల అన్వేషి 99 | GenericName[th]=เว็บเบราว์เซอร์ 100 | GenericName[tr]=Web Tarayıcı 101 | GenericName[ug]=توركۆرگۈ 102 | GenericName[uk]=Навігатор Тенет 103 | GenericName[vi]=Bộ duyệt Web 104 | GenericName[zh_CN]=网页浏览器 105 | GenericName[zh_HK]=網頁瀏覽器 106 | GenericName[zh_TW]=網頁瀏覽器 107 | Comment=Access the Internet 108 | Comment[ar]=الدخول إلى الإنترنت 109 | Comment[ast]=Accesu a Internet 110 | Comment[bg]=Достъп до интернет 111 | Comment[bn]=ইন্টারনেটে প্রবেশ করুন 112 | Comment[bs]=Pristup internetu 113 | Comment[ca]=Accediu a Internet 114 | Comment[ca@valencia]=Accediu a Internet 115 | Comment[cs]=Přístup k internetu 116 | Comment[da]=Få adgang til internettet 117 | Comment[de]=Internetzugriff 118 | Comment[el]=Πρόσβαση στο Διαδίκτυο 119 | Comment[en_AU]=Access the Internet 120 | Comment[en_GB]=Access the Internet 121 | Comment[eo]=Akiri interreton 122 | Comment[es]=Acceda a Internet 123 | Comment[et]=Pääs Internetti 124 | Comment[eu]=Sartu Internetera 125 | Comment[fi]=Käytä internetiä 126 | Comment[fil]=I-access ang Internet 127 | Comment[fr]=Accéder à Internet 128 | Comment[gl]=Acceda a Internet 129 | Comment[gu]=ઇંટરનેટ ઍક્સેસ કરો 130 | Comment[he]=גישה לאינטרנט 131 | Comment[hi]=इंटरनेट तक पहुंच स्थापित करें 132 | Comment[hr]=Pristupite Internetu 133 | Comment[hu]=Az internet elérése 134 | Comment[hy]=Մուտք համացանց 135 | Comment[ia]=Accede a le Interrete 136 | Comment[id]=Akses Internet 137 | Comment[it]=Accesso a Internet 138 | Comment[ja]=インターネットにアクセス 139 | Comment[ka]=ინტერნეტში შესვლა 140 | Comment[kn]=ಇಂಟರ್ನೆಟ್ ಅನ್ನು ಪ್ರವೇಶಿಸಿ 141 | Comment[ko]=인터넷에 연결합니다 142 | Comment[kw]=Hedhes an Kesrosweyth 143 | Comment[lt]=Interneto prieiga 144 | Comment[lv]=Piekļūt internetam 145 | Comment[ml]=ഇന്റര്‍‌നെറ്റ് ആക്‌സസ് ചെയ്യുക 146 | Comment[mr]=इंटरनेटमध्ये प्रवेश करा 147 | Comment[ms]=Mengakses Internet 148 | Comment[nb]=Bruk internett 149 | Comment[nl]=Verbinding maken met internet 150 | Comment[or]=ଇଣ୍ଟର୍ନେଟ୍ ପ୍ରବେଶ କରନ୍ତୁ 151 | Comment[pl]=Skorzystaj z internetu 152 | Comment[pt]=Aceder à Internet 153 | Comment[pt_BR]=Acessar a internet 154 | Comment[ro]=Accesați Internetul 155 | Comment[ru]=Доступ в Интернет 156 | Comment[sk]=Prístup do siete Internet 157 | Comment[sl]=Dostop do interneta 158 | Comment[sr]=Приступите Интернету 159 | Comment[sv]=Surfa på Internet 160 | Comment[ta]=இணையத்தை அணுகுதல் 161 | Comment[te]=ఇంటర్నెట్‌ను ఆక్సెస్ చెయ్యండి 162 | Comment[th]=เข้าถึงอินเทอร์เน็ต 163 | Comment[tr]=İnternet'e erişin 164 | Comment[ug]=ئىنتېرنېت زىيارىتى 165 | Comment[uk]=Доступ до Інтернету 166 | Comment[vi]=Truy cập Internet 167 | Comment[zh_CN]=访问互联网 168 | Comment[zh_HK]=連線到網際網路 169 | Comment[zh_TW]=連線到網際網路 170 | Exec=chromium-browser %U 171 | Terminal=false 172 | X-MultipleArgs=false 173 | Type=Application 174 | Icon=chromium-browser 175 | Categories=Network;WebBrowser; 176 | MimeType=text/html;text/xml;application/xhtml_xml;x-scheme-handler/http;x-scheme-handler/https; 177 | StartupNotify=true 178 | Actions=NewWindow;Incognito;TempProfile; 179 | X-AppInstall-Package=chromium-browser 180 | 181 | [Desktop Action NewWindow] 182 | Name=Open a New Window 183 | Name[ast]=Abrir una Ventana Nueva 184 | Name[bg]=Отваряне на Нов прозорец 185 | Name[bn]=একটি নতুন উইন্ডো খুলুন 186 | Name[bs]=Otvori novi prozor 187 | Name[ca]=Obre una finestra nova 188 | Name[ca@valencia]=Obri una finestra nova 189 | Name[da]=Åbn et nyt vindue 190 | Name[de]=Ein neues Fenster öffnen 191 | Name[en_AU]=Open a New Window 192 | Name[eo]=Malfermi novan fenestron 193 | Name[es]=Abrir una ventana nueva 194 | Name[et]=Ava uus aken 195 | Name[eu]=Ireki leiho berria 196 | Name[fi]=Avaa uusi ikkuna 197 | Name[fr]=Ouvrir une nouvelle fenêtre 198 | Name[gl]=Abrir unha nova xanela 199 | Name[he]=פתיחת חלון חדש 200 | Name[hy]=Բացել նոր պատուհան 201 | Name[ia]=Aperi un nove fenestra 202 | Name[it]=Apri una nuova finestra 203 | Name[ja]=新しいウィンドウを開く 204 | Name[ka]=ახალი ფანჯრის გახსნა 205 | Name[kw]=Egery fenester noweth 206 | Name[ms]=Buka Tetingkap Baru 207 | Name[nb]=Åpne et nytt vindu 208 | Name[nl]=Nieuw venster openen 209 | Name[pt_BR]=Abre uma nova janela 210 | Name[ro]=Deschide o fereastră nouă 211 | Name[ru]=Открыть новое окно 212 | Name[sl]=Odpri novo okno 213 | Name[sv]=Öppna ett nytt fönster 214 | Name[ug]=يېڭى كۆزنەك ئاچ 215 | Name[uk]=Відкрити нове вікно 216 | Name[vi]=Mở cửa sổ mới 217 | Name[zh_CN]=打开新窗口 218 | Name[zh_TW]=開啟新視窗 219 | Exec=chromium-browser 220 | 221 | [Desktop Action Incognito] 222 | Name=Open a New Window in incognito mode 223 | Name[ast]=Abrir una ventana nueva en mou incógnitu 224 | Name[bg]=Отваряне на нов прозорец в режим \"инкогнито\" 225 | Name[bn]=একটি নতুন উইন্ডো খুলুন ইনকোগনিটো অবস্থায় 226 | Name[bs]=Otvori novi prozor u privatnom modu 227 | Name[ca]=Obre una finestra nova en mode d'incògnit 228 | Name[ca@valencia]=Obri una finestra nova en mode d'incògnit 229 | Name[de]=Ein neues Fenster im Inkognito-Modus öffnen 230 | Name[en_AU]=Open a New Window in incognito mode 231 | Name[eo]=Malfermi novan fenestron nekoniĝeble 232 | Name[es]=Abrir una ventana nueva en modo incógnito 233 | Name[et]=Ava uus aken tundmatus olekus 234 | Name[eu]=Ireki leiho berria isileko moduan 235 | Name[fi]=Avaa uusi ikkuna incognito-tilassa 236 | Name[fr]=Ouvrir une nouvelle fenêtre en mode navigation privée 237 | Name[gl]=Abrir unha nova xanela en modo de incógnito 238 | Name[he]=פתיחת חלון חדש במצב גלישה בסתר 239 | Name[hy]=Բացել նոր պատուհան ծպտյալ աշխատակերպում 240 | Name[ia]=Aperi un nove fenestra in modo incognite 241 | Name[it]=Apri una nuova finestra in modalità incognito 242 | Name[ja]=新しいシークレット ウィンドウを開く 243 | Name[ka]=ახალი ფანჯრის ინკოგნიტოდ გახსნა 244 | Name[kw]=Egry fenester noweth en modh privedh 245 | Name[ms]=Buka Tetingkap Baru dalam mod menyamar 246 | Name[nl]=Nieuw venster openen in incognito-modus 247 | Name[pt_BR]=Abrir uma nova janela em modo anônimo 248 | Name[ro]=Deschide o fereastră nouă în mod incognito 249 | Name[ru]=Открыть новое окно в режиме инкогнито 250 | Name[sl]=Odpri novo okno v načinu brez beleženja 251 | Name[sv]=Öppna ett nytt inkognitofönster 252 | Name[ug]=يوشۇرۇن ھالەتتە يېڭى كۆزنەك ئاچ 253 | Name[uk]=Відкрити нове вікно у приватному режимі 254 | Name[vi]=Mở cửa sổ mới trong chế độ ẩn danh 255 | Name[zh_CN]=以隐身模式打开新窗口 256 | Name[zh_TW]=以匿名模式開啟新視窗 257 | Exec=chromium-browser --incognito 258 | 259 | [Desktop Action TempProfile] 260 | Name=Open a New Window with a temporary profile 261 | Name[ast]=Abrir una ventana nueva con perfil temporal 262 | Name[bg]=Отваряне на Нов прозорец с временен профил 263 | Name[bn]=সাময়িক প্রোফাইল সহ একটি নতুন উইন্ডো খুলুন 264 | Name[bs]=Otvori novi prozor pomoću privremenog profila 265 | Name[ca]=Obre una finestra nova amb un perfil temporal 266 | Name[ca@valencia]=Obri una finestra nova amb un perfil temporal 267 | Name[de]=Ein neues Fenster mit einem temporären Profil öffnen 268 | Name[en_AU]=Open a New Window with a temporary profile 269 | Name[eo]=Malfermi novan fenestron portempe 270 | Name[es]=Abrir una ventana nueva con perfil temporal 271 | Name[et]=Ava uus aken ajutise profiiliga 272 | Name[eu]=Ireki leiho berria behin-behineko profil batekin 273 | Name[fi]=Avaa uusi ikkuna käyttäen väliaikaista profiilia 274 | Name[fr]=Ouvrir une nouvelle fenêtre avec un profil temporaire 275 | Name[gl]=Abrir unha nova xanela con perfil temporal 276 | Name[he]=פתיחת חלון חדש עם פרופיל זמני 277 | Name[hy]=Բացել նոր պատուհան ժամանակավոր հատկագրով 278 | Name[ia]=Aperi un nove fenestra con un profilo provisori 279 | Name[it]=Apri una nuova finestra con un profilo temporaneo 280 | Name[ja]=一時プロファイルで新しいウィンドウを開く 281 | Name[ka]=ახალი ფანჯრის გახსნა დროებით პროფილში 282 | Name[kw]=Egery fenester noweth gen profil dres prys 283 | Name[ms]=Buka Tetingkap Baru dengan profil sementara 284 | Name[nb]=Åpne et nytt vindu med en midlertidig profil 285 | Name[nl]=Nieuw venster openen met een tijdelijk profiel 286 | Name[pt_BR]=Abrir uma nova janela com um perfil temporário 287 | Name[ro]=Deschide o fereastră nouă cu un profil temporar 288 | Name[ru]=Открыть новое окно с временным профилем 289 | Name[sl]=Odpri novo okno z začasnim profilom 290 | Name[sv]=Öppna ett nytt fönster med temporär profil 291 | Name[ug]=ۋاقىتلىق سەپلىمە ھۆججەت بىلەن يېڭى كۆزنەك ئاچ 292 | Name[vi]=Mở cửa sổ mới với hồ sơ tạm 293 | Name[zh_CN]=以临时配置文件打开新窗口 294 | Name[zh_TW]=以暫時性個人身分開啟新視窗 295 | Exec=chromium-browser --temp-profile 296 | -------------------------------------------------------------------------------- /docker/xfce-chromium/src/home/readme-chromium.md: -------------------------------------------------------------------------------- 1 | # Readme `Chromium` 2 | 3 | Note that `Chromium Browser` in this container runs in `--no-sandbox` mode. You should be aware of the implications. The browser is intended for testing and development. 4 | -------------------------------------------------------------------------------- /docker/xfce-firefox/README-dockerhub.md: -------------------------------------------------------------------------------- 1 | # Headless Ubuntu/Xfce container with VNC/noVNC and Firefox browser 2 | 3 | ## accetto/ubuntu-vnc-xfce-firefox-g3 4 | 5 | [User Guide][this-user-guide] - [GitHub][this-github] - [Dockerfile][this-dockerfile] - [Readme][this-readme-full] - [Changelog][this-changelog] 6 | 7 | 8 | ![badge-github-release][badge-github-release]` ` 9 | ![badge-docker-pulls][badge-docker-pulls]` ` 10 | ![badge-docker-stars][badge-docker-stars] 11 | 12 | *** 13 | 14 | This Docker Hub repository contains Docker images for headless working. 15 | 16 | The images are based on [Ubuntu 24.04, 22.04 and 20.04 LTS][docker-ubuntu] and include [Xfce][xfce] desktop, [TigerVNC][tigervnc] server and [noVNC][novnc] client. 17 | The popular web browser [Firefox][firefox] is also included. 18 | 19 | This [User guide][this-user-guide] describes the images and how to use them. 20 | 21 | The related [GitHub project][this-github] contains image generators that image users generally don’t need, unless they want to build the images themselves. 22 | 23 | ### Tags 24 | 25 | The following image tags are regularly built and published on Docker Hub: 26 | 27 | - `latest` (also as `24.04`) based on `Ubuntu 24.04 LTS` 28 | 29 | ![badge_latest_created][badge_latest_created]` `[![badge_latest_version-sticker][badge_latest_version-sticker]][link_latest_version-sticker-verbose] 30 | 31 | - `22.04` based on `Ubuntu 22.04 LTS` 32 | 33 | ![badge_22-04_created][badge_22-04_created]` `[![badge_22-04_version-sticker][badge_22-04_version-sticker]][link_22-04_version-sticker-verbose] 34 | 35 | - `20.04` based on `Ubuntu 20.04 LTS` 36 | 37 | ![badge_20-04_created][badge_20-04_created]` `[![badge_20-04_version-sticker][badge_20-04_version-sticker]][link_20-04_version-sticker-verbose] 38 | 39 | 40 | 41 | **Hint:** Clicking the version sticker badge reveals more information about the particular build. 42 | 43 | ### Features 44 | 45 | The main features and components of the images in the default configuration are: 46 | 47 | - lightweight [Xfce][xfce] desktop environment (Ubuntu distribution) 48 | - [sudo][sudo] support 49 | - current version of JSON processor [jq][jq] 50 | - current version of high-performance [TigerVNC][tigervnc] server and client 51 | - current version of [noVNC][novnc] HTML5 clients (full and lite) (TCP port **6901**) 52 | - popular text editor [nano][nano] (Ubuntu distribution) 53 | - lite but advanced graphical editor [mousepad][mousepad] (Ubuntu distribution) 54 | - current version of [tini][tini] as the entry-point initial process (PID 1) 55 | - support for overriding environment variables, VNC parameters, user and group (see [User guide][this-user-guide-using-containers]) 56 | - support of **version sticker** (see [User guide][this-user-guide-version-sticker]) 57 | - [Firefox][firefox] web browser 58 | - images based on `Ubuntu 20.04 LTS` - current version from the `Ubuntu 20.04 LTS` distribution 59 | - images based on `Ubuntu 24.04 and 22.04 LTS` - current non-snap version from the Mozilla Team PPA 60 | - additional **Firefox plus** feature (see [User guide][this-user-guide-firefox-plus]) 61 | 62 | The following **TCP** ports are exposed by default: 63 | 64 | - **5901** for access over **VNC** (using VNC viewer) 65 | - **6901** for access over [noVNC][novnc] (using web browser) 66 | 67 | ![container-screenshot][this-screenshot-container] 68 | 69 | ### Remarks 70 | 71 | There is also a similar sibling image [accetto/debian-vnc-xfce-firefox-g3][accetto-dockerhub-debian-vnc-xfce-firefox-g3] based on [Debian][docker-debian]. 72 | 73 | This is the **third generation** (G3) of my headless images. 74 | The **second generation** (G2) contains the GitHub repository [accetto/xubuntu-vnc-novnc][accetto-github-xubuntu-vnc-novnc]. 75 | The **first generation** (G1) contains the GitHub repository [accetto/ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce]. 76 | 77 | The [Firefox][firefox] installed in the images based on `Ubuntu 24.04 and 22.04 LTS` is the current non-snap version from the Mozilla Team PPA. 78 | It's because the `Ubuntu 24.04 and 22.04 LTS` distribution contains only the `snap` version and the `snap` is currently not supported in Docker containers. 79 | 80 | ### Getting help 81 | 82 | If you've found a problem or you just have a question, please check the [User guide][this-user-guide], [Issues][this-issues] and [Wiki][this-wiki] first. 83 | Please do not overlook the closed issues. 84 | 85 | If you do not find a solution, you can file a new issue. 86 | The better you describe the problem, the bigger the chance it'll be solved soon. 87 | 88 | If you have a question or an idea and you don't want to open an issue, you can also use the [Discussions][this-discussions]. 89 | 90 | *** 91 | 92 | [this-user-guide]: https://accetto.github.io/user-guide-g3/ 93 | 94 | [this-user-guide-version-sticker]: https://accetto.github.io/user-guide-g3/version-sticker/ 95 | 96 | [this-user-guide-using-containers]: https://accetto.github.io/user-guide-g3/using-containers/ 97 | 98 | [this-user-guide-firefox-plus]: https://accetto.github.io/user-guide-g3/firefox-plus/ 99 | 100 | [this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/CHANGELOG.md 101 | 102 | [this-discussions]: https://github.com/accetto/ubuntu-vnc-xfce-g3/discussions 103 | 104 | [this-github]: https://github.com/accetto/ubuntu-vnc-xfce-g3/ 105 | 106 | [this-issues]: https://github.com/accetto/ubuntu-vnc-xfce-g3/issues 107 | 108 | [this-readme-full]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/xfce-firefox/README.md 109 | 110 | [this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki 111 | 112 | [this-dockerfile]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/Dockerfile.xfce.24-04 113 | 114 | [this-screenshot-container]: https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/master/docker/doc/images/animation-ubuntu-vnc-xfce-firefox-g3.gif 115 | 116 | [accetto-dockerhub-debian-vnc-xfce-firefox-g3]: https://hub.docker.com/r/accetto/debian-vnc-xfce-firefox-g3 117 | 118 | [accetto-github-xubuntu-vnc-novnc]: https://github.com/accetto/xubuntu-vnc-novnc/ 119 | 120 | [accetto-github-ubuntu-vnc-xfce]: https://github.com/accetto/ubuntu-vnc-xfce 121 | 122 | [docker-ubuntu]: https://hub.docker.com/_/ubuntu/ 123 | [docker-debian]: https://hub.docker.com/_/debian/ 124 | 125 | [jq]: https://stedolan.github.io/jq/ 126 | [mousepad]: https://github.com/codebrainz/mousepad 127 | [nano]: https://www.nano-editor.org/ 128 | [novnc]: https://github.com/kanaka/noVNC 129 | [sudo]: https://www.sudo.ws/ 130 | [tigervnc]: http://tigervnc.org 131 | [tini]: https://github.com/krallin/tini 132 | [xfce]: http://www.xfce.org 133 | 134 | [firefox]: https://www.mozilla.org 135 | 136 | [badge-github-release]: https://img.shields.io/github/v/release/accetto/ubuntu-vnc-xfce-g3 137 | 138 | [badge-docker-pulls]: https://img.shields.io/docker/pulls/accetto/ubuntu-vnc-xfce-firefox-g3 139 | 140 | [badge-docker-stars]: https://img.shields.io/docker/stars/accetto/ubuntu-vnc-xfce-firefox-g3 141 | 142 | 143 | -------------------------------------------------------------------------------- /docker/xfce-firefox/README.md: -------------------------------------------------------------------------------- 1 | # Headless Ubuntu/Xfce container with VNC/noVNC and Firefox browser 2 | 3 | ## accetto/ubuntu-vnc-xfce-firefox-g3 4 | 5 | [User Guide][this-user-guide] - [Docker Hub][this-docker] - [Dockerfile][this-dockerfile] - [Readme][this-readme] - [Changelog][this-changelog] 6 | 7 | *** 8 | 9 | This GitHub project folder contains resources used by building Ubuntu images available on Docker Hub in the repository [accetto/ubuntu-vnc-xfce-firefox-g3][this-docker]. 10 | 11 | This [User guide][this-user-guide] describes the images and how to use them. 12 | 13 | ### Building images 14 | 15 | ```shell 16 | ### PWD = project root 17 | ### prepare and source the 'secrets.rc' file first (see 'example-secrets.rc') 18 | 19 | ### examples of building and publishing the individual images 20 | ./builder.sh latest-firefox all 21 | 22 | ### just building the image, skipping the publishing and the version sticker update 23 | ./builder.sh latest-firefox build 24 | 25 | ### examples of building and publishing the images as a group 26 | ./ci-builder.sh all group latest-firefox 27 | ``` 28 | 29 | Refer to the main [README][this-readme] file for more information about the building subject. 30 | 31 | ### Remarks 32 | 33 | There is also a sibling project [accetto/debian-vnc-xfce-g3][accetto-github-debian-vnc-xfce-g3] containing similar images based on [Debian][docker-debian]. 34 | 35 | This is the **third generation** (G3) of my headless images. 36 | The **second generation** (G2) contains the GitHub repository [accetto/xubuntu-vnc-novnc][accetto-github-xubuntu-vnc-novnc]. 37 | The **first generation** (G1) contains the GitHub repository [accetto/ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce]. 38 | 39 | The [Firefox][firefox] installed in the images based on `Ubuntu 24.04 and 22.04 LTS` is the current non-snap version from the Mozilla Team PPA. 40 | It's because the `Ubuntu 24.04 and 22.04 LTS` distribution contains only the `snap` version and the `snap` is currently not supported in Docker containers. 41 | 42 | ### Getting help 43 | 44 | If you've found a problem or you just have a question, please check the [User guide][this-user-guide], [Issues][this-issues] and [Wiki][this-wiki] first. 45 | Please do not overlook the closed issues. 46 | 47 | If you do not find a solution, you can file a new issue. 48 | The better you describe the problem, the bigger the chance it'll be solved soon. 49 | 50 | If you have a question or an idea and you don't want to open an issue, you can also use the [Discussions][this-discussions]. 51 | 52 | ### Diagrams 53 | 54 | Diagram of the multi-staged Dockerfile used for building multiple images. 55 | 56 | The actual content of a particular image build is controlled by the *feature variables*. 57 | 58 | ![Dockerfile.xfce stages][this-diagram-dockerfile-stages] 59 | 60 | *** 61 | 62 | [this-user-guide]: https://accetto.github.io/user-guide-g3/ 63 | 64 | [this-readme]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/README.md 65 | 66 | [this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/CHANGELOG.md 67 | 68 | [this-discussions]: https://github.com/accetto/ubuntu-vnc-xfce-g3/discussions 69 | 70 | [this-issues]: https://github.com/accetto/ubuntu-vnc-xfce-g3/issues 71 | 72 | [this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki 73 | 74 | [this-docker]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-firefox-g3/ 75 | 76 | [this-dockerfile]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/Dockerfile.xfce.24-04 77 | 78 | [this-diagram-dockerfile-stages]: https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/master/docker/doc/images/Dockerfile.xfce.png 79 | 80 | [accetto-github-debian-vnc-xfce-g3]: https://github.com/accetto/debian-vnc-xfce-g3 81 | 82 | [accetto-github-xubuntu-vnc-novnc]: https://github.com/accetto/xubuntu-vnc-novnc/ 83 | 84 | [accetto-github-ubuntu-vnc-xfce]: https://github.com/accetto/ubuntu-vnc-xfce 85 | 86 | [docker-debian]: https://hub.docker.com/_/debian/ 87 | 88 | [firefox]: https://www.mozilla.org 89 | -------------------------------------------------------------------------------- /docker/xfce-firefox/readme-append.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | [badge_latest_created]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@created.json 7 | 8 | [badge_latest_version-sticker]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@version-sticker.json 9 | 10 | [link_latest_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@version-sticker-verbose.txt 11 | 12 | 13 | 14 | [badge_22-04_created]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@22.04@created.json 15 | 16 | [badge_22-04_version-sticker]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@22.04@version-sticker.json 17 | 18 | [link_22-04_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@22.04@version-sticker-verbose.txt 19 | 20 | 21 | 22 | [badge_20-04_created]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@20.04@created.json 23 | 24 | [badge_20-04_version-sticker]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@20.04@version-sticker.json 25 | 26 | [link_20-04_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@20.04@version-sticker-verbose.txt 27 | -------------------------------------------------------------------------------- /docker/xfce-firefox/src/firefox.plus/home/Desktop/Copy FF Preferences.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Name=Copy FF Preferences 5 | Comment=Copy user.js into Firefox profiles 6 | Icon=accetto 7 | Path= 8 | Terminal=true 9 | StartupNotify=true 10 | GenericName=Copy FF Preferences 11 | Exec=${HOME}/firefox.plus/copy_firefox_user_preferences.sh 12 | -------------------------------------------------------------------------------- /docker/xfce-firefox/src/firefox.plus/home/Desktop/FF Profile Manager.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Name=FF Profile Manager 5 | Comment=Open Firefox Profile Manager 6 | Exec=firefox -P 7 | Icon=accetto 8 | Path= 9 | Terminal=false 10 | StartupNotify=true 11 | -------------------------------------------------------------------------------- /docker/xfce-firefox/src/firefox.plus/home/readme-firefox-plus.md: -------------------------------------------------------------------------------- 1 | # Readme `firefox-plus` 2 | 3 | The **Firefox Plus** feature script `copy_firefox_user_preferences.sh` allows copying pre-configured user preferences into existing Firefox profiles easily. The script is stored in the folder `${HOME}/firefox.plus`. Check the page **How to use pre-configured Firefox preferences** in [this Wiki](https://github.com/accetto/ubuntu-vnc-xfce-firefox-plus/wiki/How-to#how-to-use-pre-configured-firefox-preferences) for more information. 4 | -------------------------------------------------------------------------------- /docker/xfce-firefox/src/firefox.plus/resources/accetto.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 20 | 22 | 23 | 25 | image/svg+xml 26 | 28 | 29 | 30 | 31 | 32 | 34 | 54 | 116 | 117 | -------------------------------------------------------------------------------- /docker/xfce-firefox/src/firefox.plus/resources/copy_firefox_user_preferences.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | ### @accetto (https://github.com/accetto) (https://hub.docker.com/u/accetto/) 3 | 4 | # ARG_OPTIONAL_SINGLE([source],[s],[Source folder (where 'user.js' is).],[${HOME}/firefox.plus]) 5 | # ARG_OPTIONAL_SINGLE([target],[t],[Target folder (where Firefox profiles are).],[${HOME}/.mozilla/firefox]) 6 | # ARG_VERSION([echo $0 v19.06.18]) 7 | # ARG_HELP([Copy 'user.js' into existing Firefox profiles]) 8 | # ARGBASH_GO() 9 | # needed because of Argbash --> m4_ignore([ 10 | ### START OF CODE GENERATED BY Argbash v2.8.0 one line above ### 11 | # Argbash is a bash code generator used to get arguments parsing right. 12 | # Argbash is FREE SOFTWARE, see https://argbash.io for more info 13 | 14 | 15 | die() 16 | { 17 | local _ret=$2 18 | test -n "$_ret" || _ret=1 19 | test "$_PRINT_HELP" = yes && print_help >&2 20 | echo "$1" >&2 21 | exit ${_ret} 22 | } 23 | 24 | 25 | begins_with_short_option() 26 | { 27 | local first_option all_short_options='stvh' 28 | first_option="${1:0:1}" 29 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 30 | } 31 | 32 | # THE DEFAULTS INITIALIZATION - OPTIONALS 33 | _arg_source="${HOME}/firefox.plus" 34 | _arg_target="${HOME}/.mozilla/firefox" 35 | 36 | 37 | print_help() 38 | { 39 | printf '%s\n' "Copy 'user.js' into existing Firefox profiles" 40 | printf 'Usage: %s [-s|--source ] [-t|--target ] [-v|--version] [-h|--help]\n' "$0" 41 | printf '\t%s\n' "-s, --source: Source folder (where 'user.js' is). (default: '${HOME}/firefox.plus')" 42 | printf '\t%s\n' "-t, --target: Target folder (where Firefox profiles are). (default: '${HOME}/.mozilla/firefox')" 43 | printf '\t%s\n' "-v, --version: Prints version" 44 | printf '\t%s\n' "-h, --help: Prints help" 45 | } 46 | 47 | 48 | parse_commandline() 49 | { 50 | while test $# -gt 0 51 | do 52 | _key="$1" 53 | case "$_key" in 54 | -s|--source) 55 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 56 | _arg_source="$2" 57 | shift 58 | ;; 59 | --source=*) 60 | _arg_source="${_key##--source=}" 61 | ;; 62 | -s*) 63 | _arg_source="${_key##-s}" 64 | ;; 65 | -t|--target) 66 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 67 | _arg_target="$2" 68 | shift 69 | ;; 70 | --target=*) 71 | _arg_target="${_key##--target=}" 72 | ;; 73 | -t*) 74 | _arg_target="${_key##-t}" 75 | ;; 76 | -v|--version) 77 | echo $0 v19.06.18 78 | exit 0 79 | ;; 80 | -v*) 81 | echo $0 v19.06.18 82 | exit 0 83 | ;; 84 | -h|--help) 85 | print_help 86 | exit 0 87 | ;; 88 | -h*) 89 | print_help 90 | exit 0 91 | ;; 92 | *) 93 | _PRINT_HELP=yes die "FATAL ERROR: Got an unexpected argument '$1'" 1 94 | ;; 95 | esac 96 | shift 97 | done 98 | } 99 | 100 | parse_commandline "$@" 101 | 102 | # OTHER STUFF GENERATED BY Argbash 103 | 104 | ### END OF CODE GENERATED BY Argbash (sortof) ### ]) 105 | # [ <-- needed because of Argbash 106 | 107 | _counter=0 108 | _file_userjs="user.js" 109 | _file_profilesini="profiles.ini" 110 | _full_userjs="" 111 | _full_profilesini="" 112 | _input="" 113 | _line=0 114 | _mark="" 115 | _oldIFS="" 116 | declare -a _list 117 | 118 | # LOCAL_DEBUG=true 119 | 120 | [[ $LOCAL_DEBUG ]] && _arg_source="." 121 | [[ $LOCAL_DEBUG ]] && _arg_target="../.mozilla/firefox" 122 | 123 | fn_die() 124 | { 125 | local _ret=$2 126 | test -n "$_ret" || _ret=1 127 | test "$_PRINT_HELP" = yes && print_help >&2 128 | echo "$1" >&2 129 | read -rp $"Press any key to close this window" -n1 _input 130 | exit ${_ret} 131 | } 132 | 133 | ### source and target folders must be provided 134 | # : ${_arg_source?} ${_arg_target?} 135 | [[ ! ${_arg_source} ]] && fn_die "Source path must be provided!" 136 | [[ ! ${_arg_target} ]] && fn_die "Target path must be provided!" 137 | 138 | _full_userjs="${_arg_source}/${_file_userjs}" 139 | _full_profilesini="${_arg_target}/${_file_profilesini}" 140 | 141 | ### source folder must contain 'user.js' 142 | [[ -f "${_full_userjs}" ]] && echo "File '${_full_userjs}' found." || fn_die "File '${_full_userjs}' not found!" 143 | 144 | ### target folder must contain 'profiles.ini' 145 | [[ -f ${_full_profilesini} ]] && echo "File '${_full_profilesini}' found." || fn_die "File '${_full_profilesini}' not found!" 146 | 147 | ### only profiles in 'profiles.ini' will be processed, get their count 148 | _counter=$( grep -c -E '^Path=' "${_full_profilesini}" ) 149 | 150 | if [[ $_counter -gt 0 ]] ; then 151 | 152 | ### extract profile folder names from 'profiles.ini' into the array 153 | ### be aware that user profile names/folders can contain spaces 154 | _oldIFS=$IFS 155 | IFS=$'\x0A'$'\x0D' 156 | _list=( $( grep -E '^Path=' "${_full_profilesini}" | sed -E -e 's/^Path=//' ) ) 157 | IFS=$_oldIFS 158 | 159 | echo "Following profiles found in '${_file_profilesini}' ('+|-' means with/without '${_file_userjs}'):" 160 | _counter=0 161 | for p in "${_list[@]}" ; do 162 | _counter=$((${_counter}+1)) 163 | [[ $(ls "${_arg_target}/$p/${_file_userjs}" 2>/dev/null) ]] && _mark=" + " || _mark=" - " 164 | printf ' %s %s %s\n' "$_counter" "$_mark" "$p" 165 | done 166 | 167 | ### user interaction 168 | read -rp $"Into which profile to copy '${_file_userjs}' (line number or 'all')? " _input 169 | _input=$(echo ${_input,,} | grep -i -E "^[0-9]+$|^all$") 170 | [[ ! ${_input} ]] && fn_die "INTERRUPTED: Line number or 'all' required!" 171 | if [[ "${_input,,}" != "all" ]] ; then 172 | 173 | ### line number has been provided 174 | _line=${_input} 175 | [[ ${_line} -lt 1 || ${_line} -gt ${_counter} ]] && fn_die "Line number must be from the interval [1..${_counter}]!" 176 | _line=$((${_line}-1)) 177 | 178 | ### copy 'user.js' into the selected profile folder 179 | cp -v "${_full_userjs}" "${_arg_target}/${_list[${_line}]}/" 180 | 181 | else 182 | # 'all' has been provided 183 | ### copy 'user.js' into all profiles not containing it yet 184 | for p in "${_list[@]}" ; do 185 | cp -v "${_full_userjs}" "${_arg_target}/$p/" 186 | done 187 | fi 188 | 189 | fn_die "SUCCESS." 0 190 | else 191 | echo "No profiles found in '${_full_profilesini}'." 192 | fi 193 | 194 | fn_die "" 0 195 | 196 | # ] <-- needed because of Argbash 197 | -------------------------------------------------------------------------------- /docker/xfce-firefox/src/firefox.plus/resources/user.js: -------------------------------------------------------------------------------- 1 | // Add the preferences you want to force here. 2 | // They will be forced for each session, but only in profiles containing this file. 3 | 4 | // Disable WebRTC leaks as explained in https://ipleak.net/#webrtcleak 5 | // Be aware that this has impact on some applications, e.g. some messengers. 6 | // user_pref("media.peerconnection.enabled", false); 7 | -------------------------------------------------------------------------------- /docker/xfce-firefox/src/home/Desktop/firefox.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Name=Firefox Web Browser 4 | Name[ar]=متصفح الويب فَيَرفُكْس 5 | Name[ast]=Restolador web Firefox 6 | Name[bn]=ফায়ারফক্স ওয়েব ব্রাউজার 7 | Name[ca]=Navegador web Firefox 8 | Name[cs]=Firefox Webový prohlížeč 9 | Name[da]=Firefox - internetbrowser 10 | Name[el]=Περιηγητής Firefox 11 | Name[es]=Navegador web Firefox 12 | Name[et]=Firefoxi veebibrauser 13 | Name[fa]=مرورگر اینترنتی Firefox 14 | Name[fi]=Firefox-selain 15 | Name[fr]=Navigateur Web Firefox 16 | Name[gl]=Navegador web Firefox 17 | Name[he]=דפדפן האינטרנט Firefox 18 | Name[hr]=Firefox web preglednik 19 | Name[hu]=Firefox webböngésző 20 | Name[it]=Firefox Browser Web 21 | Name[ja]=Firefox ウェブ・ブラウザ 22 | Name[ko]=Firefox 웹 브라우저 23 | Name[ku]=Geroka torê Firefox 24 | Name[lt]=Firefox interneto naršyklė 25 | Name[nb]=Firefox Nettleser 26 | Name[nl]=Firefox webbrowser 27 | Name[nn]=Firefox Nettlesar 28 | Name[no]=Firefox Nettleser 29 | Name[pl]=Przeglądarka WWW Firefox 30 | Name[pt]=Firefox Navegador Web 31 | Name[pt_BR]=Navegador Web Firefox 32 | Name[ro]=Firefox – Navigator Internet 33 | Name[ru]=Веб-браузер Firefox 34 | Name[sk]=Firefox - internetový prehliadač 35 | Name[sl]=Firefox spletni brskalnik 36 | Name[sv]=Firefox webbläsare 37 | Name[tr]=Firefox Web Tarayıcısı 38 | Name[ug]=Firefox توركۆرگۈ 39 | Name[uk]=Веб-браузер Firefox 40 | Name[vi]=Trình duyệt web Firefox 41 | Name[zh_CN]=Firefox 网络浏览器 42 | Name[zh_TW]=Firefox 網路瀏覽器 43 | Comment=Browse the World Wide Web 44 | Comment[ar]=تصفح الشبكة العنكبوتية العالمية 45 | Comment[ast]=Restola pela Rede 46 | Comment[bn]=ইন্টারনেট ব্রাউজ করুন 47 | Comment[ca]=Navegueu per la web 48 | Comment[cs]=Prohlížení stránek World Wide Webu 49 | Comment[da]=Surf på internettet 50 | Comment[de]=Im Internet surfen 51 | Comment[el]=Μπορείτε να περιηγηθείτε στο διαδίκτυο (Web) 52 | Comment[es]=Navegue por la web 53 | Comment[et]=Lehitse veebi 54 | Comment[fa]=صفحات شبکه جهانی اینترنت را مرور نمایید 55 | Comment[fi]=Selaa Internetin WWW-sivuja 56 | Comment[fr]=Naviguer sur le Web 57 | Comment[gl]=Navegar pola rede 58 | Comment[he]=גלישה ברחבי האינטרנט 59 | Comment[hr]=Pretražite web 60 | Comment[hu]=A világháló böngészése 61 | Comment[it]=Esplora il web 62 | Comment[ja]=ウェブを閲覧します 63 | Comment[ko]=웹을 돌아 다닙니다 64 | Comment[ku]=Li torê bigere 65 | Comment[lt]=Naršykite internete 66 | Comment[nb]=Surf på nettet 67 | Comment[nl]=Verken het internet 68 | Comment[nn]=Surf på nettet 69 | Comment[no]=Surf på nettet 70 | Comment[pl]=Przeglądanie stron WWW 71 | Comment[pt]=Navegue na Internet 72 | Comment[pt_BR]=Navegue na Internet 73 | Comment[ro]=Navigați pe Internet 74 | Comment[ru]=Доступ в Интернет 75 | Comment[sk]=Prehliadanie internetu 76 | Comment[sl]=Brskajte po spletu 77 | Comment[sv]=Surfa på webben 78 | Comment[tr]=İnternet'te Gezinin 79 | Comment[ug]=دۇنيادىكى توربەتلەرنى كۆرگىلى بولىدۇ 80 | Comment[uk]=Перегляд сторінок Інтернету 81 | Comment[vi]=Để duyệt các trang web 82 | Comment[zh_CN]=浏览互联网 83 | Comment[zh_TW]=瀏覽網際網路 84 | GenericName=Web Browser 85 | GenericName[ar]=متصفح ويب 86 | GenericName[ast]=Restolador Web 87 | GenericName[bn]=ওয়েব ব্রাউজার 88 | GenericName[ca]=Navegador web 89 | GenericName[cs]=Webový prohlížeč 90 | GenericName[da]=Webbrowser 91 | GenericName[el]=Περιηγητής διαδικτύου 92 | GenericName[es]=Navegador web 93 | GenericName[et]=Veebibrauser 94 | GenericName[fa]=مرورگر اینترنتی 95 | GenericName[fi]=WWW-selain 96 | GenericName[fr]=Navigateur Web 97 | GenericName[gl]=Navegador Web 98 | GenericName[he]=דפדפן אינטרנט 99 | GenericName[hr]=Web preglednik 100 | GenericName[hu]=Webböngésző 101 | GenericName[it]=Browser web 102 | GenericName[ja]=ウェブ・ブラウザ 103 | GenericName[ko]=웹 브라우저 104 | GenericName[ku]=Geroka torê 105 | GenericName[lt]=Interneto naršyklė 106 | GenericName[nb]=Nettleser 107 | GenericName[nl]=Webbrowser 108 | GenericName[nn]=Nettlesar 109 | GenericName[no]=Nettleser 110 | GenericName[pl]=Przeglądarka WWW 111 | GenericName[pt]=Navegador Web 112 | GenericName[pt_BR]=Navegador Web 113 | GenericName[ro]=Navigator Internet 114 | GenericName[ru]=Веб-браузер 115 | GenericName[sk]=Internetový prehliadač 116 | GenericName[sl]=Spletni brskalnik 117 | GenericName[sv]=Webbläsare 118 | GenericName[tr]=Web Tarayıcı 119 | GenericName[ug]=توركۆرگۈ 120 | GenericName[uk]=Веб-браузер 121 | GenericName[vi]=Trình duyệt Web 122 | GenericName[zh_CN]=网络浏览器 123 | GenericName[zh_TW]=網路瀏覽器 124 | Keywords=Internet;WWW;Browser;Web;Explorer 125 | Keywords[ar]=انترنت;إنترنت;متصفح;ويب;وب 126 | Keywords[ast]=Internet;WWW;Restolador;Web;Esplorador 127 | Keywords[ca]=Internet;WWW;Navegador;Web;Explorador;Explorer 128 | Keywords[cs]=Internet;WWW;Prohlížeč;Web;Explorer 129 | Keywords[da]=Internet;Internettet;WWW;Browser;Browse;Web;Surf;Nettet 130 | Keywords[de]=Internet;WWW;Browser;Web;Explorer;Webseite;Site;surfen;online;browsen 131 | Keywords[el]=Internet;WWW;Browser;Web;Explorer;Διαδίκτυο;Περιηγητής;Firefox;Φιρεφοχ;Ιντερνετ 132 | Keywords[es]=Explorador;Internet;WWW 133 | Keywords[fi]=Internet;WWW;Browser;Web;Explorer;selain;Internet-selain;internetselain;verkkoselain;netti;surffaa 134 | Keywords[fr]=Internet;WWW;Browser;Web;Explorer;Fureteur;Surfer;Navigateur 135 | Keywords[he]=דפדפן;אינטרנט;רשת;אתרים;אתר;פיירפוקס;מוזילה; 136 | Keywords[hr]=Internet;WWW;preglednik;Web 137 | Keywords[hu]=Internet;WWW;Böngésző;Web;Háló;Net;Explorer 138 | Keywords[it]=Internet;WWW;Browser;Web;Navigatore 139 | Keywords[is]=Internet;WWW;Vafri;Vefur;Netvafri;Flakk 140 | Keywords[ja]=Internet;WWW;Web;インターネット;ブラウザ;ウェブ;エクスプローラ 141 | Keywords[nb]=Internett;WWW;Nettleser;Explorer;Web;Browser;Nettside 142 | Keywords[nl]=Internet;WWW;Browser;Web;Explorer;Verkenner;Website;Surfen;Online 143 | Keywords[pt]=Internet;WWW;Browser;Web;Explorador;Navegador 144 | Keywords[pt_BR]=Internet;WWW;Browser;Web;Explorador;Navegador 145 | Keywords[ru]=Internet;WWW;Browser;Web;Explorer;интернет;браузер;веб;файрфокс;огнелис 146 | Keywords[sk]=Internet;WWW;Prehliadač;Web;Explorer 147 | Keywords[sl]=Internet;WWW;Browser;Web;Explorer;Brskalnik;Splet 148 | Keywords[tr]=İnternet;WWW;Tarayıcı;Web;Gezgin;Web sitesi;Site;sörf;çevrimiçi;tara 149 | Keywords[uk]=Internet;WWW;Browser;Web;Explorer;Інтернет;мережа;переглядач;оглядач;браузер;веб;файрфокс;вогнелис;перегляд 150 | Keywords[vi]=Internet;WWW;Browser;Web;Explorer;Trình duyệt;Trang web 151 | Keywords[zh_CN]=Internet;WWW;Browser;Web;Explorer;网页;浏览;上网;火狐;Firefox;ff;互联网;网站; 152 | Keywords[zh_TW]=Internet;WWW;Browser;Web;Explorer;網際網路;網路;瀏覽器;上網;網頁;火狐 153 | Exec=firefox %u 154 | Terminal=false 155 | X-MultipleArgs=false 156 | Type=Application 157 | Icon=firefox 158 | Categories=GNOME;GTK;Network;WebBrowser; 159 | MimeType=text/html;text/xml;application/xhtml+xml;application/xml;application/rss+xml;application/rdf+xml;image/gif;image/jpeg;image/png;x-scheme-handler/http;x-scheme-handler/https;x-scheme-handler/ftp;x-scheme-handler/chrome;video/webm;application/x-xpinstall; 160 | StartupNotify=true 161 | Actions=new-window;new-private-window; 162 | 163 | [Desktop Action new-window] 164 | Name=Open a New Window 165 | Name[ar]=افتح نافذة جديدة 166 | Name[ast]=Abrir una ventana nueva 167 | Name[bn]=Abrir una ventana nueva 168 | Name[ca]=Obre una finestra nova 169 | Name[cs]=Otevřít nové okno 170 | Name[da]=Åbn et nyt vindue 171 | Name[de]=Ein neues Fenster öffnen 172 | Name[el]=Νέο παράθυρο 173 | Name[es]=Abrir una ventana nueva 174 | Name[fi]=Avaa uusi ikkuna 175 | Name[fr]=Ouvrir une nouvelle fenêtre 176 | Name[gl]=Abrir unha nova xanela 177 | Name[he]=פתיחת חלון חדש 178 | Name[hr]=Otvori novi prozor 179 | Name[hu]=Új ablak nyitása 180 | Name[it]=Apri una nuova finestra 181 | Name[ja]=新しいウィンドウを開く 182 | Name[ko]=새 창 열기 183 | Name[ku]=Paceyeke nû veke 184 | Name[lt]=Atverti naują langą 185 | Name[nb]=Åpne et nytt vindu 186 | Name[nl]=Nieuw venster openen 187 | Name[pt]=Abrir nova janela 188 | Name[pt_BR]=Abrir nova janela 189 | Name[ro]=Deschide o fereastră nouă 190 | Name[ru]=Новое окно 191 | Name[sk]=Otvoriť nové okno 192 | Name[sl]=Odpri novo okno 193 | Name[sv]=Öppna ett nytt fönster 194 | Name[tr]=Yeni pencere aç 195 | Name[ug]=يېڭى كۆزنەك ئېچىش 196 | Name[uk]=Відкрити нове вікно 197 | Name[vi]=Mở cửa sổ mới 198 | Name[zh_CN]=新建窗口 199 | Name[zh_TW]=開啟新視窗 200 | Exec=firefox -new-window 201 | 202 | [Desktop Action new-private-window] 203 | Name=Open a New Private Window 204 | Name[ar]=افتح نافذة جديدة للتصفح الخاص 205 | Name[ca]=Obre una finestra nova en mode d'incògnit 206 | Name[cs]=Otevřít nové anonymní okno 207 | Name[de]=Ein neues privates Fenster öffnen 208 | Name[el]=Νέο ιδιωτικό παράθυρο 209 | Name[es]=Abrir una ventana privada nueva 210 | Name[fi]=Avaa uusi yksityinen ikkuna 211 | Name[fr]=Ouvrir une nouvelle fenêtre de navigation privée 212 | Name[he]=פתיחת חלון גלישה פרטית חדש 213 | Name[hu]=Új privát ablak nyitása 214 | Name[it]=Apri una nuova finestra anonima 215 | Name[nb]=Åpne et nytt privat vindu 216 | Name[ru]=Новое приватное окно 217 | Name[sl]=Odpri novo okno zasebnega brskanja 218 | Name[sv]=Öppna ett nytt privat fönster 219 | Name[tr]=Yeni gizli pencere aç 220 | Name[uk]=Відкрити нове вікно у потайливому режимі 221 | Name[zh_TW]=開啟新隱私瀏覽視窗 222 | Exec=firefox -private-window 223 | -------------------------------------------------------------------------------- /docker/xfce/README-dockerhub.md: -------------------------------------------------------------------------------- 1 | # Headless Ubuntu/Xfce container with VNC/noVNC 2 | 3 | ## accetto/ubuntu-vnc-xfce-g3 4 | 5 | [User Guide][this-user-guide] - [GitHub][this-github] - [Dockerfile][this-dockerfile] - [Readme][this-readme-full] - [Changelog][this-changelog] 6 | 7 | 8 | ![badge-github-release][badge-github-release]` ` 9 | ![badge-docker-pulls][badge-docker-pulls]` ` 10 | ![badge-docker-stars][badge-docker-stars] 11 | 12 | *** 13 | 14 | This Docker Hub repository contains Docker images for headless working. 15 | 16 | The images are based on [Ubuntu 24.04, 22.04 and 20.04 LTS][docker-ubuntu] and include [Xfce][xfce] desktop, [TigerVNC][tigervnc] server and [noVNC][novnc] client. 17 | 18 | This [User guide][this-user-guide] describes the images and how to use them. 19 | 20 | The related [GitHub project][this-github] contains image generators that image users generally don’t need, unless they want to build the images themselves. 21 | 22 | ### Tags 23 | 24 | The following image tags are regularly built and published on Docker Hub: 25 | 26 | - `latest` (also as `24.04`) based on `Ubuntu 24.04 LTS` 27 | 28 | ![badge_latest_created][badge_latest_created]` ` 29 | [![badge_latest_version-sticker][badge_latest_version-sticker]][link_latest_version-sticker-verbose] 30 | 31 | - `22.04` based on `Ubuntu 22.04 LTS` 32 | 33 | ![badge_22-04_created][badge_22-04_created]` ` 34 | [![badge_22-04_version-sticker][badge_22-04_version-sticker]][link_22-04_version-sticker-verbose] 35 | 36 | - `20.04` based on `Ubuntu 20.04 LTS` 37 | 38 | ![badge_20-04_created][badge_20-04_created]` ` 39 | [![badge_20-04_version-sticker][badge_20-04_version-sticker]][link_20-04_version-sticker-verbose] 40 | 41 | 42 | 43 | **Hint:** Clicking the version sticker badge reveals more information about the particular build. 44 | 45 | ### Features 46 | 47 | The main features and components of the images in the default configuration are: 48 | 49 | - lightweight [Xfce][xfce] desktop environment (Debian distribution) 50 | - [sudo][sudo] support 51 | - current version of JSON processor [jq][jq] 52 | - current version of high-performance [TigerVNC][tigervnc] server and client 53 | - current version of [noVNC][novnc] HTML5 clients (full and lite) (TCP port **6901**) 54 | - popular text editor [nano][nano] (Ubuntu distribution) 55 | - lite but advanced graphical editor [mousepad][mousepad] (Ubuntu distribution) 56 | - current version of [tini][tini] as the entry-point initial process (PID 1) 57 | - support for overriding environment variables, VNC parameters, user and group (see [User guide][this-user-guide-using-containers]) 58 | - support of **version sticker** (see [User guide][this-user-guide-version-sticker]) 59 | 60 | The following **TCP** ports are exposed by default: 61 | 62 | - **5901** for access over **VNC** (using VNC viewer) 63 | - **6901** for access over [noVNC][novnc] (using web browser) 64 | 65 | ![container-screenshot][this-screenshot-container] 66 | 67 | ### Remarks 68 | 69 | There is also a similar sibling repository [accetto/debian-vnc-xfce-g3][accetto-dockerhub-debian-vnc-xfce-g3] based on [Debian][docker-debian]. 70 | 71 | This is the **third generation** (G3) of my headless images. 72 | The **second generation** (G2) contains the GitHub repository [accetto/xubuntu-vnc-novnc][accetto-github-xubuntu-vnc-novnc]. 73 | The **first generation** (G1) contains the GitHub repository [accetto/ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce]. 74 | 75 | ### Getting help 76 | 77 | If you've found a problem or you just have a question, please check the [User guide][this-user-guide], [Issues][this-issues] and [Wiki][this-wiki] first. 78 | Please do not overlook the closed issues. 79 | 80 | If you do not find a solution, you can file a new issue. 81 | The better you describe the problem, the bigger the chance it'll be solved soon. 82 | 83 | If you have a question or an idea and you don't want to open an issue, you can also use the [Discussions][this-discussions]. 84 | 85 | *** 86 | 87 | [this-user-guide]: https://accetto.github.io/user-guide-g3/ 88 | 89 | [this-user-guide-version-sticker]: https://accetto.github.io/user-guide-g3/version-sticker/ 90 | 91 | [this-user-guide-using-containers]: https://accetto.github.io/user-guide-g3/using-containers/ 92 | 93 | [this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/CHANGELOG.md 94 | 95 | [this-github]: https://github.com/accetto/ubuntu-vnc-xfce-g3/ 96 | 97 | [this-issues]: https://github.com/accetto/ubuntu-vnc-xfce-g3/issues 98 | 99 | [this-readme-full]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/xfce/README.md 100 | 101 | [this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki 102 | 103 | [this-discussions]: https://github.com/accetto/ubuntu-vnc-xfce-g3/discussions 104 | 105 | [this-dockerfile]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/Dockerfile.xfce.24-04 106 | 107 | [this-screenshot-container]: https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/master/docker/doc/images/animation-ubuntu-vnc-xfce-g3.gif 108 | 109 | [accetto-github-xubuntu-vnc-novnc]: https://github.com/accetto/xubuntu-vnc-novnc/ 110 | 111 | [accetto-github-ubuntu-vnc-xfce]: https://github.com/accetto/ubuntu-vnc-xfce 112 | 113 | [accetto-dockerhub-debian-vnc-xfce-g3]: https://hub.docker.com/r/accetto/debian-vnc-xfce-g3 114 | 115 | [docker-ubuntu]: https://hub.docker.com/_/ubuntu/ 116 | [docker-debian]: https://hub.docker.com/_/debian/ 117 | 118 | [jq]: https://stedolan.github.io/jq/ 119 | [mousepad]: https://github.com/codebrainz/mousepad 120 | [nano]: https://www.nano-editor.org/ 121 | [novnc]: https://github.com/kanaka/noVNC 122 | [sudo]: https://www.sudo.ws/ 123 | [tigervnc]: http://tigervnc.org 124 | [tini]: https://github.com/krallin/tini 125 | [xfce]: http://www.xfce.org 126 | 127 | [badge-github-release]: https://img.shields.io/github/v/release/accetto/ubuntu-vnc-xfce-g3 128 | 129 | [badge-docker-pulls]: https://img.shields.io/docker/pulls/accetto/ubuntu-vnc-xfce-g3 130 | 131 | [badge-docker-stars]: https://img.shields.io/docker/stars/accetto/ubuntu-vnc-xfce-g3 132 | 133 | 134 | -------------------------------------------------------------------------------- /docker/xfce/README.md: -------------------------------------------------------------------------------- 1 | # Headless Ubuntu/Xfce container with VNC/noVNC 2 | 3 | ## accetto/ubuntu-vnc-xfce-g3 4 | 5 | [User Guide][this-user-guide] - [Docker Hub][this-docker] - [Dockerfile][this-dockerfile] - [Readme][this-readme] - [Changelog][this-changelog] 6 | 7 | *** 8 | 9 | This GitHub project folder contains resources used by building Ubuntu images available on Docker Hub in the repository [accetto/ubuntu-vnc-xfce-g3][this-docker]. 10 | 11 | This [User guide][this-user-guide] describes the images and how to use them. 12 | 13 | ### Building images 14 | 15 | ```shell 16 | ### PWD = project root 17 | ### prepare and source the 'secrets.rc' file first (see 'example-secrets.rc') 18 | 19 | ### examples of building and publishing the individual images 20 | ./builder.sh latest all 21 | 22 | ### just building the image, skipping the publishing and the version sticker update 23 | ./builder.sh latest build 24 | 25 | ### examples of building and publishing the images 26 | ./ci-builder.sh all group latest 27 | ``` 28 | 29 | Refer to the main [README][this-readme] file for more information about the building subject. 30 | 31 | ### Remarks 32 | 33 | There is also a sibling project [accetto/debian-vnc-xfce-g3][accetto-github-debian-vnc-xfce-g3] containing similar images based on [Debian][docker-debian]. 34 | 35 | This is the **third generation** (G3) of my headless images. 36 | The **second generation** (G2) contains the GitHub repository [accetto/xubuntu-vnc-novnc][accetto-github-xubuntu-vnc-novnc]. 37 | The **first generation** (G1) contains the GitHub repository [accetto/ubuntu-vnc-xfce][accetto-github-ubuntu-vnc-xfce]. 38 | 39 | ### Getting help 40 | 41 | If you've found a problem or you just have a question, please check the [User guide][this-user-guide], [Issues][this-issues] and [Wiki][this-wiki] first. 42 | Please do not overlook the closed issues. 43 | 44 | If you do not find a solution, you can file a new issue. 45 | The better you describe the problem, the bigger the chance it'll be solved soon. 46 | 47 | If you have a question or an idea and you don't want to open an issue, you can also use the [Discussions][this-discussions]. 48 | 49 | ### Diagrams 50 | 51 | Diagram of the multi-staged Dockerfile used for building multiple images. 52 | 53 | The actual content of a particular image build is controlled by the *feature variables*. 54 | 55 | ![Dockerfile.xfce stages][this-diagram-dockerfile-stages] 56 | 57 | *** 58 | 59 | [this-user-guide]: https://accetto.github.io/user-guide-g3/ 60 | 61 | [this-readme]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/README.md 62 | 63 | [this-changelog]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/CHANGELOG.md 64 | 65 | [this-discussions]: https://github.com/accetto/ubuntu-vnc-xfce-g3/discussions 66 | 67 | [this-issues]: https://github.com/accetto/ubuntu-vnc-xfce-g3/issues 68 | 69 | [this-wiki]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki 70 | 71 | [this-docker]: https://hub.docker.com/r/accetto/ubuntu-vnc-xfce-g3/ 72 | 73 | [this-dockerfile]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/docker/Dockerfile.xfce.24-04 74 | 75 | [this-diagram-dockerfile-stages]: https://raw.githubusercontent.com/accetto/ubuntu-vnc-xfce-g3/master/docker/doc/images/Dockerfile.xfce.png 76 | 77 | [accetto-github-debian-vnc-xfce-g3]: https://github.com/accetto/debian-vnc-xfce-g3 78 | 79 | [accetto-github-xubuntu-vnc-novnc]: https://github.com/accetto/xubuntu-vnc-novnc/ 80 | 81 | [accetto-github-ubuntu-vnc-xfce]: https://github.com/accetto/ubuntu-vnc-xfce 82 | 83 | [docker-debian]: https://hub.docker.com/_/debian/ 84 | -------------------------------------------------------------------------------- /docker/xfce/readme-append.template: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | [badge_latest_created]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@created.json 7 | 8 | [badge_latest_version-sticker]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@version-sticker.json 9 | 10 | [link_latest_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@latest@version-sticker-verbose.txt 11 | 12 | 13 | 14 | [badge_22-04_created]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@22.04@created.json 15 | 16 | [badge_22-04_version-sticker]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@22.04@version-sticker.json 17 | 18 | [link_22-04_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@22.04@version-sticker-verbose.txt 19 | 20 | 21 | 22 | [badge_20-04_created]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@20.04@created.json 23 | 24 | [badge_20-04_version-sticker]: https://img.shields.io/endpoint?url=https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@20.04@version-sticker.json 25 | 26 | [link_20-04_version-sticker-verbose]: https://gist.githubusercontent.com/${OWNER}/${GIST}/raw/${REPO}@20.04@version-sticker-verbose.txt 27 | -------------------------------------------------------------------------------- /docker/xfce/src/home/Desktop/versionsticker.desktop: -------------------------------------------------------------------------------- 1 | [Desktop Entry] 2 | Version=1.0 3 | Type=Application 4 | Name=Version Sticker 5 | Comment=Verbose version sticker 6 | Exec=bash -c 'echo "Wait..." ; ${STARTUPDIR}/version_sticker.sh -f -V ; read -p "Press ENTER..."' 7 | Path=${STARTUPDIR} 8 | Terminal=true 9 | StartupNotify=false 10 | Icon=application-certificate -------------------------------------------------------------------------------- /docker/xfce/src/home/config/xfce4/terminal/terminalrc: -------------------------------------------------------------------------------- 1 | [Configuration] 2 | Encoding=UTF-8 3 | MiscAlwaysShowTabs=FALSE 4 | MiscBell=FALSE 5 | MiscBellUrgent=FALSE 6 | MiscBordersDefault=TRUE 7 | MiscCursorBlinks=FALSE 8 | MiscCursorShape=TERMINAL_CURSOR_SHAPE_BLOCK 9 | MiscDefaultGeometry=80x24 10 | MiscInheritGeometry=FALSE 11 | MiscMenubarDefault=TRUE 12 | MiscMouseAutohide=FALSE 13 | MiscMouseWheelZoom=TRUE 14 | MiscToolbarDefault=FALSE 15 | MiscConfirmClose=TRUE 16 | MiscCycleTabs=TRUE 17 | MiscTabCloseButtons=TRUE 18 | MiscTabCloseMiddleClick=TRUE 19 | MiscTabPosition=GTK_POS_TOP 20 | MiscHighlightUrls=TRUE 21 | MiscMiddleClickOpensUri=FALSE 22 | MiscCopyOnSelect=FALSE 23 | MiscShowRelaunchDialog=TRUE 24 | MiscRewrapOnResize=TRUE 25 | MiscUseShiftArrowsToScroll=FALSE 26 | MiscSlimTabs=FALSE 27 | MiscNewTabAdjacent=FALSE 28 | MiscSearchDialogOpacity=100 29 | MiscShowUnsafePasteDialog=TRUE 30 | 31 | -------------------------------------------------------------------------------- /docker/xfce/src/home/config/xfce4/xfconf/xfce-perchannel-xml/keyboard-layout.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docker/xfce/src/home/config/xfce4/xfconf/xfce-perchannel-xml/thunar.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /docker/xfce/src/home/config/xfce4/xfconf/xfce-perchannel-xml/xfwm4.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | -------------------------------------------------------------------------------- /docker/xfce/src/home/readme.md: -------------------------------------------------------------------------------- 1 | # Readme 2 | 3 | This is the main **README** file of a set of configurable Docker images that can include additional features. 4 | 5 | There may be also other **README** files in the home directory. 6 | -------------------------------------------------------------------------------- /examples/Dockerfile.extend: -------------------------------------------------------------------------------- 1 | # docker build -f Dockerfile.extend -t accetto/ubuntu-vnc-xfce-g3:extended . 2 | 3 | ### This is an example of extending the images. 4 | 5 | ### HINTS 6 | ### Sometimes you can get building errors related to cache handling. 7 | ### One of the following usually helps: 8 | ### (1) Use the '--no-cache' option 9 | ### > docker build ... --no-cache 10 | ### (2) Purge the builder cache before and/or between builds 11 | ### > docker builder prune 12 | ### (3) Re-open the terminal and/or Visual Studio Code 13 | ### (4) Remove the line containing 'rm -rf /var/lib/apt/lists/*' 14 | ### from your extending Dockerfile (like this one) 15 | 16 | ### choose a base image and tag 17 | ARG BASEIMAGE="accetto/ubuntu-vnc-xfce-g3" 18 | # ARG BASEIMAGE="accetto/ubuntu-vnc-xfce-chromium-g3" 19 | # ARG BASEIMAGE="accetto/ubuntu-vnc-xfce-firefox-g3" 20 | ARG BASETAG="latest" 21 | 22 | FROM ${BASEIMAGE}:${BASETAG} 23 | 24 | ### switch to the root user to be able to install new packages 25 | USER 0 26 | 27 | ### update the apt cache and install your new packages 28 | ### e.g. vim editor 29 | RUN \ 30 | apt-get update \ 31 | && apt-get install -y --no-install-recommends \ 32 | vim \ 33 | && apt-get -y autoremove \ 34 | && rm -rf /var/lib/apt/lists/* 35 | 36 | ### maybe you want to add some additional resources 37 | ### e.g. some preconfigured files 38 | # COPY ./bashrc "${HOME}"/.bashrc 39 | # COPY ./firefox.plus/user.js "${HOME}"/firefox.plus/ 40 | 41 | ### avoid the pitfall of failing startup under some circumstances 42 | ### permissions will be set to the system defaults on the first container start 43 | RUN chmod 666 /etc/passwd /etc/group 44 | 45 | ### usually you want to swich back to a non-root user 46 | ### alternatively you can do it in a compose file (see 'example.yml') 47 | USER "${HEADLESS_USER_ID}" 48 | 49 | ### note that some applications refuse to be installed under the root user 50 | ### those you have to install after switching the user 51 | # RUN \ 52 | # apt-get update \ 53 | # && apt-get install -y \ 54 | # \ 55 | # && apt-get -y autoremove \ 56 | # && rm -rf /var/lib/apt/lists/* 57 | -------------------------------------------------------------------------------- /examples/example-override-envv.rc: -------------------------------------------------------------------------------- 1 | ### only the lines beginning with 'export ' at the first position and containing '=' will be sourced 2 | export VNC_RESOLUTION=1024x768 3 | export VNC_PW=secret 4 | #export DISPLAY=:2 5 | #export VNC_COL_DEPTH=32 6 | -------------------------------------------------------------------------------- /examples/example-secrets.rc: -------------------------------------------------------------------------------- 1 | ### This files configures the environment (including secrets!) for building images locally. 2 | ### Source this file before building. 3 | ### Rename it to "secrets.rc" (or similar) and **make sure** that the '.gitignore' and '.dockerignore' files 4 | ### contain the 'secret*' exclusion pattern! 5 | ### Example: source ./secrets.rc 6 | ### This file is automatically sourced by the script 'hooks/env.rc' if it's found in the same directory. 7 | 8 | #region General building pipeline control 9 | 10 | export DOCKER_BUILDKIT=1 11 | # export COMPOSE_DOCKER_CLI_BUILD=0 12 | 13 | ### will force re-building regardless of the verbose version sticker changes 14 | # export FORCE_BUILDING=0 15 | 16 | ### will prohibit re-building regardless of verbose version sticker changes 17 | # export PROHIBIT_BUILDING=0 18 | 19 | #endregion 20 | 21 | 22 | #region Optional version sticker prefix and/or suffix 23 | 24 | # export VERSION_STICKER_PREFIX="LOCAL-BETA-" 25 | # export VERSION_STICKER_SUFFIX="-BETA" 26 | 27 | #endregion 28 | 29 | 30 | #region Development environment 31 | 32 | ### ----------------------- 33 | ### development environment 34 | ### ----------------------- 35 | 36 | # ### owner of Docker Hub repos 37 | # export REPO_OWNER_NAME="" 38 | # ### development builder gist 39 | # export GIST_ID="" 40 | # ### development deployment gist 41 | # export DEPLOY_GIST_ID="" 42 | # ### note that the reserved repository name 'void' will prohibit the publishing 43 | # ### primary deployment repos may not exist (may be also left unset) 44 | # export DEPLOYMENT_REPO="" 45 | # export DEPLOYMENT_REPO_CHROMIUM="" 46 | # export DEPLOYMENT_REPO_FIREFOX="" 47 | # ### builder repo can be a secondary deployment repo (if FORCE_PUBLISHING_BUILDER_REPO=1) 48 | # export BUILDER_REPO="" 49 | # ### shared g3-cache is outside the Docker building context 50 | # export SHARED_G3_CACHE_PATH="" 51 | # ### used to control building/publishing (unset means '0') 52 | # export FORCE_PUBLISHING_BUILDER_REPO=1 53 | # export FORCE_BUILDING=1 54 | # ### used by the 'post_push' hook script, which normally removes the helper files 55 | # # export KEEP_HELPER_FILES=0 56 | # ### explicitly disable features that are enabled by default 57 | # # export FEATURES_NOVNC=0 58 | # # export FEATURES_FIREFOX_PLUS=0 59 | # # export FEATURES_OVERRIDING_ENVV=0 60 | # ### ignoring 'wget' checking may be helpful on Windows 61 | # # export IGNORE_MISSING_WGET=1 62 | 63 | #endregion 64 | 65 | 66 | #region Production environment 67 | 68 | ### ---------------------- 69 | ### production environment 70 | ### ---------------------- 71 | 72 | # ### owner of Docker Hub repos 73 | # export REPO_OWNER_NAME="" 74 | # ### production builder gist 75 | # export GIST_ID="" 76 | # ### production deployment gist 77 | # export DEPLOY_GIST_ID="" 78 | # ### note that the reserved repository name 'void' will prohibit the publishing 79 | # ### primary deployment repos 80 | # export DEPLOYMENT_REPO="" 81 | # export DEPLOYMENT_REPO_CHROMIUM="" 82 | # export DEPLOYMENT_REPO_FIREFOX="" 83 | # ### builder repo can be a secondary deployment repo (if FORCE_PUBLISHING_BUILDER_REPO=1) 84 | # export BUILDER_REPO="" 85 | # ### shared g3-cache is outside the Docker building context 86 | # export SHARED_G3_CACHE_PATH="" 87 | # ### used to control building/publishing (unset means '0') 88 | # export FORCE_PUBLISHING_BUILDER_REPO=1 89 | # export FORCE_BUILDING=1 90 | # ### used by the 'post_push' hook script, which normally removes the helper files 91 | # export KEEP_HELPER_FILES=0 92 | # ### explicitly disable features that are enabled by default 93 | # # export FEATURES_NOVNC=0 94 | # # export FEATURES_FIREFOX_PLUS=0 95 | # # export FEATURES_OVERRIDING_ENVV=0 96 | # ### ignoring 'wget' checking may be helpful on Windows 97 | # # export IGNORE_MISSING_WGET=1 98 | 99 | #endregion 100 | 101 | 102 | #region Real secrets 103 | 104 | ### ------------ 105 | ### REAL SECRETS 106 | ### ------------ 107 | 108 | ### !!! REAL SECRET !!! 109 | ### GitHub: Settings/Developer settings/Personal access tokens 110 | ### this PAT must have the 'gist' scope 111 | ### warning! this gist token is valid for all gists of the same owner! 112 | # export GIST_TOKEN="" 113 | 114 | ### !!! REAL SECRETS !!! 115 | ### Docker Hub credentials 116 | ### warning! this credentials are valid for all Docker Hub repositories of the same owner! 117 | # export DOCKERHUB_USERNAME="" 118 | # export DOCKERHUB_PASSWORD="" 119 | 120 | #endregion 121 | -------------------------------------------------------------------------------- /examples/example.yml: -------------------------------------------------------------------------------- 1 | # docker compose -f example.yml -p example up -d 2 | # docker compose -f example.yml -p example down --volumes 3 | 4 | ### This example shows how to switch to another non-root user 5 | ### and how to set the VNC password (to an empty one) and VNC resolution. 6 | 7 | version: '3' 8 | 9 | services: 10 | test: 11 | image: accetto/ubuntu-vnc-xfce-g3:extended 12 | # environment: 13 | # - VNC_PW= 14 | # - VNC_RESOLUTION=1024x768 15 | ports: 16 | - ":5901" 17 | - ":6901" 18 | user: "2000:3000" 19 | -------------------------------------------------------------------------------- /readme-builder.md: -------------------------------------------------------------------------------- 1 | # Utility `builder.sh` 2 | 3 | - [Utility `builder.sh`](#utility-buildersh) 4 | - [Introduction](#introduction) 5 | - [Preparation](#preparation) 6 | - [Ensure file attributes after cloning](#ensure-file-attributes-after-cloning) 7 | - [Set environment variables before building](#set-environment-variables-before-building) 8 | - [Ensure `wget` utility](#ensure-wget-utility) 9 | - [Executing complete pipeline](#executing-complete-pipeline) 10 | - [Executing individual pipeline steps](#executing-individual-pipeline-steps) 11 | - [What about the 'cache' helper script](#what-about-the-cache-helper-script) 12 | - [Additional building parameters](#additional-building-parameters) 13 | - [Helper commands for specific scenarios](#helper-commands-for-specific-scenarios) 14 | 15 | ## Introduction 16 | 17 | This utility script can build and publish individual images. 18 | It can also execute the individual hook scripts of the building pipeline (`docker/hooks` folder). 19 | 20 | Common usage pattern: 21 | 22 | ```shell 23 | ./builder.sh [build-options] 24 | ``` 25 | 26 | The supported option values can be taken from the embedded help: 27 | 28 | ```shell 29 | This script can: 30 | - build and publish the individual images 31 | - execute the individual hook scripts of the building pipeline '/docker/hooks/' 32 | - refresh the local builder 'g3-cache' 33 | 34 | Usage: ./builder.sh [] 35 | 36 | blend := (latest|noble|24.04|jammy|22.04|focal|20.04)[-chromium|-firefox] 37 | command := (all|all-no-push)|(pre_build|build|push|post_push|cache) 38 | 39 | The (e.g. '--no-cache') are passed to the Docker CLI commands used internally. 40 | 41 | The script creates a complete execution log. 42 | ``` 43 | 44 | The `` are passed to the Docker CLI commands used internally depending on the usage mode (see below). 45 | 46 | ## Preparation 47 | 48 | ### Ensure file attributes after cloning 49 | 50 | It may be necessary to repair the executable files attributes after cloning the repository (by `git clone`). 51 | 52 | You can do that by executing the following commands from the project's root directory: 53 | 54 | ```shell 55 | find . -type f -name "*.sh" -exec chmod +x '{}' \; 56 | chmod +x docker/hooks/* 57 | ``` 58 | 59 | For example, if the files in the folder `docker/hooks` would not be executable, then you would get errors similar to this: 60 | 61 | ```shell 62 | $ ./builder.sh latest build 63 | 64 | ==> EXECUTING @2023-03-05_16-42-57: ./builder.sh 65 | 66 | ./builder.sh: line 84: ./docker/hooks/build: Permission denied 67 | ``` 68 | 69 | ### Set environment variables before building 70 | 71 | Open a terminal windows and change the current directory to the root of the project (where the license file is). 72 | 73 | Make a copy of the secrets example file, modify it and then source it in the terminal: 74 | 75 | ```shell 76 | ### make a copy and then modify it 77 | cp examples/example-secrets.rc secrets.rc 78 | 79 | ### source the secrets 80 | source ./secrets.rc 81 | 82 | ### or also 83 | 84 | . ./secrets.rc 85 | ``` 86 | 87 | **TIP**: If you copy a file named `secrets.rc` into the folder `docker/hooks/`, then it will be automatically sourced by the hook script `env.rc`. 88 | 89 | Be aware that the following environment variables are mandatory and must be always set: 90 | 91 | - `REPO_OWNER_NAME` 92 | - `BUILDER_REPO` 93 | 94 | Ensure that your `secrets.rc` file contains at least the lines similar to these: 95 | 96 | ```shell 97 | export REPO_OWNER_NAME="accetto" 98 | export BUILDER_REPO="headless-ubuntu-g3" 99 | ``` 100 | 101 | You can use your own names if you wish. 102 | 103 | Alternatively you can modify the hook script file env.rc like this: 104 | 105 | ```shell 106 | ### original lines 107 | declare _owner="${REPO_OWNER_NAME:?Need repo owner name}" 108 | DOCKER_REPO="${_owner}/${BUILDER_REPO:?Need builder repo name}" 109 | 110 | ### modified lines 111 | declare _owner="${REPO_OWNER_NAME:-accetto}" 112 | DOCKER_REPO="${_owner}/${BUILDER_REPO:-headless-ubuntu-g3}" 113 | ``` 114 | 115 | Again, you can use your own names if you wish. 116 | 117 | You can also use other ways to set the variables. 118 | 119 | ### Ensure `wget` utility 120 | 121 | If you are on Windows, you can encounter the problem of missing `wget` utility. 122 | It is used by refreshing the `g3-cache` and it's available on Linux by default. 123 | 124 | On Windows you have generally two choices. 125 | You can build your images inside the `WSL` environment or you can download the `wget.exe` application for Windows. 126 | Make sure to update also the `PATH` environment variable appropriately. 127 | 128 | Since the version `25.04` the availability of the utility is checked. 129 | 130 | The checking can be skipped by setting the environment variable `IGNORE_MISSING_WGET=1`. 131 | 132 | The selected packages still will be downloaded into a temporary image layer, but not into the project's 133 | `.g3-cache` folder nor the shared one, defined by the variable `SHARED_G3_CACHE_PATH`. 134 | 135 | ## Executing complete pipeline 136 | 137 | Building the individual images and publishing them to the **Docker Hub**: 138 | 139 | ```shell 140 | ### PWD = project's root directory 141 | 142 | ### ubuntu-vnc-xfce-g3 143 | ./builder.sh latest all 144 | 145 | ### ubuntu-vnc-xfce-chromium-g3 146 | ./builder.sh latest-chromium all 147 | 148 | ### ubuntu-vnc-xfce-firefox-g3 149 | ./builder.sh latest-firefox all 150 | ``` 151 | 152 | You can skip the publishing to the **Docker Hub** by replacing the command `all` by the command `all-no-push`: 153 | 154 | ```shell 155 | ./builder.sh latest all-no-push 156 | ``` 157 | 158 | You can also provide additional parameters for the internally used Docker `build` command. 159 | For example: 160 | 161 | ```shell 162 | ./builder.sh latest all-no-push --no-cache 163 | 164 | ### it results in 165 | ### docker build --no-cache ... 166 | ``` 167 | 168 | The optional `` are passed only to the `pre_build` hook script, which passes them to the internally used `docker build` command. 169 | The `cache` hook script, however, doesn't use any Docker CLI commands. 170 | 171 | ## Executing individual pipeline steps 172 | 173 | The building pipeline consists of the following steps, that can be executed also individually: 174 | 175 | ```shell 176 | ### This step builds the helper image and compares its verbose version sticker to the one 177 | ### from the builder repository gist. 178 | ### It also refreshes the 'g3-cache' by executing the 'cache' hook script. 179 | ### The helper image is not deleted because it'll be used in the next step. 180 | ./builder.sh latest pre_build 181 | 182 | ### This step builds a new image depending on the comparison result from the previous step. 183 | ### If you want to force the building in any case, then delete the file 'scrap-demand-stop-building' 184 | ### or set the environment variable 'FORCE_BUILDING=1'. 185 | ### The helper image, built in the previous step, is used as an external cache and then deleted. 186 | ./builder.sh latest build 187 | 188 | ### This step publishes the image to the deployment repository on the Docker Hub. 189 | ### There are actually more configurations possible. Check the Wiki for the description. 190 | ./builder.sh latest push 191 | 192 | ### This step updates the gists that store off-line data like badge endpoints or version stickers. 193 | ### Note that it will not publish the README file to the Docker Hub. 194 | ./builder.sh latest post_push 195 | ``` 196 | 197 | The optional `` are passed to the each individual hook script, which can pass them to the internally used Docker CLI command. 198 | The `cache` hook script, however, doesn't use any Docker CLI commands. 199 | 200 | ### What about the 'cache' helper script 201 | 202 | The `cache` hook script has been introduced in the **second version** (G3v2) of the building pipeline. 203 | It refreshes the local `g3-cache`, which must be always placed inside the Docker build context. 204 | The script is also used by the `pre_build` and `build` hook scripts. 205 | 206 | The `g3-cache` and the rules for its refreshing are described separately. 207 | 208 | The script can be also used as a quick check, if there are newer versions of the following packages that are downloaded from external sources: 209 | 210 | - `TigerVNC` 211 | - `noVNC` 212 | - `websockify` 213 | - `Chromium Browser` 214 | 215 | The script will refresh only the packages that are required for the current build: 216 | 217 | ```shell 218 | ### this will refresh only 'TigerVNC', 'noVNC' and 'websockify' 219 | ./builder.sh latest cache 220 | ./builder.sh latest-firefox cache 221 | 222 | ### this will refresh also 'Chromium Browser' 223 | ./builder.sh latest-chromium cache 224 | ``` 225 | 226 | ## Additional building parameters 227 | 228 | The script `builder.sh` passes the additional parameters, that come after the mandatory ones, to the hook scripts in the folder `docker/hooks`. 229 | 230 | For example: 231 | 232 | ```shell 233 | ./builder.sh latest build --target stage_xfce --no-cache 234 | ``` 235 | 236 | The additional parameters `--target stage_xfce --no-cache` will be passed to the script `docker/hooks/build`. 237 | 238 | See the file [readme-local-building-example][this-readme-local-building-example] for more information about handling of the additional building parameters. 239 | 240 | ## Helper commands for specific scenarios 241 | 242 | There has been a case when it was necessary to update the badges of all repositories because of switching from the **badgen.net** provider to the **shields.io** one. 243 | 244 | Therefore the **Release 25.05 (G3v8)** has introduced a new hook script called `helper` and also the following new `ci-builder.sh` commands: 245 | 246 | - list 247 | - pull 248 | - helper-help 249 | - update-gists 250 | 251 | Most of the commands are forwarded to the new `helper` hook script, only the `update-gists` command is forwarded to the updated `post_push` hook script. 252 | It's all implemented in the procedure `build_single_image()`. 253 | 254 | The actual gist update is implemented in the hook script `util.rc`, which has been also updated. Up to 3 gist update retries have also been added. 255 | 256 | The new commands are intended for the building utility script `ci-builder.sh` and therefore they are described in the file `readme-ci-builder.md`. 257 | 258 | *** 259 | 260 | [this-readme-local-building-example]: https://github.com/accetto/ubuntu-vnc-xfce-g3/blob/master/readme-local-building-example.md 261 | -------------------------------------------------------------------------------- /readme-g3-cache.md: -------------------------------------------------------------------------------- 1 | # Custom `g3-cache` 2 | 3 | - [Custom `g3-cache`](#custom-g3-cache) 4 | - [Introduction](#introduction) 5 | - [Ensure `wget` utility](#ensure-wget-utility) 6 | - [Local `g3-cache`](#local-g3-cache) 7 | - [Shared g3-cache](#shared-g3-cache) 8 | - [Helper script `cache`](#helper-script-cache) 9 | 10 | ## Introduction 11 | 12 | The custom `g3-cache` has been introduced in the **second version** (G3v2) of the project. 13 | 14 | The local `g3-cache` is an additional cache used by the building pipeline and it should not be confused with the **Docker builder cache** maintained by the [Docker Build][docker-doc-docker-build] itself. 15 | 16 | The `g3-cache` stores the selected pre-downloaded packages used by the Dockerfiles, that would be otherwise repeatedly downloaded from the external sources by each build. 17 | 18 | It results in a significantly higher performance by building sets of images or by repeated builds. 19 | 20 | You can learn more about the concept on the Wiki page ["Concepts of `g3-cache`"][this-wiki-concepts-of-g3-cache] and about the implementation on the Wiki page ["How `g3-cache` works"][this-wiki-how-g3-cache-works]. 21 | 22 | ### Ensure `wget` utility 23 | 24 | If you are on Windows, you can encounter the problem of missing `wget` utility. 25 | It is used by refreshing the `g3-cache` and it's available on Linux by default. 26 | 27 | On Windows you have generally two choices. 28 | You can build your images inside the `WSL` environment or you can download the `wget.exe` application for Windows. 29 | Make sure to update also the `PATH` environment variable appropriately. 30 | 31 | Since the version `25.04` the availability of the utility is checked. 32 | 33 | The checking can be skipped by setting the environment variable `IGNORE_MISSING_WGET=1`. 34 | 35 | The selected packages still will be downloaded into a temporary image layer, but not into the project's 36 | `.g3-cache` folder nor the shared one, defined by the variable `SHARED_G3_CACHE_PATH`. 37 | 38 | ## Local `g3-cache` 39 | 40 | The local `g3-cache` of this project has the following **cache sections**: 41 | 42 | - `chromium` 43 | - `novnc` 44 | - `tigervnc` 45 | - `websockify` 46 | 47 | The local `g3-cache` folder `docker/.g3-cache` is excluded from the commits into the `git` repository by the means of the `.gitignore` file. 48 | 49 | You can delete the local `g3-cache` folder any time, because it will be re-created each time you build an image. 50 | 51 | ## Shared g3-cache 52 | 53 | The absolute path to the root folder of the shared `g3-cache` should be set as the value of the environment variable `SHARED_G3_CACHE_PATH`. 54 | 55 | The same shared `g3-cache` is usually used also by the sibling projects [accetto/headless-drawing-g3][accetto-github-headless-drawing-g3] and [accetto/headless-coding-g3][accetto-github-headless-coding-g3]. 56 | 57 | ## Helper script `cache` 58 | 59 | Both `g3-caches` are refreshed by the helper script `cache`, which is stored in the folder `docker/hooks/`. 60 | Therefore it's sometimes referenced as a hook script. 61 | 62 | The script is used by the hook scripts `pre_build` and `build`. 63 | However, it can be executed also stand-alone. 64 | 65 | Since the version `G3v8` (Release `25.05`) the updated script checks if the shared `g3-cache` directory, defined by the environment variable `SHARED_G3_CACHE_PATH`, is reachable and writable. 66 | The shared `g3-cache` update will be skipped otherwise. 67 | 68 | **Remark**: The current implementation of the cache refreshing code is not thread safe and it is not intended for parallel building of multiple images. 69 | 70 | *** 71 | 72 | [this-wiki-concepts-of-g3-cache]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki/Concepts-of-g3-cache 73 | [this-wiki-how-g3-cache-works]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki/How-g3-cache-works 74 | 75 | [accetto-github-headless-coding-g3]:https://github.com/accetto/headless-coding-g3 76 | [accetto-github-headless-drawing-g3]: https://github.com/accetto/headless-drawing-g3 77 | 78 | [docker-doc-docker-build]: https://docs.docker.com/develop/develop-images/build_enhancements/ 79 | -------------------------------------------------------------------------------- /utils/readme-util-readme-examples.md: -------------------------------------------------------------------------------- 1 | # Examples `util-readme.sh` 2 | 3 | ## Preparation 4 | 5 | Open a terminal window and change the current directory to `utils/`. 6 | 7 | The utility requires the `ID` of the deployment **GitHub Gist**, which you can provide as a parameter or by setting the environment variable `DEPLOY_GIST_ID`: 8 | 9 | ```shell 10 | export DEPLOY_GIST_ID="" 11 | ``` 12 | 13 | Embedded help describes the parameters: 14 | 15 | ```shell 16 | ./util-readme.sh -h 17 | ``` 18 | 19 | ## Usage examples 20 | 21 | ```shell 22 | ### PWD = utils/ 23 | 24 | ./util-readme.sh --repo accetto/ubuntu-vnc-xfce-g3 --context=../docker/xfce --gist -- preview 25 | 26 | ./util-readme.sh --repo accetto/ubuntu-vnc-xfce-chromium-g3 --context=../docker/xfce-chromium --gist -- preview 27 | 28 | ./util-readme.sh --repo accetto/ubuntu-vnc-xfce-firefox-g3 --context=../docker/xfce-firefox --gist -- preview 29 | 30 | ### or if the environment variable 'DEPLOY_GIST_ID' has been set 31 | 32 | ./util-readme.sh --repo accetto/ubuntu-vnc-xfce-g3 --context=../docker/xfce -- preview 33 | 34 | ./util-readme.sh --repo accetto/ubuntu-vnc-xfce-chromium-g3 --context=../docker/xfce-chromium -- preview 35 | 36 | ./util-readme.sh --repo accetto/ubuntu-vnc-xfce-firefox-g3 --context=../docker/xfce-firefox -- preview 37 | ``` 38 | 39 | See the Wiki page ["Utility util-readme.sh"][this-wiki-utility-util-readme] for more information. 40 | 41 | *** 42 | 43 | [this-wiki-utility-util-readme]: https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki/Utility-util-readme 44 | -------------------------------------------------------------------------------- /utils/util-readme.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash -e 2 | 3 | ### @accetto, December 2020 4 | ### https://github.com/accetto/ubuntu-vnc-xfce-g3 5 | ### https://github.com/accetto/ubuntu-vnc-xfce-g3/wiki 6 | 7 | # ARG_VERSION([echo $0 v22.11.04]) 8 | # ARG_HELP([Utility for previewing README files intended for Docker Hub. The prepared files can be manually copy-and-pasted to Docker Hub. The utility should be run from the '/utils' directory.]) 9 | # 10 | # ARG_POSITIONAL_SINGLE([command],[Command to execute. Available commands: \n \ 11 | # cleanup - Deletes the previously generated README preview and other helper files. \n \ 12 | # This is the default command if both and are empty. \n \ 13 | # preview - Generates the README preview file and checks its length. \n \ 14 | # This is the default command if is empty, but is not. \n \ 15 | #],[""]) 16 | # 17 | # ARG_DEFAULTS_POS([]) 18 | # ARG_POSITIONAL_DOUBLEDASH([]) 19 | # 20 | # ARG_OPTIONAL_SINGLE([repo],[],[Target Docker Hub repository (owner/repo)],[""]) 21 | # ARG_OPTIONAL_SINGLE([context],[],[Path to the readme files (relative to '/utils', e.g. '../docker/xfce')],[""]) 22 | # ARG_OPTIONAL_SINGLE([readme],[],[Readme file main part name],[README-dockerhub.md]) 23 | # ARG_OPTIONAL_SINGLE([template],[],[Readme appendix template file name],[readme-append.template]) 24 | # ARG_OPTIONAL_SINGLE([limit],[],[Max. length of the final README file in bytes (max. 25000)],[25000]) 25 | # ARG_OPTIONAL_SINGLE([gist],[],[Gist ID containing off-line metadata (e.g. badge endpoints)(alternatively set 'DEPLOY_GIST_ID' environment variable)]) 26 | # 27 | # ARGBASH_GO() 28 | # needed because of Argbash --> m4_ignore([ 29 | ### START OF CODE GENERATED BY Argbash v2.10.0 one line above ### 30 | # Argbash is a bash code generator used to get arguments parsing right. 31 | # Argbash is FREE SOFTWARE, see https://argbash.dev for more info 32 | 33 | 34 | die() 35 | { 36 | local _ret="${2:-1}" 37 | test "${_PRINT_HELP:-no}" = yes && print_help >&2 38 | echo "$1" >&2 39 | exit "${_ret}" 40 | } 41 | 42 | 43 | begins_with_short_option() 44 | { 45 | local first_option all_short_options='vh' 46 | first_option="${1:0:1}" 47 | test "$all_short_options" = "${all_short_options/$first_option/}" && return 1 || return 0 48 | } 49 | 50 | # THE DEFAULTS INITIALIZATION - POSITIONALS 51 | _positionals=() 52 | _arg_command="" 53 | # THE DEFAULTS INITIALIZATION - OPTIONALS 54 | _arg_repo="" 55 | _arg_context="" 56 | _arg_readme="README-dockerhub.md" 57 | _arg_template="readme-append.template" 58 | _arg_limit="25000" 59 | _arg_gist= 60 | 61 | 62 | print_help() 63 | { 64 | printf '%s\n' "Utility for previewing README files intended for Docker Hub. The prepared files can be manually copy-and-pasted to Docker Hub. The utility should be run from the '/utils' directory." 65 | printf 'Usage: %s [-v|--version] [-h|--help] [--repo ] [--context ] [--readme ] [--template ] [--limit ] [--gist ] [--] []\n' "$0" 66 | printf '\t%s\n' ": Command to execute. Available commands: 67 | \ 68 | # cleanup - Deletes the previously generated README preview and other helper files. 69 | \ 70 | # This is the default command if both and are empty. 71 | \ 72 | # preview - Generates the README preview file and checks its length. 73 | \ 74 | # This is the default command if is empty, but is not. 75 | \ 76 | # (default: '""')" 77 | printf '\t%s\n' "-v, --version: Prints version" 78 | printf '\t%s\n' "-h, --help: Prints help" 79 | printf '\t%s\n' "--repo: Target Docker Hub repository (owner/repo) (default: '""')" 80 | printf '\t%s\n' "--context: Path to the readme files (relative to '/utils', e.g. '../docker/xfce') (default: '""')" 81 | printf '\t%s\n' "--readme: Readme file main part name (default: 'README-dockerhub.md')" 82 | printf '\t%s\n' "--template: Readme appendix template file name (default: 'readme-append.template')" 83 | printf '\t%s\n' "--limit: Max. length of the final README file in bytes (max. 25000) (default: '25000')" 84 | printf '\t%s\n' "--gist: Gist ID containing off-line metadata (e.g. badge endpoints)(alternatively set 'DEPLOY_GIST_ID' environment variable) (no default)" 85 | } 86 | 87 | 88 | parse_commandline() 89 | { 90 | _positionals_count=0 91 | while test $# -gt 0 92 | do 93 | _key="$1" 94 | if test "$_key" = '--' 95 | then 96 | shift 97 | test $# -gt 0 || break 98 | _positionals+=("$@") 99 | _positionals_count=$((_positionals_count + $#)) 100 | shift $(($# - 1)) 101 | _last_positional="$1" 102 | break 103 | fi 104 | case "$_key" in 105 | -v|--version) 106 | echo $0 v22.11.04 107 | exit 0 108 | ;; 109 | -v*) 110 | echo $0 v22.11.04 111 | exit 0 112 | ;; 113 | -h|--help) 114 | print_help 115 | exit 0 116 | ;; 117 | -h*) 118 | print_help 119 | exit 0 120 | ;; 121 | --repo) 122 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 123 | _arg_repo="$2" 124 | shift 125 | ;; 126 | --repo=*) 127 | _arg_repo="${_key##--repo=}" 128 | ;; 129 | --context) 130 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 131 | _arg_context="$2" 132 | shift 133 | ;; 134 | --context=*) 135 | _arg_context="${_key##--context=}" 136 | ;; 137 | --readme) 138 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 139 | _arg_readme="$2" 140 | shift 141 | ;; 142 | --readme=*) 143 | _arg_readme="${_key##--readme=}" 144 | ;; 145 | --template) 146 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 147 | _arg_template="$2" 148 | shift 149 | ;; 150 | --template=*) 151 | _arg_template="${_key##--template=}" 152 | ;; 153 | --limit) 154 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 155 | _arg_limit="$2" 156 | shift 157 | ;; 158 | --limit=*) 159 | _arg_limit="${_key##--limit=}" 160 | ;; 161 | --gist) 162 | test $# -lt 2 && die "Missing value for the optional argument '$_key'." 1 163 | _arg_gist="$2" 164 | shift 165 | ;; 166 | --gist=*) 167 | _arg_gist="${_key##--gist=}" 168 | ;; 169 | *) 170 | _last_positional="$1" 171 | _positionals+=("$_last_positional") 172 | _positionals_count=$((_positionals_count + 1)) 173 | ;; 174 | esac 175 | shift 176 | done 177 | } 178 | 179 | 180 | handle_passed_args_count() 181 | { 182 | test "${_positionals_count}" -le 1 || _PRINT_HELP=yes die "FATAL ERROR: There were spurious positional arguments --- we expect between 0 and 1, but got ${_positionals_count} (the last one was: '${_last_positional}')." 1 183 | } 184 | 185 | 186 | assign_positional_args() 187 | { 188 | local _positional_name _shift_for=$1 189 | _positional_names="_arg_command " 190 | 191 | shift "$_shift_for" 192 | for _positional_name in ${_positional_names} 193 | do 194 | test $# -gt 0 || break 195 | eval "$_positional_name=\${1}" || die "Error during argument parsing, possibly an Argbash bug." 1 196 | shift 197 | done 198 | } 199 | 200 | parse_commandline "$@" 201 | handle_passed_args_count 202 | assign_positional_args 1 "${_positionals[@]}" 203 | 204 | # OTHER STUFF GENERATED BY Argbash 205 | 206 | ### END OF CODE GENERATED BY Argbash (sortof) ### ]) 207 | # [ <-- needed because of Argbash 208 | 209 | ### ##################### 210 | ### USER CODE BEGINS HERE 211 | ### ##################### 212 | 213 | dump_args() { 214 | 215 | printf "Value of '%s': %s\\n" 'command' "${_arg_command}" 216 | printf "Value of '%s': %s\\n" 'repo' "${_arg_repo}" 217 | printf "Value of '%s': %s\\n" 'context' "${_arg_context}" 218 | printf "Value of '%s': %s\\n" 'readme' "${_arg_readme}" 219 | printf "Value of '%s': %s\\n" 'template' "${_arg_template}" 220 | printf "Value of '%s': %s\\n" 'limit' "${_arg_limit}" 221 | printf "Value of '%s': %s\\n" 'gist' "${_arg_gist}" 222 | } 223 | 224 | do_cleanup() { 225 | 226 | rm -f "${_scrap_append_file}" "${_readme_upload_file}" 227 | echo "Cleanup finished." 228 | } 229 | 230 | do_preview() { 231 | 232 | local repo="${_arg_repo}" 233 | local readme_context="${_arg_context}" 234 | local readme_main="${_arg_readme}" 235 | local readme_append="${_arg_template}" 236 | local gist="${_arg_gist:-${DEPLOY_GIST_ID}}" 237 | 238 | local readme_append_file 239 | local readme_main_file 240 | local repo_name 241 | local repo_owner 242 | 243 | local -i size 244 | local -i delta 245 | 246 | if [[ -z ${_arg_repo} ]] ; then 247 | 248 | die "Repository (owner/repo) must be provided." 249 | fi 250 | 251 | if [[ -z "${readme_context}" ]] ; then 252 | 253 | die "Readme context must be provided." 254 | fi 255 | 256 | if [[ -z "${readme_main}" ]] ; then 257 | 258 | die "Readme main part file name must be provided." 259 | fi 260 | 261 | readme_main_file="${readme_context}/${readme_main}" 262 | 263 | if [[ ! -f "${readme_main_file}" ]] ; then 264 | 265 | die "Missing readme main part file: '${readme_main_file}' " 266 | fi 267 | 268 | ### readme appendix template is optional 269 | if [[ -n "${readme_append}" ]] ; then 270 | 271 | readme_append_file="${readme_context}/${readme_append}" 272 | 273 | if [[ ! -f "${readme_append_file}" ]] ; then 274 | 275 | die "Missing readme appendix template file: '${readme_append_file}' " 276 | fi 277 | 278 | if [[ -z "${gist}" ]] ; then 279 | 280 | die "Deployment gist ID must provided as a parameter or 'DEPLOY_GIST_ID' environment variable!" 281 | fi 282 | fi 283 | 284 | ### extract the repo owner and its name 285 | ### alternative 1 286 | repo_name="$(basename $repo)" 287 | repo_owner="$(basename $(dirname ${repo}))" 288 | ### alternative 2 289 | # repo_name="${repo##*/}" 290 | # repo_owner="${repo%$repo_name}" ; repo_owner="${repo_owner::-1}" ; repo_owner="${repo_owner##*/}" 291 | ### also ensure that the deployment repo has only two parts like 'repo_owner/repo_name' 292 | # _deployment_repo="$(basename $(dirname ${repo}))/$(basename ${repo})" 293 | _deployment_repo="${repo_owner}/${repo_name}" 294 | 295 | ### create the actual README file for Docker Hub by replacing the variables in the append-template (badge links) 296 | ### and appending it to the main-readme partial file 297 | ### it is expected that the readme include template contains the following variables: 298 | ### ${OWNER} - owner of the deployment repository and also the related deployment gist 299 | ### ${GIST} - gist containing the badge endpoints 300 | ### ${REPO} - name of the deployment repository 301 | 302 | ### readme appendix templating is optional 303 | if [[ -n "${readme_append}" ]] ; then 304 | 305 | ### replace the environment variables in the template 306 | ( OWNER="${repo_owner}" GIST="${gist}" REPO="${repo_name}" envsubst < "${readme_append_file}" > "${_scrap_append_file}" ) 307 | 308 | ### append the updated template to the main readme part 309 | cat "${readme_main_file}" "${_scrap_append_file}" > "${_readme_upload_file}" 310 | rm -f "${_scrap_append_file}" 311 | else 312 | ### no appendix and no templating 313 | cp "${readme_main_file}" "${_readme_upload_file}" 314 | fi 315 | 316 | echo "Readme preview: ${_readme_upload_file} " 317 | 318 | size=$( wc --bytes "${_readme_upload_file}" | awk '{print $1}' ) 319 | delta=$((_arg_limit-size)) 320 | echo "Readme length is ${size} bytes, leaving ${delta} bytes available (max. ${_arg_limit}). " 321 | 322 | } 323 | 324 | main() { 325 | 326 | ### just debugging support 327 | # dump_args 328 | case ${_arg_command,,} in 329 | 330 | cleanup ) 331 | do_cleanup "${_scrap_append_file}" "${_readme_upload_file}" 332 | ;; 333 | 334 | preview ) 335 | do_cleanup "${_scrap_append_file}" "${_readme_upload_file}" 336 | do_preview 337 | ;; 338 | 339 | * ) 340 | if [[ -z "${_arg_command}" ]] ; then 341 | 342 | if [[ -z "${_arg_repo}" ]] ; then 343 | 344 | do_cleanup 345 | else 346 | do_preview 347 | fi 348 | else 349 | die "Unsupported command '${_arg_command}' " 350 | fi 351 | ;; 352 | esac 353 | } 354 | 355 | ### ################ 356 | ### MAIN ENTRY POINT 357 | ### ################ 358 | 359 | declare _current_dir 360 | declare _deployment_repo 361 | declare _readme_upload_file 362 | declare _scrap_append_file 363 | 364 | _current_dir=$(dirname $0) 365 | 366 | _scrap_append_file="${_current_dir}/scrap-append.tmp" 367 | _readme_upload_file="${_current_dir}/scrap-readme.md" 368 | 369 | main 370 | 371 | # ] <-- needed because of Argbash 372 | --------------------------------------------------------------------------------