Skip to content
New issue

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

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

Already on GitHub? Sign in to your account

docker-wine #23

Draft
wants to merge 8 commits into
base: master
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ alpine: alpine.img
%.img: builder %.dir
@echo ${COL_GRN}"[Create $* disk image]"${COL_END}
docker run -it \
--platform linux/amd64 \
Copy link
Author

Choose a reason for hiding this comment

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

otherwise building on Apple M1 will oddly default to arm64 I believe

-v `pwd`:/os:rw \
-e DISTR=$* \
--privileged \
Expand Down
44 changes: 44 additions & 0 deletions download_gecko_and_mono.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
#!/usr/bin/env bash
Copy link
Author

Choose a reason for hiding this comment

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


# 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</g" | sed -n -E "s|^.*<a href=\"(${regexp})\">.*|\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
144 changes: 144 additions & 0 deletions entrypoint.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,144 @@
#!/usr/bin/env bash
Copy link
Author

Choose a reason for hiding this comment

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


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
9 changes: 9 additions & 0 deletions pulse-client.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Connect to the host's server using the mounted UNIX socket
Copy link
Author

Choose a reason for hiding this comment

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

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
97 changes: 97 additions & 0 deletions ubuntu/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,8 +1,105 @@
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 \
linux-image-virtual \
systemd-sysv
RUN echo "root:root" | chpasswd

# docker-remote-desktop
RUN sed -i -E 's/^# deb-src /deb-src /g' /etc/apt/sources.list \
Copy link
Author

Choose a reason for hiding this comment

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

not really sure if we can support the multistage FROM stuff, so this is a copy and paste hackjob from https://github.com/scottyhardy/docker-remote-desktop/blob/master/Dockerfile

&& 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
Copy link
Author

Choose a reason for hiding this comment

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

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