Play Teeworlds through Docker
       2023-10-24
       Last edit: 2023-10-24
       ---------------------
       
       Many Teeworlds servers currently in use are containerized. However, it is also possible to containerize the Teeworlds client using Docker.
       
       The Dockerfile is available below, it compiles and executes the ELF file in the Docker container. I've also published the image on Docker's public registry, Docker Hub.
       
       ## Build the Docker image
       
       So there are two methods to get the Docker image, you can download it or building it yourself.
       
       ### Pull from Docker Hub
       
       ```bash
       docker pull b0thr34l/teeworlds:1.0
       ```
       
       ### Build from source
       
       ```dockerfile
       FROM ubuntu:20.04 as build
       
       # Avoid tz stuck at installation
       ARG DEBIAN_FRONTEND=noninteractive
       ENV TZ=Europe/Moscow
       
       # Install dependencies to build binaries
       RUN apt-get update -y && \
           apt-get -y install --no-install-recommends \
           ca-certificates \
           build-essential \
           cmake \
           git \
           libfreetype6-dev \
           libsdl2-dev \
           libpnglite-dev \
           libwavpack-dev
       
       # Clone the git repository
       RUN git clone https://github.com/teeworlds/teeworlds /client
       
       # Go into the build directory
       WORKDIR /client
       
       # Compile client only
       RUN mkdir -p build && \
           cd build && \
           cmake .. && \
           make teeworlds
       
       FROM ubuntu:20.04 as run
       
       # Install the shared library
       RUN apt-get update -y && \
           apt-get -y install --no-install-recommends \
           libfreetype6 \
           libsdl2-2.0-0 \
           libpnglite0 \
           libwavpack1 \
           libopengl0 \
           libgl1
       
       # Create a new user
       RUN useradd -ms /bin/bash tee
       
       USER tee
       
       WORKDIR /teeworlds
       
       # Copy the output files
       COPY --from=build /client/build/data ./data
       COPY --from=build /client/build/teeworlds .
       
       CMD [ "./teeworlds" ]
       ```
       
       ## Create and start the Docker container
       
       Now we can create and start a new container with the teeworlds client image we just created or downloaded.
       
       I consider that you're using X as your windowing system, rather than something like Wayland or something else.
       
       ### X Window System
       
       So that the game can work and we can play it. I assume you are using the X window system and that you have a X server listening at a UNIX domain socket.
       
       That is why we are forwarding the `/tmp/.X11-unix/` directory that contains the UNIX domain socket(s) for the X server.
       
       The `DISPLAY` environment variable is going to target the UNIX socket that we are using. This means that, technically, the container will be able to write data to this UNIX socket, and thus create a new window.
       
       Make sure that your X server controll is configured correctly before running the Docker container. If you just want to try you could disable entirely the policies but it is not recommended.
       
       ```bash
       xhost +
       ```
       
       Instead, you should add a single local user.
       
       ```bash
       xhost +si:localuser:$USER
       ```
       
       ### Storage configuration
       
       Teeworlds uses a specific location to store its data, it is described in a file named `storage.cfg` that we can find on the 
 (HTM) offical Teeworlds GitHub repository
       .
       
       We are looking for `$USERDIR`, we are going to mount this directory into our Docker container.
       
       The first option is to create a new Docker volume containing the Teeworlds user data. We don't want to override the container directory, so we will create a shared Docker volume.
       
       ```bash
       #!/bin/sh
       
       TW_USERDIR=$HOME/.config/teeworlds-userdir
       TW_DOCKER_VOLUME=teeworlds-userdir
       
       mkdir -p ${TW_USERDIR}
       
       docker volume create \
           --driver local \
           --opt type=none \
           --opt device=${TW_USERDIR} \
           --opt o=bind \
           ${TW_DOCKER_VOLUME}
       
       docker run -it \
           -e "DISPLAY=$DISPLAY" \
           -v "/tmp/.X11-unix:/tmp/.X11-unix" \
           -v "${TW_DOCKER_VOLUME}:/home/tee/.local/share/teeworlds" \
           --device "/dev/snd" \
           --device "/dev/dri" \
           b0thr34l/teeworlds:1.0
       ```
       
       If you already had Teeworlds data in an user directory on your host system. You can mount a volume directly without creating a Docker volume, as shown in the example below.
       
       ```bash
       -v "$HOME/.teeworlds:/home/tee/.local/share/teeworlds"
       ```