Thursday, March 23 2023, 10:14 UTC
Ayy it's time for another late blog post from yours truly. As the title says today's post is all about docker, to be specific, I'll be explaining some of the basics on how to use docker for self-hosting :^)
So to start with docker, you obviously need a computer to run it on. For today I'll be covering the linux side of things, since it's the one that has the most support and it's the one I'm familiar with.
Install docker and docker-compose. Most distros will have them in the official repos already, but in case they aren't just googl... well SearX, your distro and how to install docker on it. Once you have it on your system, you'll need to start the daemon. You're most likely running systemd as your init system, if not I trust you already know what to run insted of the commads below:
sudo systemctl start docker
And to make it run at boot:
sudo systemctl enable docker
After you run those commands you can check if the daemon is running with:
sudo systemctl status docker
If it's running, the output should be something like this:
- (press RETURN)● docker.service - Docker Application Container Engine Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled) Active: active (running) since Wed 2023-03-08 15:22:44 CET; 2 weeks 0 days ago TriggeredBy: ● docker.socket Docs: https://docs.docker.com
And once the docker engine is running, we can move on, on how to actually use it!
To keep things tidy I suggest you create a folder in your user's home directory dedicated to this stuff. I called mine docker-compose, it's mostly what's gonna be in it. Navigate inside your newly created folder and create another folder for the project you want to host, let's say AdGuard Home for example, you can call the folder just adguard. Navigate inside this folder too and finally create a file called docker-compose.yml. We'll use this file to define all the variables needed to run a docker container, so open it with a text editor of your choosing and for now copy this text to it:
version: "3" services: adguard: container_name: adguard image: adguard/adguardhome:latest ports: - 53:53/tcp - 53:53/udp - 67:67/udp - 68:68/tcp - 68:68/udp - 853:853/tcp - 8012:8012/tcp volumes: - ./workdir:/opt/adguardhome/work - ./confdir:/opt/adguardhome/conf restart: unless-stopped
Like the name of the file says, docker-compose uses yaml files as persistat configs for docker containers, this makes re-deployment extremely easy and straight forward, but before that, I want to explain how the configuration actually works.
One important thing to keep in mind is that since the file is a yaml file you must respect it's syntax/indentation, one mistake in spacing could and will throw out an error when trying to launch the container. So I recommend looking at some examples of docker-compose files to get familiar with the correct formatting.
The version field refers to what version of docker-compose file you want to use, this will determine what docekr engine release will be supported, you can find the complete table of copatibility here.
The services field is where you'll list all the containers you want to run it this stack, for adguard only one is necessary, but some services require multiple.
The adguard field refers to the name of the service
The container_name field will be the name the container will take, I suggest making it the same as the service.
The image field is where you'll enter the image of the service you want to use. To find an image, you can look in Docker Hub. Images can also be used along with tags like :latest which tells docker to pull the latest available version of that image, through this, a specific version can be pulled and if available even images based on different distros like alpine and debian. Furthermore, different architechtures are also supported and can be specified if available. Here's an example of all the cases:
The ports field is used to bridge the ports inside the container to the ports in the host machine, the ports to the left are the one on the host, the ones on the right are the ones in the container. The internal port can also be linked to a different external port. Different portocols can also be specified by using /tcp or /udp.
ports: - 69:420/tcp
The volumes field much like the ports field is used to link folders or files from inside to outside the container. Again the left is the outside, the right is the inside. Volumes managed by docker can also be created like this:
version: "3" services: alpine: image: alpine volumes: - xyz:/home/user/xyz #linking a virtual volume - /mnt/data:/data #linking a folder volumes: xyz:
As a sidenote, like I said files can also be linked but MUST be cretead before running the container.
If docker-compose doesn't find a file or a folder that is listed in it's volumes, it will default to creating a folder.
And for last the restart field is used to tell the container when it should restart. The options are: always, never, unless-stopped. The last one seems always seems like the best one for me to use, in case of a crash or a computer restart the container will always restart, unless it was stopped manually.
Well now the container is ready and you understand how it works, the only thing left to do is to run the command:
sudo docker-compose up -d
Make sure to run it in the same folder as the
docker-compose.yml file, so it knows where to pull it from.
And there you go, it should pull the image the first time you run it and once it's done, the container will launch. With this your container should be up and running. If it has a web interface you'll be able to connect to it by entering the local ip of the computer you're running docker on in a browser, followed by the port that is linked on the host pc.
If you ever need to take down the container you can this command the same way you ran the previous one.
sudo docker-compose down
But yeah that's pretty much it! Not that complicated, to be fair this is just scratching the surface.
For now this is all, in the next post I'll cover the networking side of things and how to set up a reverse proxy to host something publicly :^)