Docker Installation and Setup
Prerequisites: Current Ubuntu Server LTS. If you’ve never used Ubuntu Server and just Desktop this is your opportunity to challenge yourself. I’ll cover some basic commands to get you over the hump.
UPDATE : Debian is my current recommendation, setup is very similar.
I won’t cover getting the VM installed, so we’ll assume you’re at a command prompt via SSH and ready to get to work.
Let’s cover some basic commands .
sudo - since we won’t be running as root (nor should you) we’ll run commands with sudo before anything docker related or requiring higher permissions.
ls -la - this will list the contents of a directory plus permissions. As we’ll be editing some permissions we’ll need to validate.
pwd - shows the path of the current directory. Useful for getting our bearings. Also handy for lazy typers who would rather copy/paste than type out a long path.
nano - text editor.
cd - change the directory you’re working out of.
/ - this is a representation of the root directory. E.G. cd / will take you to the root directory. Also implied in a path. E.G. the path to the opt folder is /opt .
mkdir - creates a directory
rm - deletes a file. To delete a folder, add -r
NOTE: this isn’t windows. make damn sure your path is correct. Linux is like the honeybadger. IDGAF about you or your files it’ll wreck your day and walk away with a smile.

Ok, let’s get going. https://docs.docker.com/engine/install/ubuntu/
Update: Debian! https://www.debian.org/CD/http-ftp/#stable
Note: Do not set a root password at setup.
For Docker, we’re going to use the “apt repository” method. It’s a simple copy and paste affair. Follow all the outlined steps. Then follow steps 2 and 3.
When you ran Step3, you saw that the docker image didn’t exist locally, so the system did a “pull” and obtained it from an online repository.
Once it pulled it down the docker started, fired off some text and shut down!
Let’s run sudo docker ps

That command only shows running containers. Let’s add -a. This will show all images. Remember when it’s not running it’s an image. When running, it’s a container.

So here we see the container ID, the image name, etc. Take note this image has no network ports, and the name at the end is randomly generated. Let’s make our docker volume directly and set permissions.
I’ve adopted the standard of using the opt folder for my docker configs. It’s easy to find, standardized, and a bit of a best practice.mkdir /opt/dockerconfigs

ah, lets check permissions. ls -la /opt

root owns it, which is fine. We just need to add sudo to our mkdir command

There’s our directory. What we want to do next is change the permissions for the 1001 user and group to own dockerconfigs. Our docker images will also use the same user. sudo chown -R 1000:1000 /opt/dockerconfigs/
Let’s run ls -la again and review.

Notice that the folder is now owned by 1001, aliased to my local user. We did not modify opt though. See that ..? that references the folder above us which is opt and is still owned by root.
Now try : mkdir /opt/dockerconfigs/test
Notice we don’t need sudo for this folder creation since we own dockerconfigs. But if you try and make a new folder under /opt sudo is still required. We want to own dockerconfigs so we don’t have to change the permissions for new folders constantly.

Checking the permissions dockerconfigs shows our test folder has the right settings. Let’s delete our test folder, and remember the honey badger at all times: rm -r /opt/dockerconfigs/test/
Ok, let’s talk Docker Networking.
Docker Networking
Ok, this is where docker gets hella cool. Run: sudo docker network ls

What we care about is host and bridge. Host is the network interface of the VM, and bridge is a default virtual network for use in docker. We can make lots of virtual networks in our docker config.
The vast majority of our containers will be mapped to a network other than host. Mapping a container to host removes much of the flexibility of docker. When we map to a virtual bridge, we can re-use internal ports between containers!
Each container gets its own namespace, so docker knows what service maps to which port. What you cannot do is re-use host ports, because you know…networking.
In this example, all the containers can communicate internally because they are are in same virtual segment. Every container you spin up can have its own network for segmentation. We’ll cover more on that shortly, as there is a change we should make.
So if we inspect the bridge network: sudo docker network inspect bridge we’ll see that it has a 172.17.0.0/16 network assigned.
Any new networks we make will get assigned the next range in the series, all /16s. Pretty soon, you’ll hit the 192.168.0.0/16 ranges and that’s just messy and terrible.
Do not like. Keep in mind that if these subnets conflict with a subnet on your network, any traffic destined will blackhole on egress. I mean, if the docker subnet is 172.17.0.0/16 and the source is 172.17.1.1, then there’s nowhere to go. You’re already there. A real “Hotel California” scenario.
So let’s change this behavior to hand out /24s instead in a different range.
sudo nano /etc/docker/daemon.json
change to the network standard you want and paste:
NOTE: Keep reading. I found an issue and fixed it below.

Then restart the docker daemon. sudo systemctl restart docker
If we re-inspect the bridge, we’ll see it has a /24 now.
Hol’ up. I noticed that while the CIDR range changed, the IP range did not. After some digging, we need to change the “bridge ip” since the networks iterate off the bridge.

To save in nano, ctrl+x, then save the buffer.
Due to the way Substack mangles the formatting I have an Example on my github. Now when I restart the daemon and inspect the bridge I see the right range, as well with the new networks. This concludes our setup prep.
Running Docker Images
So here’s where we are largely going to deviate from the CLI, and use a GUI tool going forward. The more time I’ve spent with Docker the more I’ve gotten comfortable with CLI, but I do love a good GUI that just makes life…easier.
Let’s talk Portainer, which is a great GUI docker management tool. 10/8/26: Nah, let’s talk Dockge instead. The more I used Portainer, the more I realized how much it abstracted the user from what was really going on, and it was honestly “too GUI” for our needs.
I then found Dockge. It still has a GUI, but it’s far simpler and works with the compose files directly, which provides the user with a better understanding. I am going to recommend my fork: https://github.com/darthrater78/dockge.
The maintainer has slowed way down on Dockge which is ok, but it was falling pretty far behind in vulnerabilities and features, so I decided to fork it and fix it with Claude because it’s just too good. What did I change?
Package vulnerabilities (still some upstream stuff but way less than it was)
Dockge supports “agents” for a pane of glass approach for multiple instances from one control panel. Those connections/creds are now properly encrypted
total mobile redesign
re-sizable terminal window
port conflict detection
stack port labeling (left panel)
compose drift sync. Tools like WUD will update the container but not touch the compose, this is a one click method to update them to the running container’s version.
API framework so containers can be controlled via Home Assistant.
https://github.com/darthrater78/ha-dockgeUpdated permissions to dockge itself, see latest for more.
The GitHub repo has a “quickstart” section but let’s get into it here. So this is going to be the one container you will manage manually because Dockge cannot manage itself. Our folder structure will look like this:/opt/docker/[ project name] These are the folders we will keep the data for our containers in.
/opt/docker/stacks [ project name] These are where we will keep the compose files for our projects. This is a bit different than standard, in that our compose files will be separate from the data. Below is an example.
In fact, the only container in my environment(s) that has the compose file in the data folder is Dockge. Since it can’t manage itself that makes the most sense, in my opinion as it’s the only one we will manage “traditionally.”
https://github.com/darthrater78/dockge#install
Run the block of text found there as it appears. It will ask you to confirm the box’s IP, pull down the latest compose, create the folder structure, set the permissions, and start up Dockge. EASY.
Click on +Compose. There’s always a example there, we can delete it. I am going to test with a Apprise container.
Save and start. You should see the image pull down start smoothly. Also, this is why we bind the IP in the yaml, that little grey button with the ip:port is clickable so you can test right away.
That’s it! If you have other docker instances you can also add them as “agents” and manage multiples from one place. Oh, and if you’re already running some containers and Dockge says they aren’t managed there, simply create a folder in stacks and move the compose file over. You should then be able to manage the container.
What’s great about Dockge is that it’s basically out of line management. All it does is monitor the docker socket and allow you send commands, edit the compose and easily view the terminal. Great stuff.
One last thing, let’s talk about the buttons, the Compose Sync Drift.
Edit: edit the compose file. Does not affect the running container when saved.
Restart: restarts the container
Update: if you edit the image in the line to the new version, update will save, pull the new image and restart
Stop: the container is stopped
Stop and Inactive: this will stop and delete the container. This is not as bad as it sounds. The image will still be on disk, but the container gets deleted. The data is in the bind volumes so that’s safe. I’ll mark a container inactive if I don;t want it to start on a boot or I have it down because I don’t want it to show up on my monitoring.

About the Compose Sync Drift, if you are updating your containers with something like WUD, make it a habit to come in here and hit the sync. That way if the server reboots the compose is up to date and you won’t boot with an older version.
Ok that about wraps it up. If you want a really deep dive into docker I highly recommend:
And remember, if there’s an app you want to run the first thing you should ask is…hey is there a docker for that? :)
Until next time.











