Skip to content

Overview

I started ThoriumLXC after spending some time experimenting with emulator game servers. I frequently encountered issues when switching between server versions or variants, as resuming progress from a backup often failed. Although several containerized solutions were available for these emulator services, each approached the problem differently, and I felt like I was starting from scratch every time.

That's when I began developing ThoriumLXC, aiming to create a plug-and-play solution for easily spinning up different servers. The idea was simple: stop a server at any time (and back up the game data) and restart it later without any hassle.

To run these environments, I decided to use Docker and Docker Compose because they simplify starting and stopping services. For building the container images, I chose Bazel in an effort to make the build process more predictable. In simple terms, every build would produce exactly the same result, regardless of where or when it was executed. This approach also gave me the opportunity to experiment with rules_oci, a new Bazel method for building container images.

Docker

Docker is a tool that bundles an application (like a game server emulator) with everything it needs—code, libraries, system tools, and more—into a portable container.

Think of it like a lunchbox: once everything is inside, it's the same no matter where you open it.

I've used containers while working within cloud environments and for services I self-host on my own home servers. I find they make things easier, especially when it comes to tasks such as backups, migrating between hardware, or stopping and starting projects.

Why Docker for ThoriumLXC?

  • No installs: There is no need to manually install runtime libraries or handle multiple programs.
  • Simple updates: If a new version is released, you simply download the updated container.
  • Quick resets: If something goes wrong, you remove the container and start fresh.
  • Portable: Moving to different hardware is easy—just restore the game data from a backup.
  • Rollbacks: If something is off in a new version, you can use an older version tag.

Docker Compose

When your setup requires multiple containers, such as an emulator server plus a database, Docker Compose launches them all together with a single command and manages them as a group. It acts as a coordinator, so you don't have to start each component individually. This also takes care of dependencies, ensuring that a server waits for its associated database to be up before starting correctly.

Why Docker Compose for ThoriumLXC?

  • Easier management: Launch or shut down every container at once.
  • Portable configuration: Create a repository with a configuration that can be booted up quickly.
  • Clear organization: Define everything in a single file, making it simple to see how the pieces connect.
  • Administration: Easily include backups, supporting services, and configuration files.

Bazel

Bazel is a build system that I use to package the emulator code and files into container images. In practice, this means that for any given version of the emulator code, the build produces an identical container image.

I chose Bazel because I was already familiar with it and wanted to take the opportunity to work with the new rules_oci ruleset, which simplifies building container images within Bazel. The rules_oci ruleset offers a different experience compared to using Dockerfiles and has notable quirks when it comes to ad-hoc scripts. This resulted in a build that worked out, though it probably isn’t the best practice.

Why Bazel for ThoriumLXC?

  • Predictable Builds: Every container image is built in a repeatable way, reducing surprises.
  • Variant Management: Managing different versions or optional builds is straightforward.
  • Smooth Experimentation: Building and testing new versions is easier when the process remains consistent.
  • Hermetic Outputs: Because each container image is derived solely from its source, it's easier to verify that no tampering has occurred.

In short, I mostly just wanted to tinker with Bazel and figured it would be pretty straightforward.