Self-Hosting Your First App with Docker: A Beginner’s Walkthrough

Welcome back to Self-Hosted Tech! If you’ve been hanging around the homelab community, reading our blog, or watching our videos, you’ve probably heard the word “Docker” thrown around more times than you can count. You might be wondering what all the hype is about and, more importantly, how you can actually use it to run your own software.

Well, today is the day. We are going to take you from zero to self-hosted hero by deploying your very first application using Docker.

Before Docker came along, self-hosting was a bit of a headache. You had to install dependencies, configure web servers, manage database versions, and pray that installing one app didn’t break another app on the same machine. It was the digital equivalent of trying to perform open-heart surgery while riding a rollercoaster.

Docker changed all of that by using “containers.” Think of a container as a self-contained shipping crate. Inside that crate is everything the app needs to run: the code, the runtime, the system tools, and the libraries. Because it brings its own environment with it, you can place that crate on any machine running Docker, and it will run exactly the same way. No dependency conflicts, no mess, just clean, isolated applications.

Ready to build your first crate? Let’s dive in.

Prerequisites: What You Need Before We Start

Before we type a single command, let’s make sure you have the right gear. For this tutorial, you will need:

  • A Linux Machine: This can be a spare PC in your closet, a Raspberry Pi sitting on your desk, a Virtual Machine (VM) running on Proxmox, or a cheap cloud VPS (Virtual Private Server). We’ll be using Ubuntu/Debian commands for installation, but Docker runs on almost anything.
  • SSH Access: You need to be able to access your machine’s command line. If you’re using a Raspberry Pi or a remote server, you’ll SSH into it using a terminal.
  • Basic Command Line Knowledge: You don’t need to be a Linux sysadmin, but knowing how to navigate directories and run commands will help.

Got your terminal open and ready? Let’s move on to installing Docker.

Step 1: Installing Docker

If you already have Docker installed, you can skip ahead. If not, let’s get it set up.

While you can install Docker through the official Ubuntu repositories, those versions are often outdated. The best way to get the latest, stable version is to use the official Docker installation script.

Run the following command in your terminal:

1
2
curl -fsSL https://get.docker.com -o get-docker.sh
sudo sh get-docker.sh

This script will automatically detect your Linux distribution, add the official Docker repositories, and install everything you need. It might take a minute or two, so feel free to grab a coffee.

Once the installation is complete, you want to make sure Docker starts automatically whenever your machine reboots. Run this command:

1
sudo systemctl enable docker

Finally, if you don’t want to type sudo before every single Docker command (trust me, you don’t), add your current user to the Docker group:

1
sudo usermod -aG docker $USER

Important: For the group change to take effect, you need to log out and log back in, or simply close your terminal and open a new SSH session. Do that now, and then verify Docker is working by typing:

1
docker --version

If you see a version number printed on your screen, congratulations! You now have Docker installed.

Step 2: Understanding the Docker Vocabulary

Before we run our first app, let’s quickly go over a few terms so you actually understand what you’re doing, rather than just copy-pasting commands like a monkey.

  • Image: This is the blueprint. It’s a read-only file that contains the application and its environment. When you download an app to self-host, you are downloading an Image.
  • Container: This is the running instance of an Image. If the Image is a recipe for a cake, the Container is the baked cake sitting on your counter.
  • Volumes: This is how we save data. Containers are ephemeral—meaning if you delete a container, any data inside it is destroyed. Volumes map a folder on your host machine to a folder inside the container, so your data survives even if the container is deleted.
  • Ports: Containers run in their own isolated network. To access them from your web browser, we have to map a port on your host machine (like port 3001) to a port inside the container.

Keep these four concepts in mind as we move forward. They are the building blocks of everything you will do in Docker.

Step 3: Choosing Our First App

For your first self-hosted app, we want something that is incredibly useful, visually appealing, and easy to set up. We are going to deploy Uptime Kuma.

Uptime Kuma is a fancy, self-hosted monitoring tool. It’s basically a beautiful alternative to services like “Uptime Robot.” Once it’s running, you can give it a list of websites or services (like your other homelab apps), and it will ping them every few seconds. If a website goes down, Uptime Kuma will send you a notification via Telegram, Discord, Email, or a dozen other methods.

It’s the perfect homelab starter app because it will eventually help you monitor the rest of your homelab as it grows!

Step 4: The Walkthrough — Running Uptime Kuma

It’s time for the magic moment. We are going to use the docker run command to download the Uptime Kuma image and spin it up as a container.

Here is the full command. Take a look at it, and then we will break it down piece by piece so you understand exactly what it does.

1
2
3
4
5
6
docker run -d \
  --restart=always \
  -p 3001:3001 \
  -v uptime-kuma:/app/data \
  --name uptime-kuma \
  louislam/uptime-kuma:1

Let’s break down exactly what this command is doing:

  • docker run: This is the base command telling Docker to create and start a new container.
  • -d (or --detach): This tells Docker to run the container in the background. If you don’t use this, your terminal will be locked up showing the app’s logs, and if you close the terminal, the app will die.
  • --restart=always: This is a crucial flag for homelabs. If your machine reboots, or if the app crashes, Docker will automatically try to start it back up again.
  • -p 3001:3001: This is our port mapping. The first 3001 is the port on your host machine. The second 3001 is the port inside the container. We are telling Docker to take traffic hitting the host on port 3001 and funnel it directly into the container’s port 3001.
  • -v uptime-kuma:/app/data: This is our volume mapping. We are telling Docker to create a managed volume called uptime-kuma on our host machine, and link it to the /app/data folder inside the container. This ensures that if we ever need to update or delete the container, our Uptime Kuma settings and history are saved safely on the host.
  • --name uptime-kuma: By default, Docker assigns random, wacky names to containers (like nostalgic_einstein). Giving it a specific name makes it much easier to manage later.
  • louislam/uptime-kuma:1: This is the name of the image we want to download. louislam is the creator, uptime-kuma is the app name, and :1 specifies we want version 1 (the latest stable release of version 1).

Go ahead and paste that command into your terminal and hit Enter.

You’ll see Docker reach out to the internet, download the image layers, and then spit out a long string of letters and numbers. That string is your container’s ID. It means the app is running!

Step 5: Accessing Your New App

Now that the container is running in the background, how do you actually use it?

You need to open a web browser on your personal computer. In the address bar, type in the IP address of the machine you just installed Docker on, followed by the port number we mapped.

1
http://<YOUR_SERVER_IP>:3001

For example, if your Raspberry Pi’s IP address is 192.168.1.50, you would type http://192.168.1.50:3001.

Hit enter, and you should be greeted by the Uptime Kuma setup screen!

From here, it’s just a matter of creating an admin username and password. Once you log in, you can click the “Add New Monitor” button, type in a website like google.com, and watch as Uptime Kuma starts tracking its status.

You’ve officially self-hosted your first application. Take a moment to appreciate what you’ve done—you’ve bypassed big tech subscriptions and run a service entirely on your own hardware.

Step 6: Managing Your Container

Eventually, you’ll need to manage your app. Maybe you want to check if it’s still running, look at its error logs, or stop it temporarily. Docker makes this incredibly easy.

To see a list of all currently running containers, type:

1
docker ps

You’ll see a table showing the Container ID, the name (uptime-kuma), the status (Up X minutes), and the ports.

If you want to see the logs (which is very helpful for troubleshooting if an app isn’t working), use this command:

1
docker logs uptime-kuma

You can even follow the logs in real-time by adding the -f (follow) flag:

1
docker logs -f uptime-kuma

(To exit the live log view, just press Ctrl + C).

If you need to stop the app, perhaps to do maintenance on your server, run:

1
docker stop uptime-kuma

And when you are ready to start it back up:

1
docker start uptime-kuma

Step 7: How to Update Your App (The Homelab Way)

One of the most common questions beginners ask is, “How do I update my Docker container?”

Unlike traditional software, there is no “Update” button inside a Docker container. Because containers are immutable (they don’t change), updating means pulling the newest image from the internet and recreating the container.

Don’t worry—because we used a Volume (-v uptime-kuma:/app/data), your data is safe! Here is the exact process to update Uptime Kuma in the future:

  1. Stop the current container:
    1
    
    docker stop uptime-kuma
    
  2. Delete the old container: (Don’t panic! Deleting the container does NOT delete your data, because it is stored in the volume.)
    1
    
    docker rm uptime-kuma
    
  3. Pull the latest image:
    1
    
    docker pull louislam/uptime-kuma:1
    
  4. Run the exact same docker run command from Step 4:
    1
    2
    3
    4
    5
    6
    
    docker run -d \
      --restart=always \
      -p 3001:3001 \
      -v uptime-kuma:/app/data \
      --name uptime-kuma \
      louislam/uptime-kuma:1
    

Docker will see that the image has been updated, spin up a new container using that new image, and re-attach your existing data volume. You are now running the latest version, and you didn’t lose any of your settings!

Where to Go From Here?

You’ve successfully deployed, accessed, managed, and learned how to update a Docker container. You are officially a homelabber now!

As you start adding more and more apps to your server, typing out those long docker run commands can get tedious. That’s where Docker Compose comes in. Docker Compose allows you to write your container configurations in a simple text file (a docker-compose.yml file) and deploy them with a single command. We’ll be covering Docker Compose in our next tutorial, so stay tuned for that.

Summary and Call to Action

Today, we took a massive step in your self-hosting journey. We covered what Docker is, why containers are vastly superior to bare-metal installs, and walked through deploying Uptime Kuma as your very first self-hosted app. You learned how to map ports, map volumes for data persistence, and how to manage and update your containers from the command line.

Self-hosting is all about taking control of your data, learning how the technology you use every day actually works, and having fun along the way.

What app are you planning to self-host next? Let us know in the comments below or join our community over on Discord! If you found this walkthrough helpful, make sure to hit that subscribe button on the Self-Hosted Tech YouTube channel and drop your email on our blog so you never miss a tutorial.

Happy hosting, and we’ll see you in the next one!