Hi Everyone! First off, let me introduce myself. I am dragonlord, the system administrator for a server called Adobocraft. I'm here to share some of the good stuff we've been doing to run and manage our servers, using Docker and Git. What is Docker? Docker is the hottest technology to come out since Virtual Machines. Docker allows applications and its dependencies to be packaged and deployed regardless of the server environment. The main difference is that you don't have the overhead of a Virtual Machine. This allows applications to run at near-native performance. Docker is a Linux-only technology, open source, and is constantly being improved. The client can be used on Linux, OS X, and Windows. The server component is currently Linux only, and Microsoft has been hard at work bringing the technology to Windows Servers. Want more details? Check out their page here: https://www.docker.com/what-docker Why use Docker for running Minecraft Servers? Let's enumerate the steps on how to setup a Minecraft server on Linux. I'll use Spigot in this case: Install the Linux distribution of your choice Install Java. You will need the JDK for compiling Spigot. Create separate user to run Minecraft (because running a Minecraft Server as root is a BIG NO). Install screen/tmux to allow scripting of console commands Download Spigot Build Tools to a temporary directory Run Spigot Build Tools to start building the server Have coffee and go to the gym Copy the compiled jars to the Minecraft user Run Spigot server to test if it's running Create shell script to manage the Spigot server by wrapping the server instance in screen or tmux For distros that still use SysV, create another shell script to control the execution and shutdown of the Spigot server. For distros that use Systemd, create a Unit File for the shell script, then register it with the systemd daemon. Restart your server and see if the Spigot server automatically starts. WOW! THAT'S A LOT OF WORK FOR ONE SERVER! Try rolling out 3 server instances, and suddenly you have this complicated mess of shell scripts, configs, port conflicts. Try adding Bungee to the mix, and it becomes a crazy mess! There is always a better way. Let's take that same example above, and deploy a server using Docker: Install the Linux distribution of your choice Create a group with the name docker, and add your user to the group Install Docker and enable at startup. It is absolutely simple to install. Deploy a Spigot server with the following command: Code (Text): docker run \ --name spigot-1 \ -p 0.0.0.0:25565:25565 \ -d \ -it \ -e DEFAULT_OP=dinnerbone \ -e MINECRAFT_EULA=true \ --restart always \ dlord/spigot THAT'S IT! No additional management scripts. No need to worry about adding users. No need to worry where the files are stored. Spigot gets compiled and deployed automatically. It just works! Need another Spigot instance on the same server, running on port 25566? No problem! You only need to changed the port mapping from the outside world to the container like so: Code (Text): docker run \ --name spigot-2 \ -p 0.0.0.0:25566:25565 \ -d \ -it \ -e DEFAULT_OP=dinnerbone \ -e MINECRAFT_EULA=true \ --restart always \ dlord/spigot No need to change the server.properties for the port mapping! And this is just the beginning! Spigot Docker Image used in Adobocraft Running a Dockerized Spigot server, while it all sounds great, has its own set of problems: Spigot does not have a clear separation between plugin configuration and data - Most of the time, the data files are living inside the same folder, together with the config files. This breaks one of the rules of Docker: you package your application and configuration together, and the data is stored outside the application. Of course, this can be easily solved by configuring the plugin to use an external DB. However, not all plugins support that. Sending console commands for automation purposes - Most server admins would probably use screen or tmux to allow sending console commands via scripts. While you can attach to a Docker container's STDIN to send commands, this does not mean you can send commands to it in an automated fashion. To allow sending console commands via scripts, you will need to wrap the docker attach session inside screen or tmux. Very annoying if you want to manage multiple Spigot instances. Performing a safe shutdown - Safe shutdown can be achieved by sending the stop command via the console or chat. If you want to do this in an automated manner, you will need to do something like #2, which is not ideal if you're handling multiple Spigot instances. To address these 3 main problems, I developed a Spigot Docker image. This is publicly available for download here. We have been using this to rollout configuration changes, execute scheduled commands without installing tmux, screen, or Spigot plugins, and cleanly shutdown our server instances during server updates. Configuration Management using Docker and Git Most Minecraft server admins are used to adding plugins and changing server configurations the old-fashioned way: either they manually upload via FTP, or they remotely access the server to edit the files. Not only is this inefficient, it is very error prone. I'm pretty sure a lot of you have tons of *.bak files to ensure you can rollback to the last known version. And even with that, there's no guarantee that you can rollback your server completely. Our configuration management is done via Git, a popular source control developed by the father of the Linux kernel, Linus Torvalds. We check in all our plugins and configuration files into a local Git repository. Once somebody pushes their changes to our central Git repo, all of the artifacts are packaged into a Docker image. This image can then be deployed as our test server. Once we're happy with the changes, we simply tear down the production docker container, and then recreate it using the updated image. This setup has many benefits: Traceability and Accountability - We can easily track who changed what, and who screwed up. Development Environments - All personnel who has access to our Git repo can run our entire infrastructure in their local machines, as if they are running the whole thing in production. Since every piece of our infrastructure is running as a Docker container, our setup is portable across machines. Fast deployments - We are able to deploy to production in under 30 seconds. Users only know we're restarting. What they don't know is we're replacing the entire server with a new one, every single time. Creating server instances with the same configuration - We have a test and a production environment. If we wanted to provision a new environment with the same settings, we can just spin up another instance using the same Docker image we used on test or production. Ability to rollback to previous versions - sometimes we would encounter an issue on the production server that we were not able to catch on our test environment. We can easily rollback to any version we wish, all under 30 seconds. This setup has saved our asses ALOT OF TIMES NOW! Data Management As mentioned previously, the main problem with running a Spigot server is that data and configuration are intertwined. Until such time that Spigot and/or plugin authors store their data files on a location outside the plugins folder, managing data can be such a hassle. We've experimented with different ways to make this manageable with our setup, and we settled with the following: Data Volume Containers is our best friend - We do not store our data directly on the host system. Instead, we make use of Docker's Data Volumes. This allows us to deploy our whole infrastructure on a different server, without worrying about missing folders and other similar problems. World data is stored on a separate folder from Spigot's main folder - We were able to achieve this thanks to Spigot's ability to specify a different world directory. This is a feature baked into my Spigot Docker image, which makes it easier for us to backup and restore the world data. Configured every plugin we use to store data in a DB like MySQL - not all plugins offer this option. Some only use sqlite, which is practically a flat file. Those that can store in an external DB are immediately configured to do so. We then provision a database server instance for each environment using Docker. For plugins that store data as flat files, exclude the data files from the Git repo - This is a tedious process. We test each plugin we add to determine where they store their data files. Once we've determined them, we exclude them from the Git repo, so that they are not overwritten during deployment. Things could be better. For now, this setup works well. Conclusion Running a Dockerized Minecraft Server may seem like a lot of hard work, especially if you're used to using things like McMyAdmin. Docker works well with automation tools like Jenkins and Ansible. It has allowed us to monitor and control all Spigot server logs via systemd. We can even create complex scripts to execute console commands automatically, without the hassle of managing tmux or screen sessions. Overall, it has been a pleasant experience for all of us. We continue to refine how we do things at Adobocraft, and we'll be sharing more as we go along.