This guide assumes:
- You know the basics of Docker.
- You know what Team Fortress 2 is.
- You have a Linux machine capable of running containers.
1. Install Docker.
Let's install docker. Follow the article linked below. 😄
Install Docker Engine
2. Introducing: cm2network TF2 image.
To start a container, you'll have to provide an image. Of course you can make your own, however in this guide we'll use an unofficial, community built image from cm2network. You can find the git hub repository
here. Execute the following command to pull the image:
sudo docker pull cm2network/tf2
Optionally you can add the
sourcemod and the
metadmod image tags after
tf2.
- sourcemod will pull an image with sourcemod.
- metamod will pull an image with metamod.
An example of this command goes as follows:
sudo docker pull cm2network/tf2:sourcemod
3. Create a named volume.
As we all know, containers without a bind mount only persist data in an overlay, using the overlay storage driver. However, the TF2 game server constantly updates data, so we should store our data using a bind mount, or a named volume. In this step, we'll create a named volume, to store our serbur files on. You can read more about docker volume management
here. Run the following command:
sudo docker volume create volume_name
Make sure to replace volume_name with your preferred volume name. It can be anything you wish. This volume name is important for the next step.
⚠️ Warning: The Team Fortress 2 server is around 8GB in file size, and can be more if you add maps, plugins, mods and scripts. Manage storage space accordingly.
4. Start the server.
The most important, and probably the hardest step. Let's actually "make" the container, and get the serbur running! Don't worry, it's not too complicated:
Let's cook up a command using the docker syntax:
sudo docker run -d --name=tf2 \
-p 27015:27015 \
-p 27015:27015/udp \
-v volume_name:/home/steam/tf-dedicated/ \
-e SRCDS_TOKEN="" \
-e SRCDS_PW="changeme" cm2network/tf2:sourcemod
Where:
- -d - Starts the container in a De-attached mode.
- --name=tf2 - Names the container, so you can use it instead of the Container Id.
- -p 27015:2715 - Exposes the port 27015 on the host machine, on 0.0.0.0 which points to all addresses and interfaces. You might want to change that to something, e.g your public ipv4 address.
- -p 27015:27015/udp - Is the duplicate of this, just with the UDP protocol; The Docker -p command allocates the TCP protocol by default.
- -v volume_name:/home/steam/tf-dedicated/ - Here is where we define where the container should store the server files, by using the named volume we created earlier. Make sure to replace the volume_name block with the name you used to create the named volume.
- -e SRCDS_TOKEN="" - Is an environment variable. You can read more about the environment variables here. This is required to be listed & reachable. You can get your token here.
- -e SRCDS_PW="changeme" - The same applies to this environment variable, except that this isn't required, and certainly shouldn't be listed if you are making a private server. Just set it to empty if you wouldn't like to set a password.
- cm2network/tf2:sourcemod - Defines the image we pulled earlier. Don't worry. If you haven't pulled an image, this will automatically pull it from Docker Hub if it can't find it locally.
Port 27015 is the default port used by Team Fortress 2 servers. Feel free to change it, however in this case you'll have to add the port at the end of the IP when connecting, or you'll have to use an SRV record if using a DNS record.
⚠️ Warning: It is recommended to use the host interface if hosting a lot of Team Fortress 2 game servers because of it's more bandwidth efficient than containers using the docker bridge. You can do that by passing the --network=host option to the command, and removing the -p ... option(s).
🗒️ Note: If you are an advanced user, and you need STDIN, or a TTY session for automation, or something else, consider passing the -it option.
5. Connect to the server.
Time to connect to your server! Launch the game, open console, and type:
connect publivipv4ofyourserbur; password password
You should be able to connect. Don't specify a password if you haven't set one.
⚠️ Warning: If you are unable to connect, verify that your SRCDS_TOKEN is valid, and it's accessible. If using --net=host, or the host interface, make sure to open the port(s) on the firewall, on both UDP, and TCP, in & out.
You can find a firewall tutorial for ufw
here, or a tutorial for iptables
here.
If using
Ufw Docker, set up a route, by following the
README.md file.
6. Tips & tricks.
You might be wondering how to install maps, or plugins.
There are multiple ways of installing a map. One of them is using a command to do install maps from the Community Workshop. Let's do that:
1. First, we are going to attach to the server console:
sudo docker attach tf2
Make sure to replace the tf2 block with the name of your container.
2. Find a map that you wish to use, and copy the id like so:
Copy the id from the url.
3. Execute the following command in the console:
tf_workshop_map_sync mapid
Make sure to replace the mapid with the map id. This should automatically pull the map, add it to the tracking list.
To exit the console, hold Ctrl + p + q. This is the docker container escape sequence.
🗒️ Note: There are other ways to install maps outside Steam Workshop. One of them is getting inside the container file system using docker exec, and then downloading the files to the correct directory using wget or curl.
If you decided to install sourcemod, you have the option to install plugins. But how do you get them inside the container? Well, that's something for another post, where we will discuss the management of a Tf2 server in Docker.
Closing thoughts:
Thank you for reading my article! If you found it helpful consider sharing with others! Huge thanks to
Walentin for correction, and opinions. Thanks to
Dorkix for finding the command to install a map from the Steam Workshop. If you found something that is worth mentioning, feel free to add me on Discord at
Simon.#4921. Have a nice day/night! ❤️
⚠️ Warning: Edit on 2022.01.16: This post was originally published on Sep 12. 2021, and got migrated today.