From e37e79b475c865a7a2f19bc462c48d7123874d8b Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Fri, 24 Dec 2021 00:15:03 -0500 Subject: [PATCH 1/8] docker-wine --- Makefile | 1 + download_gecko_and_mono.sh | 44 ++++++++++++ entrypoint.sh | 144 +++++++++++++++++++++++++++++++++++++ pulse-client.conf | 9 +++ ubuntu/Dockerfile | 97 +++++++++++++++++++++++++ 5 files changed, 295 insertions(+) create mode 100644 download_gecko_and_mono.sh create mode 100644 entrypoint.sh create mode 100644 pulse-client.conf diff --git a/Makefile b/Makefile index 8abb1d0..a74c490 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,7 @@ alpine: alpine.img %.img: builder %.dir @echo ${COL_GRN}"[Create $* disk image]"${COL_END} docker run -it \ + --platform linux/amd64 \ -v `pwd`:/os:rw \ -e DISTR=$* \ --privileged \ diff --git a/download_gecko_and_mono.sh b/download_gecko_and_mono.sh new file mode 100644 index 0000000..6612599 --- /dev/null +++ b/download_gecko_and_mono.sh @@ -0,0 +1,44 @@ +#!/usr/bin/env bash + +# Scrapes the Wine source code for versions of mono and gecko to download for a given version of Wine + +get_hrefs () { + local url="$1" + local regexp="$2" + + wget -q -O- "${url}" | sed -E "s/>\n.*|\1|p" | uniq +} + +get_app_ver () { + local app="${1^^}" # Convert to uppercase + local url="https://raw.githubusercontent.com/wine-mirror/wine/wine-${WINE_VER}/dlls/appwiz.cpl/addons.c" + + wget -q -O- "${url}" | grep -E "^#define ${app}_VERSION\s" | awk -F\" '{print $2}' +} + + +WINE_VER="$1" + +if [ -z "${WINE_VER}" ]; then + echo "Please specify the version of wine that requires gecko and mono installers" + echo "e.g." + echo " $0 5.0.1" + exit 1 +fi + +for APP in "gecko" "mono"; do + + # Get the app version required from wine source code + APP_VER=$(get_app_ver "${APP}") + + # Get the list of files to download + APP_URL="http://dl.winehq.org/wine/wine-${APP}/${APP_VER}/" + mapfile -t FILES < <(get_hrefs "${APP_URL}" ".*\.msi") + + # Download the files + [ ! -d "/usr/share/wine/${APP}" ] && mkdir -p "/usr/share/wine/${APP}" + for FILE in "${FILES[@]}"; do + echo "Downloading '${FILE}'" + wget -nv -O "/usr/share/wine/${APP}/${FILE}" "${APP_URL}${FILE}" + done +done diff --git a/entrypoint.sh b/entrypoint.sh new file mode 100644 index 0000000..af2684b --- /dev/null +++ b/entrypoint.sh @@ -0,0 +1,144 @@ +#!/usr/bin/env bash + +is_enabled () { + echo "$1" | grep -q -i -E "^(yes|on|true|1)$" +} + +is_disabled () { + echo "$1" | grep -q -i -E "^(no|off|false|0)$" +} + + +# Set user account and run values +USER_NAME=${USER_NAME:-wineuser} +USER_UID=${USER_UID:-1010} +USER_GID=${USER_GID:-"${USER_UID}"} +USER_HOME=${USER_HOME:-/home/"${USER_NAME}"} +USER_PASSWD=${USER_PASSWD:-"$(openssl passwd -1 -salt "$(openssl rand -base64 6)" "${USER_NAME}")"} +USER_SUDO=${USER_SUDO:-yes} +RDP_SERVER=${RDP_SERVER:-no} +RUN_AS_ROOT=${RUN_AS_ROOT:-no} +FORCED_OWNERSHIP=${FORCED_OWNERSHIP:-no} +TZ=${TZ:-UTC} +USE_XVFB=${USE_XVFB:-no} +DUMMY_PULSEAUDIO=${DUMMY_PULSEAUDIO:-no} + +# Catch attempts to set user as root +if [ "${USER_NAME}" = 'root' ] || [ "${USER_UID}" -eq 0 ] || [ "${USER_GID}" -eq 0 ]; then + echo "ERROR: To run as root, either set env RUN_AS_ROOT=yes or use ./docker-wine --as-root" + exit 1 +fi + +# Create the user account +grep -q ":${USER_GID}:$" /etc/group || groupadd --gid "${USER_GID}" "${USER_NAME}" +grep -q "^${USER_NAME}:" /etc/passwd || useradd --shell /bin/bash --uid "${USER_UID}" --gid "${USER_GID}" --password "${USER_PASSWD}" --no-create-home --home-dir "${USER_HOME}" "${USER_NAME}" + +# Create the user's home if it doesn't exist +[ -d "${USER_HOME}" ] || mkdir -p "${USER_HOME}" + +# Add or remove user from sudo group +if is_enabled "${USER_SUDO}"; then + groups "${USER_NAME}" | tr " " "\n" | grep -q "^sudo$" || usermod -aG sudo "${USER_NAME}" +elif is_disabled "${USER_SUDO}"; then + ! groups "${USER_NAME}" | tr " " "\n" | grep -q "^sudo$" || gpasswd -d "${USER_NAME}" sudo +else + echo "ERROR: '${USER_SUDO}' is not a valid value for USER_SUDO" + exit 1 +fi + +# Take ownership of user's home directory if owned by root or if FORCED_OWNERSHIP is enabled +OWNER_IDS="$(stat -c "%u:%g" "${USER_HOME}")" +if [ "${OWNER_IDS}" != "${USER_UID}:${USER_GID}" ]; then + if [ "${OWNER_IDS}" == "0:0" ] || is_enabled "${FORCED_OWNERSHIP}"; then + chown -R "${USER_UID}":"${USER_GID}" "${USER_HOME}" + else + echo "ERROR: User's home '${USER_HOME}' is currently owned by $(stat -c "%U:%G" "${USER_HOME}")" + echo "Use option --force-owner to enable user ${USER_NAME} to take ownership" + exit 1 + fi +fi + +# Configure timezone +ln -snf "/usr/share/zoneinfo/${TZ}" /etc/localtime +echo "${TZ}" > /etc/timezone + +# Run in X11 redirection mode (default) or with xvfb +if is_disabled "${RDP_SERVER}"; then + + # Set up pulseaudio for redirection to UNIX socket + if is_disabled "${DUMMY_PULSEAUDIO}" && [ -e /tmp/pulse-socket ]; then + [ ! -f /root/pulse/client.conf ] || cp /root/pulse/client.conf /etc/pulse/client.conf + fi + + # Run xvfb + if is_enabled "${USE_XVFB}"; then + nohup /usr/bin/Xvfb "${XVFB_SERVER}" -screen "${XVFB_SCREEN}" "${XVFB_RESOLUTION}" >/dev/null 2>&1 & + fi + + # Generate .Xauthority using xauth with .Xkey sourced from host + if [ -f /root/.Xkey ]; then + [ -f /root/.Xauthority ] || touch /root/.Xauthority + xauth add "$DISPLAY" . "$(cat /root/.Xkey)" + fi + + # Run in X11 redirection mode as $USER_NAME (default) + if is_disabled "${RUN_AS_ROOT}"; then + + # Copy and take ownership of .Xauthority for X11 redirection + if [ -f /root/.Xauthority ] && is_disabled "${USE_XVFB}"; then + cp /root/.Xauthority "${USER_HOME}" + chown "${USER_UID}":"${USER_GID}" "${USER_HOME}/.Xauthority" + fi + + # Run in X11 redirection mode as user + exec gosu "${USER_NAME}" "$@" + + # Run in X11 redirection mode as root + elif is_enabled "${RUN_AS_ROOT}"; then + exec "$@" + else + echo "ERROR: '${RUN_AS_ROOT}' is not a valid value for RUN_AS_ROOT" + exit 1 + fi + +# Run in RDP server mode +elif is_enabled "${RDP_SERVER}"; then + + # Exit if using nordp image + if ! [ -f /usr/sbin/xrdp ]; then + echo "ERROR: Unable to start RDP server as it is not included in this version of the docker-wine image" + exit 1 + fi + + # Remove xrdp pulseaudio source and sink modules if using dummy sound option + if is_enabled "${DUMMY_PULSEAUDIO}"; then + rm -f /var/lib/xrdp-pulseaudio-installer/module-xrdp-{sink,source}.so + fi + + # If the pid for sesman or xrdp is there they need to be removed + # or else sesman/xrdp won't start and connections will fail + [ ! -f /var/run/xrdp/xrdp-sesman.pid ] || rm -f /var/run/xrdp/xrdp-sesman.pid + [ ! -f /var/run/xrdp/xrdp.pid ] || rm -f /var/run/xrdp/xrdp.pid + + # Start xrdp sesman service + /usr/sbin/xrdp-sesman + + # Run xrdp in foreground if no commands specified + if [ -z "$1" ]; then + exec /usr/sbin/xrdp --nodaemon + else + /usr/sbin/xrdp + + if is_disabled "${RUN_AS_ROOT}"; then + exec gosu "${USER_NAME}" "$@" + elif is_enabled "${RUN_AS_ROOT}"; then + exec "$@" + else + echo "ERROR: '${RUN_AS_ROOT}' is not a valid value for RUN_AS_ROOT" + exit 1 + fi + fi +else + echo "ERROR: '${RDP_SERVER}' is not a valid value for RDP_SERVER" + exit 1 +fi diff --git a/pulse-client.conf b/pulse-client.conf new file mode 100644 index 0000000..3cc6942 --- /dev/null +++ b/pulse-client.conf @@ -0,0 +1,9 @@ +# Connect to the host's server using the mounted UNIX socket +default-server = unix:/tmp/pulse-socket + +# Prevent a server running in the container +autospawn = no +daemon-binary = /bin/true + +# Prevent the use of shared memory +enable-shm = false diff --git a/ubuntu/Dockerfile b/ubuntu/Dockerfile index b678bce..52472df 100644 --- a/ubuntu/Dockerfile +++ b/ubuntu/Dockerfile @@ -1,4 +1,6 @@ FROM amd64/ubuntu:20.04 + +# docker-to-linux LABEL com.iximiuz-project="docker-to-linux" RUN apt-get update -y RUN apt-get -y install \ @@ -6,3 +8,98 @@ RUN apt-get -y install \ systemd-sysv RUN echo "root:root" | chpasswd +# docker-remote-desktop +RUN sed -i -E 's/^# deb-src /deb-src /g' /etc/apt/sources.list \ + && apt-get update \ + && DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \ + build-essential \ + dpkg-dev \ + git \ + libpulse-dev \ + pulseaudio \ + && apt-get build-dep -y pulseaudio \ + && apt-get source pulseaudio \ + && rm -rf /var/lib/apt/lists/* + +RUN cd /pulseaudio-$(pulseaudio --version | awk '{print $2}') \ + && ./configure + +RUN git clone https://github.com/neutrinolabs/pulseaudio-module-xrdp.git /pulseaudio-module-xrdp \ + && cd /pulseaudio-module-xrdp \ + && ./bootstrap \ + && ./configure PULSE_DIR=/pulseaudio-$(pulseaudio --version | awk '{print $2}') \ + && make \ + && make install + +RUN apt-get update \ + && DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \ + dbus-x11 \ + firefox \ + git \ + locales \ + pavucontrol \ + pulseaudio \ + pulseaudio-utils \ + sudo \ + x11-xserver-utils \ + xfce4 \ + xfce4-goodies \ + xfce4-pulseaudio-plugin \ + xorgxrdp \ + xrdp \ + xubuntu-icon-theme \ + && rm -rf /var/lib/apt/lists/* + +RUN sed -i -E 's/^; autospawn =.*/autospawn = yes/' /etc/pulse/client.conf \ + && [ -f /etc/pulse/client.conf.d/00-disable-autospawn.conf ] && sed -i -E 's/^(autospawn=.*)/# \1/' /etc/pulse/client.conf.d/00-disable-autospawn.conf || : \ + && locale-gen en_US.UTF-8 +ENV LANG en_US.UTF-8 + +# docker-wine +# Install prerequisites +RUN apt-get update \ + && DEBIAN_FRONTEND="noninteractive" apt-get install -y --no-install-recommends \ + apt-transport-https \ + ca-certificates \ + cabextract \ + git \ + gnupg \ + gosu \ + gpg-agent \ + locales \ + p7zip \ + pulseaudio \ + pulseaudio-utils \ + sudo \ + tzdata \ + unzip \ + wget \ + winbind \ + xvfb \ + zenity \ + && rm -rf /var/lib/apt/lists/* + +# Install wine +ARG WINE_BRANCH="stable" +RUN wget -nv -O- https://dl.winehq.org/wine-builds/winehq.key | APT_KEY_DONT_WARN_ON_DANGEROUS_USAGE=1 apt-key add - \ + && echo "deb https://dl.winehq.org/wine-builds/ubuntu/ $(grep VERSION_CODENAME= /etc/os-release | cut -d= -f2) main" >> /etc/apt/sources.list \ + && dpkg --add-architecture i386 \ + && apt-get update \ + && DEBIAN_FRONTEND="noninteractive" apt-get install -y --install-recommends winehq-${WINE_BRANCH} \ + && rm -rf /var/lib/apt/lists/* + +# Install winetricks +RUN wget -nv -O /usr/bin/winetricks https://raw.githubusercontent.com/Winetricks/winetricks/master/src/winetricks \ + && chmod +x /usr/bin/winetricks + +# Download gecko and mono installers +COPY download_gecko_and_mono.sh /root/download_gecko_and_mono.sh +RUN chmod +x /root/download_gecko_and_mono.sh \ + && /root/download_gecko_and_mono.sh "$(wine --version | sed -E 's/^wine-//')" + +# Configure locale for unicode +RUN locale-gen en_US.UTF-8 +ENV LANG en_US.UTF-8 + +COPY pulse-client.conf /root/pulse/client.conf +COPY entrypoint.sh /usr/bin/entrypoint From efdf24db17cf31a58d6d8f1a471e930cf623c44a Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Fri, 24 Dec 2021 00:55:41 -0500 Subject: [PATCH 2/8] 20gb image --- create_image.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/create_image.sh b/create_image.sh index 6aaeac1..d5dab0a 100755 --- a/create_image.sh +++ b/create_image.sh @@ -11,7 +11,7 @@ echo_blue() { } echo_blue "[Create disk image]" -dd if=/dev/zero of=/os/${DISTR}.img bs=$(expr 1024 \* 1024 \* 1024) count=1 +dd if=/dev/zero of=/os/${DISTR}.img bs=$(expr 1024 \* 1024 \* 1024 * 20) count=1 echo_blue "[Make partition]" sfdisk /os/${DISTR}.img < /os/partition.txt From 5ea1a25833168c7cbbadf3cf7361ffb1f0470e63 Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Fri, 24 Dec 2021 00:55:48 -0500 Subject: [PATCH 3/8] platform everywhere --- Makefile | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/Makefile b/Makefile index a74c490..d3a6aac 100644 --- a/Makefile +++ b/Makefile @@ -15,7 +15,7 @@ alpine: alpine.img %.tar: @echo ${COL_GRN}"[Dump $* directory structure to tar archive]"${COL_END} - docker build -f $*/Dockerfile -t ${REPO}/$* . + docker buildx build --platform linux/amd64 -f $*/Dockerfile -t ${REPO}/$* . docker export -o $*.tar `docker run -d ${REPO}/$* /bin/true` %.dir: %.tar @@ -37,12 +37,13 @@ alpine: alpine.img builder: @echo ${COL_GRN}"[Ensure builder is ready]"${COL_END} @if [ "`docker images -q ${REPO}/builder`" = '' ]; then\ - docker build -f Dockerfile -t ${REPO}/builder .;\ + docker buildx build --platform linux/amd64 -f Dockerfile -t ${REPO}/builder .;\ fi .PHONY: builder-interactive: docker run -it \ + --platform linux/amd64 \ -v `pwd`:/os:rw \ --cap-add SYS_ADMIN \ ${REPO}/builder bash From d20bf8d1e247fff57fe42d182f14f92cef5fe6ae Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Fri, 24 Dec 2021 01:44:04 -0500 Subject: [PATCH 4/8] create_image typo --- create_image.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/create_image.sh b/create_image.sh index d5dab0a..fb9891d 100755 --- a/create_image.sh +++ b/create_image.sh @@ -11,7 +11,7 @@ echo_blue() { } echo_blue "[Create disk image]" -dd if=/dev/zero of=/os/${DISTR}.img bs=$(expr 1024 \* 1024 \* 1024 * 20) count=1 +dd if=/dev/zero of=/os/${DISTR}.img bs=$(expr 1024 \* 1024 \* 1024 \* 20) count=1 echo_blue "[Make partition]" sfdisk /os/${DISTR}.img < /os/partition.txt From 563891dfc57ebcf1c3fcf96c3e68af551e80747a Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Fri, 24 Dec 2021 02:00:20 -0500 Subject: [PATCH 5/8] fix dd blocksize issue --- create_image.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/create_image.sh b/create_image.sh index fb9891d..96ba20d 100755 --- a/create_image.sh +++ b/create_image.sh @@ -11,7 +11,7 @@ echo_blue() { } echo_blue "[Create disk image]" -dd if=/dev/zero of=/os/${DISTR}.img bs=$(expr 1024 \* 1024 \* 1024 \* 20) count=1 +dd if=/dev/zero of=/os/${DISTR}.img bs=1024 count=$(expr 1024 \* 1024 \* 20) # 20gb echo_blue "[Make partition]" sfdisk /os/${DISTR}.img < /os/partition.txt From 2171bd67b80e2f3c0b4495ea757aa4c6a20a82cd Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Fri, 24 Dec 2021 02:31:58 -0500 Subject: [PATCH 6/8] only 5gb --- create_image.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/create_image.sh b/create_image.sh index 96ba20d..eb0d17d 100755 --- a/create_image.sh +++ b/create_image.sh @@ -11,7 +11,7 @@ echo_blue() { } echo_blue "[Create disk image]" -dd if=/dev/zero of=/os/${DISTR}.img bs=1024 count=$(expr 1024 \* 1024 \* 20) # 20gb +dd if=/dev/zero of=/os/${DISTR}.img bs=1024 count=$(expr 1024 \* 1024 \* 5) # 5gb echo_blue "[Make partition]" sfdisk /os/${DISTR}.img < /os/partition.txt @@ -26,7 +26,7 @@ mkfs.ext4 ${LOOPDEVICE} echo_blue "[Copy ${DISTR} directory structure to partition]" mkdir -p /os/mnt mount -t auto ${LOOPDEVICE} /os/mnt/ -cp -R /os/${DISTR}.dir/. /os/mnt/ +cp -Rv /os/${DISTR}.dir/. /os/mnt/ echo_blue "[Setup extlinux]" extlinux --install /os/mnt/boot/ From bd978d55b8446e641f1d16ef15f8a707e43ea3d6 Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Fri, 24 Dec 2021 03:09:02 -0500 Subject: [PATCH 7/8] 5g partition --- partition.txt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/partition.txt b/partition.txt index f77bbaa..39548fa 100644 --- a/partition.txt +++ b/partition.txt @@ -3,5 +3,5 @@ label-id: 0x5d8b75fc device: new.img unit: sectors -linux.img1 : start=2048, size=2095104, type=83, bootable +linux.img1 : start=2048, size=10483712, type=83, bootable From d62fe8261d18639a86fa8e8804c07b66ddfcc64b Mon Sep 17 00:00:00 2001 From: Brandon Ros Date: Fri, 24 Dec 2021 03:25:40 -0500 Subject: [PATCH 8/8] entrypoint --- ubuntu/Dockerfile | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ubuntu/Dockerfile b/ubuntu/Dockerfile index 52472df..3f8d71e 100644 --- a/ubuntu/Dockerfile +++ b/ubuntu/Dockerfile @@ -102,4 +102,5 @@ RUN locale-gen en_US.UTF-8 ENV LANG en_US.UTF-8 COPY pulse-client.conf /root/pulse/client.conf -COPY entrypoint.sh /usr/bin/entrypoint +COPY entrypoint.sh /root/entrypoint.sh +RUN chmod +x /root/entrypoint.sh