Setup for Tarn and Zach Adams’ Dwarf Fortress, using the Linux Lazy Newb Pack, running on top of Docker.
Current setup is for DF v0.40.24 (x64 LNP). As stated by the LNP Linux page:
If you are using a x64 bit system then you should download the x64 PyLNP interface, and 32 bit should download i686 PyLNP interface
This has been tested on Debian Jessie, but should work on any system with Docker for Linux installed. Let me know if this isn’t the case.
As stated in the forum posting, this LNP has been tested only on Ubuntu 14.04, on a fresh install. I’m not using Ubuntu — while I am using Debian, I’ve noticed enough differences between both distros to realize that this sort of thing is a pain in the ass to deal with.
Then I discovered Docker, and I noticed other projects using Docker to run LNP. Some even managed to do it so that they end up running GUI apps with Docker (the original idea came from one of Docker’s software engineers, and they’ve got a repo full of Dockerfiles for reference).
Which is neat. I wanted to do that.
First, follow the instructions for installing Docker for Linux. Once you’re able to run both hello-world
and whalesay
, you should be able to install this.
Clone this repository, or even download the ZIP file, and then run the following command:
$ make
Once that’s done, at the directory, run and it should work.
$ ./start-df-lnp-docker
There are several files that are available here:
Makefile
, which downloads the required ZIP files and creates the Docker image.Dockerfile
, tells Docker how to create and setup the image.start-df-lnp-docker
, which either runs or restarts the Docker image containing the LNP.
The Dockerfile’s basic structure is as follows:
<<metadata>>
<<download-prerequisites>>
<<prepare-environment>>
<<setup-defaults>>
Firstly, begin by defining the docker image’s meta-data and it’s base image:
FROM ubuntu:14.04
MAINTAINER Tariq Kamal <[email protected]>
LABEL vendor="Tariq Kamal" \
net.bebudak.version="0.0.2-alpha" \
net.bebudak.release_date="2015-11-05" \
net.bebudak.project_name="df/lnp/docker"
Then, set up and download the pre-requisites for the program:
RUN dpkg --add-architecture i386 && \
apt-get update -y && \
apt-get install -y default-jre libsdl1.2debian:i386 libsdl-image1.2:i386 libsdl-ttf2.0-0:i386 libglu1-mesa:i386 libgtk2.0-0:i386 libopenal1:i386 libjpeg62:i386 coreutils g++ gcc patch xterm sed python bzip2 qtchooser qtbase5-dev qtbase5-dev-tools qtscript5-dev qt5-qmake libqt5script5 libqt5scripttools5 libqxt-core0 libqxt-gui0 wget unzip locales
The download for this, disappointingly, will take a long time, and will bloat the image to approximately around 800 MB.
Set up the locales. We can only bring in the installation environment during the run command, so we’ll only do it then.
Essentially, set up the staging area — in this case, /home/Urist/bin/df
, and ensure that the locales are set properly.
ENV LANG en_US.UTF-8
RUN locale-gen en_US.UTF-8
RUN mkdir -p /home/Urist/bin/df
WORKDIR /home/Urist/bin/df
Export the values needed for this container.
Sections of this portion come from this blog post, as it covers the instructions that are needed to share your X11 socket with the docker container.
ENV uid=1000 gid=1000
RUN echo "Urist:x:${uid}:${gid}:Urist,,,:/home/Urist:/bin/bash" >> /etc/passwd && \
echo "Urist:x:${uid}:" >> /etc/group && \
echo "Urist ALL=(ALL) NOPASSWD: ALL" > /etc/sudoers.d/Urist && \
chmod 0440 /etc/sudoers.d/Urist && \
chown ${uid}:${gid} -R /home/Urist
USER Urist
ENV HOME /home/Urist
CMD /home/Urist/bin/df/startlnp
The Makefile’s basic structure is as follows:
<<make-variables>>
<<build-everything>>
<<download-LNP>>
<<cleanup>>
We’re using the latest version of LNP, as of [2015-10-22 Thu]. Also, we’re using the latest version of DF, as of [2015-10-22 Thu]. These will be downloaded every make
.
lnp-URL=http://lazynewbpack.com/linux/04024/download/x64/04024r3-x64.zip
lnp-zip=resources/install.zip
image-name=tariqk/dwarf-fortress-lnp
We’re using the -k
flag because I don’t want to be stopped by any iffiness with regards to SSL certs. After that, unzip it to the working directory and rename the directory accordingly.
resources/install.zip:
curl -kL -o $(lnp-zip) $(lnp-URL)
df:
unzip $(lnp-zip) -d . && \
mv 04024r3-x64 df
Once that’s done, we’ll just have a go and build it, eh?
all: | resources/install.zip resources/PyLNP.user start-df-lnp-docker df
docker build -t $(image-name) .
.PHONY: clean
clean:
rm -rf resources/install.zip df
This settings file, which is included in the resources directory, resolves the following issue.
Once this bug is closed, I’ll update this.
{
"terminal": "xterm -e",
"tkgui_height": 643,
"tkgui_width": 386
}
This basically checks if an existing container of the current version exists, and if so, restart the container.
Right now, if the ./df
folder is missing, I do think this will choke out.
<<project-variables>>
<<i-can-haz-container>>
if [[ $? != 0 ]]; then
echo "docker ps failed with exit code $?."
elif [[ $container_id ]]; then
echo "Container $container_id found. Restarting..."
<<restart-container>>
else
echo "No container found. Attempting to find image..."
<<i-can-haz-image>>
if [[ $? != 0 ]]; then
echo "docker images failed with exit code $?."
elif [[ $image_id ]]; then
echo "Image $image_id found. Running..."
<<run-image>>
else
echo "Image not found. Container not found. Have you already run make yet?"
fi
fi
PROJECT_NAME="df/lnp/docker"
PROJECT_NAME_LABEL="net.bebudak.project_name"
PROJECT_VERSION="0.0.2-alpha"
PROJECT_VERSION_LABEL="net.bebudak.version"
USER_ID=$(id -u)
GROUP_ID=$(id -g)
WORK_DIR=$(pwd)
We do this by running the docker ps
command, relying on the project name and version labels. We take the first entry, which, by rights, should be the newest container.
container_id=$(docker ps \
--all \
--format "{{.ID}}" \
--filter="label=$PROJECT_NAME_LABEL=$PROJECT_NAME" \
--filter="label=$PROJECT_VERSION_LABEL=$PROJECT_VERSION" | \
head -n1)
docker restart $container_id
We do this by running the the docker images
command, relying on the project name and version labels. We take the first entry, again, which, by rights, should be the newest image.
image_id=$(docker images \
-q \
--filter="label=$PROJECT_NAME_LABEL=$PROJECT_NAME" \
--filter="label=$PROJECT_VERSION_LABEL=$PROJECT_VERSION" | \
head -n1)
I’m trying to figure out where I got the export uid
and gid
trick is from, and when I do I’ll add the link.
docker run -ti \
-e DISPLAY=$DISPLAY \
-e uid=$USER_ID \
-e gid=$GROUP_ID \
-v /tmp/.X11-unix:/tmp/.X11-unix \
-v $WORK_DIR/df:/home/Urist/bin/df \
-v $WORK_DIR/resources/PyLNP.user:/home/Urist/bin/df/PyLNP.user \
-l $PROJECT_NAME_LABEL=$PROJECT_NAME \
-l $PROJECT_VERSION_LABEL=$PROJECT_VERSION \
$image_id
Yep, this is the org-file that generates most of the other files necessary for this, using org-mode
on Emacs.
After making changes in this document, I run org-babel-tangle
and update all the other files.
This file also sets up local variables (using add-file-local-variable
) to ensure that org-src-preserve-indentation
is set to t
. This ensures that the Makefile is properly created, preserving the TAB
used to define actions to specific rules.