Taylor

Made for Games

CapRover and Processes on the Metal

- 2 minutes to read

Why

With Heroku dropping the free tier from their service I decided to make better use of the “server” I have sitting in my home office. My current system was to just boot docker containers in the background with --restart unless-stopped, setting the ports manually, and updating my nginx configuration to forward correctly per sub-domain.

Naturally this is a pretty manual process which I have gotten sick of, so I decided to check out the alternatives and settled on CapRover which describes itself as:

CapRover is an extremely easy to use app/database deployment & web server manager for your NodeJS, Python, PHP, ASP.NET, Ruby, MySQL, MongoDB, Postgres, WordPress (and etc…) applications!

It’s blazingly fast and very robust as it uses Docker, nginx, LetsEncrypt and NetData under the hood behind its simple-to-use interface.

For all my toy applications I had it was as simple as caprover deploy from the directory since they all had their own Dockerfiles, which meant CapRover could very easily boot it up and manage the docker service for me.

Problem

This all sounds pretty amazing, so what was the problem I actually had? Well there’s one service I didn’t want to move into CapRover and it was my media service Jellyfin. CapRover doesn’t have a way to just point at the localhost instead of a docker container which makes sense, since there’s zero guarantee that CapRover is running on a single server as it’s designed to handle a swarm.

Solution

To make this less-than-usual setup work we’re required to boot a simple docker image:

FROM tecnativa/tcp-proxy

ENV LISTEN=:8096
ENV TALK=atom:8096

This uses docker-tcp-proxy which describes itself as:

Yes, this is a simply and stupid TCP proxy that listens in one address and talks to another one, with optional forced DNS preresolving.

The port 8096 is just the one used by Jellyfin by default so I kept it to keep the interface for docker consistent. But if you boot this now you’ll notice that it actually doesn’t work. We need to let the docker service know how to resolve atom which is done with a simple command:

docker service update --host-add atom:192.168.1.128 srv-captain--jellyfin

You’ll notice that I don’t use 127.0.0.1 and that’s because if I ever get a second server I don’t want it to randomly break if my Jellyfin instance decides to boot on the other server where it’s not hosted.

And with that done we should now have a functioning pass through on the CapRover application with minimal over head.

CONTAINER ID   NAME                                                 CPU % MEM USAGE / LIMIT     MEM %     NET I/O           BLOCK I/O         PIDS
fe598e5dd266   srv-captain--jellyfin.1.o8mq6v32sky20waib5bnovnyl    0.01% 4.293MiB / 31.06GiB   0.01%     432kB / 72.7kB    13.3MB / 4.1kB    2