# syntax=docker/dockerfile:experimental ARG BASEIMAGE=debian ARG BASETAG=11-slim ARG ARG_MERGE_STAGE_VNC_BASE=stage_vnc ARG ARG_MERGE_STAGE_BROWSER_BASE=merge_stage_vnc ARG ARG_FINAL_STAGE_BASE=merge_stage_browser ARG ARG_HEADLESS_USER_ID=1000 ARG ARG_HEADLESS_USER_NAME=headless ARG ARG_HEADLESS_USER_GROUP_ID=1000 ARG ARG_HEADLESS_USER_GROUP_NAME=headless ARG ARG_SUDO_INITIAL_PW=headless ############### ### stage_cache ############### FROM ${BASEIMAGE}:${BASETAG} as stage_cache ### refresh the 'apt' cache RUN rm -f /etc/apt/apt.conf.d/docker-clean ; \ echo 'Binary::apt::APT::Keep-Downloaded-Packages "true" ;' > /etc/apt/apt.conf.d/keep-cache RUN apt-get update ### embed the local '.g3-cache' from the build context ### note that the bound cache '/tmp/cache2' is ephemeral and all written data will be discarded automatically ### therefore copy its content into the another permanent cache '/tmp/g3-cache' RUN \ --mount=type=bind,target=/tmp/cache2 \ mkdir -p /tmp/g3-cache \ && if [ -d /tmp/cache2/.g3-cache/ ] ; then cp -r /tmp/cache2/.g3-cache/* /tmp/g3-cache/ ; fi #################### ### stage_essentials #################### FROM ${BASEIMAGE}:${BASETAG} as stage_essentials RUN \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/cache/apt,target=/var/cache/apt \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/lib/apt,target=/var/lib/apt \ DEBIAN_FRONTEND=noninteractive apt-get install -y \ gir1.2-rsvg-2.0 \ jq \ nano \ procps \ psmisc \ sudo \ tini \ wget ################# ### stage_xserver ################# FROM stage_essentials as stage_xserver ARG ARG_APT_NO_RECOMMENDS ENV \ FEATURES_BUILD_SLIM_XSERVER="${ARG_APT_NO_RECOMMENDS:+1}" \ NO_AT_BRIDGE=1 RUN \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/cache/apt,target=/var/cache/apt \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/lib/apt,target=/var/lib/apt \ DEBIAN_FRONTEND=noninteractive apt-get install -y "${ARG_APT_NO_RECOMMENDS:+--no-install-recommends}" \ dbus-x11 \ xauth \ xinit \ x11-xserver-utils \ xdg-utils ############## ### stage_xfce ############## FROM stage_xserver as stage_xfce ARG ARG_APT_NO_RECOMMENDS ENV FEATURES_BUILD_SLIM_XFCE="${ARG_APT_NO_RECOMMENDS:+1}" RUN \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/cache/apt,target=/var/cache/apt \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/lib/apt,target=/var/lib/apt \ DEBIAN_FRONTEND=noninteractive apt-get install -y "${ARG_APT_NO_RECOMMENDS:+--no-install-recommends}" \ xfce4 \ xfce4-terminal ############### ### stage_tools ############### FROM stage_xfce as stage_tools ARG ARG_APT_NO_RECOMMENDS ARG ARG_FEATURES_SCREENSHOOTING ARG ARG_FEATURES_THUMBNAILING ENV \ FEATURES_BUILD_SLIM_TOOLS="${ARG_APT_NO_RECOMMENDS:+1}" \ FEATURES_SCREENSHOOTING="${ARG_FEATURES_SCREENSHOOTING:+1}" \ FEATURES_THUMBNAILING="${ARG_FEATURES_THUMBNAILING:+1}" RUN \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/cache/apt,target=/var/cache/apt \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/lib/apt,target=/var/lib/apt \ DEBIAN_FRONTEND=noninteractive apt-get install -y "${ARG_APT_NO_RECOMMENDS:+--no-install-recommends}" \ mousepad \ python3 \ systemctl \ "${ARG_FEATURES_SCREENSHOOTING:+ristretto}" \ "${ARG_FEATURES_SCREENSHOOTING:+xfce4-screenshooter}" \ "${ARG_FEATURES_THUMBNAILING:+tumbler}" ############# ### stage_vnc ############# FROM stage_tools as stage_vnc ARG ARG_VNC_COL_DEPTH ARG ARG_VNC_DISPLAY ARG ARG_VNC_PORT ARG ARG_VNC_PW ARG ARG_VNC_RESOLUTION ARG ARG_VNC_VIEW_ONLY ARG ARG_TIGERVNC_DISTRO ARG ARG_TIGERVNC_VERSION RUN \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/cache/apt,target=/var/cache/apt \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/lib/apt,target=/var/lib/apt \ --mount=type=cache,from=stage_cache,sharing=locked,source=/tmp/g3-cache/,target=/tmp/g3-cache/ \ TIGERVNC_VERSION="${ARG_TIGERVNC_VERSION}" \ TIGERVNC_DISTRO="${ARG_TIGERVNC_DISTRO}" \ && if [ ! -s /tmp/g3-cache/tigervnc/tigervnc-"${TIGERVNC_VERSION}"."${TIGERVNC_DISTRO}".tar.gz ] ; then \ wget --show-progress --progress=bar:force:noscroll \ -q https://sourceforge.net/projects/tigervnc/files/stable/"${TIGERVNC_VERSION}"/tigervnc-"${TIGERVNC_VERSION}"."${TIGERVNC_DISTRO}".tar.gz \ -P /tmp/g3-cache/tigervnc ; \ fi \ && tar xzf /tmp/g3-cache/tigervnc/tigervnc-"${TIGERVNC_VERSION}"."${TIGERVNC_DISTRO}".tar.gz --strip 1 -C / \ && ln -s /usr/libexec/vncserver /usr/bin/vncserver \ && sed -i 's/exec(@cmd);/print "@cmd";\nexec(@cmd);/g' /usr/libexec/vncserver ENV \ DISPLAY="${ARG_VNC_DISPLAY:-:1}" \ FEATURES_VNC=1 \ VNC_COL_DEPTH="${ARG_VNC_COL_DEPTH:-24}" \ VNC_PORT="${ARG_VNC_PORT:-5901}" \ VNC_PW="${ARG_VNC_PW:-headless}" \ VNC_RESOLUTION="${ARG_VNC_RESOLUTION:-1360x768}" \ VNC_VIEW_ONLY="${ARG_VNC_VIEW_ONLY:-false}" EXPOSE "${VNC_PORT}" ############### ### stage_novnc ############### FROM stage_vnc as stage_novnc ARG ARG_APT_NO_RECOMMENDS ARG ARG_NOVNC_PORT ARG ARG_NOVNC_VERSION ARG ARG_WEBSOCKIFY_VERSION ENV \ FEATURES_BUILD_SLIM_NOVNC="${ARG_APT_NO_RECOMMENDS:+1}" \ FEATURES_NOVNC=1 \ NOVNC_HOME="/usr/libexec/noVNCdim" \ NOVNC_PORT="${ARG_NOVNC_PORT:-6901}" RUN \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/cache/apt,target=/var/cache/apt \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/lib/apt,target=/var/lib/apt \ --mount=type=cache,from=stage_cache,sharing=locked,source=/tmp/g3-cache/,target=/tmp/g3-cache/ \ DEBIAN_FRONTEND=noninteractive apt-get install -y "${ARG_APT_NO_RECOMMENDS:+--no-install-recommends}" \ python3-numpy \ && mkdir -p "${NOVNC_HOME}"/utils/websockify \ && NOVNC_VERSION="${ARG_NOVNC_VERSION}" \ && WEBSOCKIFY_VERSION="${ARG_WEBSOCKIFY_VERSION}" \ && if [ ! -s /tmp/g3-cache/novnc/v"${NOVNC_VERSION}".tar.gz ] ; then \ wget --show-progress --progress=bar:force:noscroll \ -q https://github.com/novnc/noVNC/archive/v"${NOVNC_VERSION}".tar.gz \ -P /tmp/g3-cache/novnc ; \ fi \ && if [ ! -s /tmp/g3-cache/websockify/v"${WEBSOCKIFY_VERSION}".tar.gz ] ; then \ wget --show-progress --progress=bar:force:noscroll \ -q https://github.com/novnc/websockify/archive/v"${WEBSOCKIFY_VERSION}".tar.gz \ -P /tmp/g3-cache/websockify ; \ fi \ && tar xzf /tmp/g3-cache/novnc/v"${NOVNC_VERSION}".tar.gz --strip 1 -C "${NOVNC_HOME}" \ && tar xzf /tmp/g3-cache/websockify/v"${WEBSOCKIFY_VERSION}".tar.gz --strip 1 -C "${NOVNC_HOME}"/utils/websockify \ && chmod 755 -v "${NOVNC_HOME}"/utils/novnc_proxy ### add 'index.html' for choosing noVNC client RUN echo \ "\n\ \n\ \n\ noVNC\n\ \n\ \n\ \n\

noVNC Lite Client

\n\

noVNC Full Client

\n\ \n\ " \ > "${NOVNC_HOME}"/index.html EXPOSE "${NOVNC_PORT}" ################### ### merge_stage_vnc ################### FROM ${ARG_MERGE_STAGE_VNC_BASE} as merge_stage_vnc ARG ARG_HEADLESS_USER_ID ARG ARG_HEADLESS_USER_NAME ARG ARG_HEADLESS_USER_GROUP_ID ARG ARG_HEADLESS_USER_GROUP_NAME ENV \ HEADLESS_USER_ID="${ARG_HEADLESS_USER_ID}" \ HEADLESS_USER_NAME="${ARG_HEADLESS_USER_NAME}" \ HEADLESS_USER_GROUP_ID="${ARG_HEADLESS_USER_GROUP_ID}" \ HEADLESS_USER_GROUP_NAME="${ARG_HEADLESS_USER_GROUP_NAME}" \ HOME="${ARG_HOME:-/home/${ARG_HEADLESS_USER_NAME}}" WORKDIR "${HOME}" ################## ### stage_chromium ################## FROM merge_stage_vnc as stage_chromium ARG ARG_APT_NO_RECOMMENDS ENV \ FEATURES_BUILD_SLIM_CHROMIUM="${ARG_APT_NO_RECOMMENDS:+1}" \ FEATURES_CHROMIUM=1 RUN \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/cache/apt,target=/var/cache/apt \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/lib/apt,target=/var/lib/apt \ DEBIAN_FRONTEND=noninteractive apt-get install -y "${ARG_APT_NO_RECOMMENDS:+--no-install-recommends}" \ chromium COPY ./xfce-chromium/src/home/Desktop "${HOME}"/Desktop/ COPY ./xfce-chromium/src/home/readme*.md "${HOME}"/ ################# ### stage_firefox ################# FROM merge_stage_vnc as stage_firefox ARG ARG_APT_NO_RECOMMENDS ENV \ FEATURES_BUILD_SLIM_FIREFOX="${ARG_APT_NO_RECOMMENDS:+1}" \ FEATURES_FIREFOX=1 RUN \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/cache/apt,target=/var/cache/apt \ --mount=type=cache,from=stage_cache,sharing=locked,source=/var/lib/apt,target=/var/lib/apt \ DEBIAN_FRONTEND=noninteractive apt-get install -y "${ARG_APT_NO_RECOMMENDS:+--no-install-recommends}" \ firefox-esr COPY ./xfce-firefox/src/home/Desktop "${HOME}"/Desktop/ ### ################## ### stage_firefox_plus ### ################## FROM stage_firefox as stage_firefox_plus ENV FEATURES_FIREFOX_PLUS=1 COPY ./xfce-firefox/src/firefox.plus/home/Desktop "${HOME}"/Desktop/ COPY ./xfce-firefox/src/firefox.plus/resources "${HOME}"/firefox.plus/ COPY ./xfce-firefox/src/firefox.plus/home/readme*.md "${HOME}"/ RUN \ chmod 744 "${HOME}"/firefox.plus/*.sh \ && echo "Exec=${HOME}/firefox.plus/copy_firefox_user_preferences.sh" >> "${HOME}/Desktop/Copy FF Preferences.desktop" \ && install -o root -g root -m 644 "${HOME}"/firefox.plus/accetto.svg /usr/share/icons/hicolor/scalable/apps/ \ && gtk-update-icon-cache -f /usr/share/icons/hicolor ####################### ### merge_stage_browser ####################### FROM ${ARG_MERGE_STAGE_BROWSER_BASE} as merge_stage_browser ############### ### FINAL STAGE ############### FROM ${ARG_FINAL_STAGE_BASE} as stage_final ARG ARG_SUDO_INITIAL_PW ENV \ FEATURES_VERSION_STICKER=1 \ STARTUPDIR="/dockerstartup" COPY ./src/xfce-startup "${STARTUPDIR}"/ COPY ./src/tests "${HOME}"/tests/ COPY ./xfce/src/home/config "${HOME}"/.config/ COPY ./xfce/src/home/Desktop "${HOME}"/Desktop/ COPY ./xfce/src/home/readme*.md "${HOME}"/ ### Note that the line 'chmod 666 /etc/passwd /etc/group' sets the "softer" permissions only temporary. ### It allows the user generator startup script to configure the user and the group correctly. ### The script will set the permissions of both files back to the default '644'. ### The script will also clear the file '.initial_sudo_password' after using it. ### However, note that the initial sudo password will still be persisted in the image history. ### You have to change it inside the container, if you want to keep it really secret. ### Note that all this will not be done, if the startup script will not be executed. RUN \ chmod 666 /etc/passwd /etc/group \ && echo "${HEADLESS_USER_NAME}:x:${HEADLESS_USER_ID}:${HEADLESS_USER_GROUP_ID}:Default:${HOME}:/bin/bash" >> /etc/passwd \ && echo "${HEADLESS_USER_NAME} ALL=(ALL:ALL) ALL" | sudo tee /etc/sudoers.d/"${HEADLESS_USER_NAME}" \ && echo "${ARG_SUDO_INITIAL_PW:-headless}" > "${STARTUPDIR}"/.initial_sudo_password \ && echo "${HEADLESS_USER_NAME}:$(cat "${STARTUPDIR}"/.initial_sudo_password)" | chpasswd \ && ln -s "${HOME}"/readme.md "${HOME}"/Desktop/README \ && "${STARTUPDIR}"/set_user_permissions.sh "${STARTUPDIR}" "${HOME}" USER "${HEADLESS_USER_ID}" ENTRYPOINT [ "/usr/bin/tini", "--", "/dockerstartup/startup.sh" ] # RUN chmod 644 /etc/passwd /etc/group # ENTRYPOINT [ "/usr/bin/tini", "--", "tail", "-f", "/dev/null" ] ################## ### METADATA STAGE ################## FROM stage_final as stage_metadata ARG ARG_CREATED ARG ARG_DOCKER_TAG ARG ARG_VCS_REF ARG ARG_VERSION_STICKER LABEL \ org.opencontainers.image.authors="accetto" \ org.opencontainers.image.created="${ARG_CREATED}" \ org.opencontainers.image.description="Headless Debian/Xfce/VNC/noVNC containers with Internet browsers" \ org.opencontainers.image.documentation="https://github.com/accetto/debian-vnc-xfce-g3" \ org.opencontainers.image.source="https://github.com/accetto/debian-vnc-xfce-g3" \ org.opencontainers.image.title="accetto/debian-vnc-xfce-g3" \ org.opencontainers.image.url="https://github.com/accetto/debian-vnc-xfce-g3" \ org.opencontainers.image.vendor="https://github.com/accetto" \ org.opencontainers.image.version="${ARG_DOCKER_TAG}" LABEL \ org.label-schema.vcs-url="https://github.com/accetto/debian-vnc-xfce-g3" \ org.label-schema.vcs-ref="${ARG_VCS_REF}" LABEL \ any.accetto.version-sticker="${ARG_VERSION_STICKER}"