Running Linux games on MacOS with Docker

Setting up X

Install XQuartz (X.Org X Window System that runs on MacOS)

brew cask install xquartz

Then in the XQuartz preferences, under the security tab, check the allow connections from network clients button

Quickstart (tldr)

Given XQuartz is set up

Find your IP address and allow access to the X server (assuming en0 is your network device)

export localIP=$(ipconfig getifaddr en0) xhost + $localIP

pull the container

docker pull theden/linux-games

run it with the following environment variables (passing in your localIP to DISPLAY )

docker run --hostname linux-games --user ubuntu -it -e DISPLAY=$localIP:0 -e XAUTHORITY=~/.Xauthority -v /tmp/.X11-unix:/tmp/.X11-unix -v ~/.Xauthority:/.Xauthority theden/linux-games

Now that’s fun, but let’s go through how the Dockerfile was built, and add a generic script that would ensure it would run on any MacBook.

Building the Dockerfile

Using ubuntu as the base image. Let’s work out the RUN commands we’ll need.

Base software

Let’s install the packages required, xauth , xorg , and sudo since we want your non-root user to be able to escalate to root.

apt-get install -y --no-install-recommends sudo xauth xorg

For the games, we’ll install gnome-games and the KDE games. the kdegames package doesn’t exist anymore, so we’ll individually install all the known packages.

apt-get install -y --no-install-recommends gnome-games bomber bovo granatier kajongg kapman katomic kblackbox kblocks kbounce kbreakout kdiamond kfourinline kgoldrunner kigo killbots kiriki kjumpingcube klickety klines kmahjongg kmines knavalbattle knetwalk kolf kollision konquest kpat kreversi kshisen ksirk ksnakeduel kspaceduel ksquares ksudoku ktuberling kubrick lskat palapeli picmi

User configuration

We’ll create the user ubuntu with sudo privledges

adduser --disabled-password --gecos '' ubuntu adduser ubuntu sudo echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers

Then set it as default with its home as the WORKDIR , add the /usr/games to PATH

USER ubuntu ENV PATH $PATH:/usr/games/ WORKDIR /home/ubuntu

Game list

I’d like the user to have a list of games avaiable with a description for each one. A trick is to use apt-cache search ^packagename$ to get the description, e.g.,

apt-cache search ^ksudoku$ ksudoku - Sudoku puzzle game and solver

What we can do is run this against all the games in the /usr/games directory and redirect it to a file gamelist that we can output when the container is run. Using some xargs magic, we can speed it up during the build

ls -A /usr/games | xargs -n 1 -I {} -P $(nproc) sh -c "apt-cache search ^{}$" > ${HOME}/gamelist

where the -P flag is for Parallel mode and nproc will print the number of processing units available to the current process, so we can parallelise the process as much as possible.

Entrypoint

We’ll set the entrypoint to be a script

ENTRYPOINT ["./start.sh"]

where it will print the list of games, cd in /user/games , and exec whatever command is passed to the container

#!/bin/bash cat gamelist cd /usr/games/ exec $@

Putting it all together

Optimising for layers and image size we now have our Dockerfile

FROM ubuntu:16.04 RUN apt-get -y update \ && apt-get install -y --no-install-recommends sudo xauth xorg \ && apt-get install -y --no-install-recommends gnome-games bomber bovo granatier kajongg kapman katomic kblackbox kblocks kbounce kbreakout kdiamond kfourinline kgoldrunner kigo killbots kiriki kjumpingcube klickety klines kmahjongg kmines knavalbattle knetwalk kolf kollision konquest kpat kreversi kshisen ksirk ksnakeduel kspaceduel ksquares ksudoku ktuberling kubrick lskat palapeli picmi \ && adduser --disabled-password --gecos '' ubuntu \ && adduser ubuntu sudo \ && echo '%sudo ALL=(ALL) NOPASSWD:ALL' >> /etc/sudoers \ && rm -rf /var/lib/apt/lists/* USER ubuntu ENV PATH $PATH:/usr/games/ WORKDIR /home/ubuntu COPY --chown=ubuntu start.sh /home/ubuntu RUN ls -A /usr/games | xargs -n 1 -I {} -P $(nproc) sh -c "apt-cache search ^{}$" > ${HOME}/gamelist \ && touch ~/.hushlogin \ && chmod a+x $HOME/start.sh ENTRYPOINT ["./start.sh"]

Running the container

I wrote a script that finds the MacBook’s active network device and the local IP, gives it access to the X server, and runs the container

#!/bin/bash IMAGENAME=theden/linux-games getip() { localIP=$(ipconfig getifaddr en0) if [ -z "$localIP" ] ; then localIP=$(ipconfig getifaddr en1) else return fi if [ -z "$localIP" ] ; then for i in $(networksetup -listallhardwareports | grep Device | awk '{print $2}' | grep -v "en0\|en1"); do localIP=$(ipconfig getifaddr $i) if [ ! -z "$localIP" ] ; then return fi done fi echo "can't find local IP" exit 1 } startcontainer() { docker run --hostname linux-games --user ubuntu -it -e DISPLAY=$localIP:0 -e XAUTHORITY=~/.Xauthority -v /tmp/.X11-unix:/tmp/.X11-unix -v ~/.Xauthority:/.Xauthority $IMAGENAME $1 } getip xhost + $localIP &> /dev/null if [ -z "$@" ] ; then startcontainer bash else startcontainer $@ fi

it works as expected

./run-container.sh five-or-more - make color lines of five or more length bovo - gomoku (five in line) board game bomber - arcade spaceship game four-in-a-row - Four in a Row game for GNOME gnome-chess - chess game with 3D graphics gnome-mines - popular minesweeper puzzle game for GNOME gnome-nibbles - snake game, up to four players gnome-klotski - Klotski puzzle game for GNOME gnome-mahjongg - classic Eastern tile game for GNOME gnome-robots - improved old BSD robots game granatier - Bomberman clone gnome-sudoku - Sudoku puzzle game for GNOME gnome-tetravex - put tiles on a board and match their edges together hitori - logic puzzle game similar to sudoku hoichess - xboard compatible chess engine to play chess with kajongg - classical Mah Jongg game iagno - popular Othello game for GNOME kapman - Pac-Man clone kblackbox - Black Box puzzle game kblocks - falling blocks game katomic - atomix puzzle game kbounce - Jezzball arcade game kfourinline - Connect Four game kdiamond - three-in-a-row game kbreakout - ball and paddle game kgoldrunner - Lode Runner arcade game killbots - port of the classic BSD console game robots kigo - go game kiriki - Yahtzee dice game klickety - SameGame puzzle game kjumpingcube - simple tactical game kmahjongg - mahjongg solitaire game klines - color lines game knavalbattle - battleship board game kmines - minesweeper game knetwalk - wire puzzle game kollision - simple ball dodging game kolf - miniature golf game konquest - simple turn-based strategy game kpat - solitaire card games kshisen - Shisen-Sho solitaire game kreversi - reversi board game ksirk - Risk strategy game ksnakeduel - snake race game ksquares - Dots and Boxes game kspaceduel - SpaceWar! arcade game ksudoku - Sudoku puzzle game and solver ktuberling - stamp drawing toy kubrick - game based on Rubik's Cube lskat - Lieutnant Skat card game palapeli - jigsaw puzzle game lightsoff - Light puzzle game picmi - Number logic game swell-foop - Colored ball puzzle game quadrapassel - popular Russian game, similar to Tetris tali - sort of poker with dice and less money ubuntu@linux-games:/usr/games$

With no arguments passed, the container will cat the gamelist file and give the user an interactive shell in the /usr/games directory. Passing a game name as an argument, the container will simply run the game.

Nice and simple! 👏

GitHub repository

https://github.com/TheDen/xserver-games-docker