I Stopped Running All My Docker Containers 24/7 and Do This Instead

Docker on demand 2

For the most part for years now if I run a Docker container that houses an app, my workflow has been pretty simple. I deploy it using Docker Compose, and then I leave it running. My home lab runs 24/7/365, so the containers just stay running along with everything else. This makes sense for infrastructure services like DNS for example that needs to be available so that your infrastructure components can talk to one another. Databases are another example. But, after I spun up more and more services in the home lab, I started to wonder if really everything “needed” to be up all the time and if I could run Docker containers on demand? This led me back to a project I have stumbled on and wanted to try, called DockerWakeUp. Let me show you what this means for your home lab and how to use it.

What is DockerWakeUp?

DockerWakeUp is a tool that sits between a client and an application that the client is trying to reach in your containerized environment. The term I think best describes what DockerWakeUp is doing is it is doing something like a scale to zero in the Kubernetes world.

So, this is like a Kubernetes feature, or cloud-native platform feature that allows you to reduce replicas when demand disappears. So DockerWakeUp essentially reduces it to zero so that the container is spun down, until demand comes back.

It has an NGINX component that handles the frontend HTTPS connection. Then it routes the requests toward your DockerWakeUp container which acts as a proxy and it will decide if the target service is up and running or not. If it is already running, the proxy will just forward on the request as you would expect. But, if it is stopped, DockerWakeUp will launch the Docker Compose project. It will then wait for the target app to respond, and then it will proxy and forward traffic to it once it is up and running.

Dockerwakeup architecture
Dockerwakeup architecture for Docker containers on demand

It basically keeps tabs on each configured service and how long it has been up and running. But, also, importantly, how long it has been idle. It has a built-in idle-shutdown process that checks the services every five minutes. It will stop containers when the idle time exceeds the threshold. By default, this is set in seconds to 3 days, or 259200 seconds. However, you can configure that. You could set something really aggressive for home lab if you have certain workloads that you know you don’t need for a bit.

Installed a few prerequisites as documentation a little fuzzy here

I ran through the install process on GitHub using the setup script, but found a few things didn’t really work the way the repo has the instructions written. In the defense of the developer here, the notes about needing npm, etc are in the README. But the “Quick start” guide is a little misleading as it says it has “dependency installation” which I think would make most assume that it installs everything it needs.

I found out this wasn’t the case, so I am going to paste here what I had to do to get things up and running in my test environment. You need to make sure your host already has Docker, Docker Compose, Node.js, npm, NGINX, Certbot, and jq installed.

On Ubuntu or Debian, I started with:

sudo apt update
sudo apt install -y nodejs npm nginx jq certbot

I also installed the Certbot DNS plugin for Cloudflare since I wanted to use a wildcard certificate:

sudo apt install -y python3-certbot-dns-cloudflare

After that, I created the letsencrypt folder and a cloudflare.ini since that is my DNS provider:

sudo mkdir -p /etc/letsencrypt
sudo nano /etc/letsencrypt/cloudflare.ini
Creating letsencrypt folder
Creating letsencrypt folder
The cloudflare.ini file
The cloudflare.ini file

Set the permissions on the cloudflare.ini file:

Set the permission son the cloudflare.ini file
Set the permission son the cloudflare.ini file

Nginx doesn’t quite get configured automatically

Part of the issue I ran into at first was self-inflicted since I assumed everything was installed. So my setup script bombed since Nginx wasn’t there. However, after getting Nginx there, I assumed I was on the home stretch.

The Quick Start says that after running the setup script, the wake proxy is running with NGINX configs “generated and ready to use. And, in the automated setup section, it says it automatically generates and links SSL-enabled NGINX configs. But when you ran it before NGINX was installed, it could not actually activate those configs.

In my configuration, even after I:

The generated file still only contained:

server {
    listen 80;
    server_name nginx.example.cloud;

There was no:

listen 443 ssl;

and no:

ssl_certificate /etc/letsencrypt/live/example.cloud/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/example.cloud/privkey.pem;

I used Certbot with the Cloudflare DNS plugin to manually request a wildcard certificate for example.cloud and *.example.cloud. This step gives you the standard Let’s Encrypt certificate and key under /etc/letsencrypt/live/example.cloud/. Certbot also set up automatic cert renewal.

Again, I reran DockerWakeUp’s NGINX generation step (step 4) again.

Rerunning step 4 after resolving certificate issues
Rerunning step 4 after resolving certificate issues

The generated config still only listened on port 80. So, I had to manually add the SSL config in the NGINX configuration. My file looked like this in the end:

# wakeup:manual

server {
    listen 80;
    server_name nginx.example.cloud;

    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl;
    server_name nginx.example.cloud;

    ssl_certificate /etc/letsencrypt/live/example.cloud/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/example.cloud/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:8080/proxy/nginx/;

        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto https;

        proxy_http_version 1.1;
        proxy_buffering off;
        proxy_request_buffering off;
    }
}

Now, installing DockerWakeUp

Now, that I had these things in place (remember I went through it once before to find out some of the above), I was able to get the DockerWakeUp solution up and running. First, clone down the repo and

https://github.com/jelliott2021/DockerWakeUp.git
cd DockerWakeUp
Cloning down the dockerwakeup
Cloning down the dockerwakeup

Then create the main configuration from the supplied example:

cp config.json.example config.json

From there, edit:

nano config.json
Copying and creating the config.json file and edit
Copying and creating the config.json file and edit

In case you are wondering what is in that example file, when you “nano” to edit it, you will see the following:

Default config.json file for dockerwakeup
Default config.json file for dockerwakeup

In case you are wondering, my config.json file looks like the following. I just have another NGINX container running for testing. So, this is the config file pointing to that single service. Note how you also configure the public domain as well.

The idleThreshold is the amount of seconds you want to wait before DockerWakeUp shuts the container down.

{
  "proxyPort": 8080,
  "idleThreshold": 300,
  "domain": "example.cloud",
  "services": [
    {
      "route": "nginx",
      "target": "http://localhost:8081",
      "composeDir": "/home/linuxadmin/homelabservices/nginx"
    }
  ]
}

It will combine the “route” name and prepend that on the front of your public domain. So below this will be:

nginx.example.cloud

Once you get to this point, we are ready to run the setup script that is included in the repo files. First, we need to make the script executable:

chmod +x setup-service.sh

Then, run the setup script:

./setup-service.sh
Running the setup script
Running the setup script
Setup completed successfully
Setup completed successfully

Enable the service to start at boot:

sudo systemctl enable docker-wakeup
Enabling the dockerwakeup service to start at boot
Enabling the dockerwakeup service to start at boot

Testing DockerWakeUp with an NGINX container

So to test this, I had a simple NGINX docker compose project on my test docker container host. What I then did is just ran a docker compose down on the NGINX stack.

Running a docker compose down
Running a docker compose down

After this, I ran a quick telnet to make sure the port was no longer listening that I had setup for NGINX.

Making sure the nginx container is down
Making sure the nginx container is down

When I pulled up the domain name for the NGINX container in a browser and then I saw this:

Dockerwakeup begins starting the nginx container
Dockerwakeup begins starting the nginx container for Docker containers on demand
The nginx container becomes available in just a couple of seconds
The nginx container becomes available in just a couple of seconds for Docker containers on demand

Idle shutdowns are where you can save resources

If you are interested in something like this for saving power or physical resources, the idle shutdowns are really where you can save resources. Obviously, the more idle containers that you have running on a node, the more resources this requires and more processing power. So if you have something that is already resource constrained like maybe an ARM64 device such as a Raspberry Pi, you could have this shutdown your containers that aren’t being used.

Granted we are talking “idle” containers so hopefully not a ton of resources, but every container adds up. Especially in the middle of the night, you may not need a big GitLab instance up and running. So you can imagine this can add up.

What types of idle policies might you think about? Below are just a few ideas on what you might consider for different types of workloads and use cases:

WorkloadExample idle policy
Frequently used utility12 to 24 hours
Occasionally used application1 to 4 hours
Development environment30 to 60 minutes
Demo environment15 to 30 minutes
Game server15 to 60 minutes

Security is bolstered with this as well

As you can imagine, if you are only running resources when they are needed, this is also a great capability for security purposes. Imagine drastically reducing the ports exposed and services running on your network for the majority of the day until you actually need those resources. This puts this into the realm of a “just in time” type solution where you only get the resources when you need them. But, that is a little bit of a stretch for me to put it in that category, but I do think this has a bit of a security benefit all in all.

Cold starts are the tradeoff

You have probably heard about something called “cold starts” with serverless technology. It is the amount of time for a backend container to spin up before it can start serving end users. So, obviously the same is true here. For my testing, a simple small NGINX camera spun up very quickly. But, that is just a simple NGINX container.

My GitLab server can take 2-3 minutes to get up and running. So, keep this in mind that there isn’t magic happening when it “starts” a container. It is just like you issuing a docker start command from the command line. So, if you have a container that takes a while to get fully spun up, that would be the same with DockerWakeUp.

Wrapping up

I found that DockerWakeUp is a pretty interesting tool for Docker containers on demand. I could definitely see that it would be interesting for many hyper power savers out there running home labs. Being able to spin down your containers will definitely save on processing and memory footprint across your home lab. The installation process I think is a little rough around the edges due to the documentation, but hopefully what I have shown here will help anyone get past a few of those areas of the instructions. What about you? Are you using anything like this, like a Sablier or something else? Let me know in the comments.

Google
Add as a preferred source on Google

Google is updating how articles are shown. Don’t miss our leading home lab and tech content, written by humans, by setting Virtualization Howto as a preferred source.

About The Author

Brandon Lee

Brandon Lee

Brandon Lee is the Senior Writer, Engineer and owner at Virtualizationhowto.com, and a 7-time VMware vExpert, with over two decades of experience in Information Technology. Having worked for numerous Fortune 500 companies as well as in various industries, He has extensive experience in various IT segments and is a strong advocate for open source technologies. Brandon holds many industry certifications, loves the outdoors and spending time with family. Also, he goes through the effort of testing and troubleshooting issues, so you don't have to.

0 0 votes
Article Rating
Subscribe
Notify of
guest
0 Comments
Oldest
Newest Most Voted