Docker Setup
With the initial setup finalized and the operating system updated, we can now proceed to install docker and docker compose. Wherever possible, I will include the source of the information, enabling you to verify the correctness of the details provided here.
From this point forward, it is recommended to use SSH access instead of the console in PVE. Copying and pasting into the console can be tedious and unpleasant, but the choice is ultimately yours. If you are using a Windows-based system, you can utilize puTTY. If you are comfortable with a pure CLI (command line), PowerShell for Windows is an option. Personally, I use a program called Termius as it allows synchronization of all your configurations and keys on each computer, which is particularly useful when using multiple different computers. Please note that this guide assumes you are using a Windows computer. If you are using a variant of Linux or even BSD, then built-in terminals that can use SSH should be available.
Please be aware that Termius requires you to create an account to use the program. It is also a subscription-based program to enable synchronization, which may be a consideration given that the two aforementioned programs are free. However, as a general terminal program, it performs well and will not cease functioning if you choose not to subscribe.
Docker Installation
Let's proceed with the setup of Docker and Docker Compose.
All the information on how to install Docker was obtained from How2shout
setup-apkrepos -cf
The -c option enables the community repository (which contains most of the packages we will need), and the -f option instructs the system to automatically find the fastest mirror for downloading packages.
apk update
We will run the update command again to ensure that no updates have been released since we performed the initial package update in the previous step.
apk add docker docker-compose
Let's break down the above commands:
apkis equivalent toaptin Ubuntu.addis equivalent toinstallin Ubuntu.dockeranddocker-composeare the packages we want to install on the system. You can find a List of all packages here.
Next, we need to configure Docker to start with every boot of the VM.
rc-update add docker boot
This command adds the Docker service to the boot runlevel.
rc-service docker start
This command starts the service, allowing us to continue with the Docker setup.
Next, we need to add a user to Docker.
addgroup username docker
Docker Swarm Manager Setup
For Docker Swarm to function correctly, we need to use the VM. There appears to be a bug in the networking and swarm functionality that prevents the manager and workers running in containers (LXC) from communicating properly (I spent a considerable amount of time figuring this out, so learn from my experience!). Another reason to use Docker Swarm is that it allows us to run all of our services in their own containers. This means that if an update goes wrong or a configuration error occurs, it will not bring down all of your services. I also prefer the ability to start and stop everything individually, allowing me to make changes or even switch out services without the fear of causing a catastrophic failure. The VM will be our manager node (this will also be used for a few other services later on that need to be co-located).
docker swarm init
This command tells Docker to initialize the swarm and designates this VM as the manager node.
Once this process completes, a token will be displayed on the screen (it will look something like this: docker swarm join --token SWMTKN-1-48yic948l8c9sme8fv8m8w71hyj22dag8zs7xxw8yg0q-7gx8j672j1migqzzbucy3pfy3 192.168.80.152:2377). Copy this token to Notepad/Notepad++/your preferred text editor as it will be needed later to create worker nodes.
You can find Notepad++ here.
Docker Swarm Workers Setup
For the worker nodes, you can use separate LXCs as mentioned above. For information on how to set up an Alpine Linux LXC, you can see this page.
On the worker node, you will need to use the join token from the previous step.
docker swarm join --token SWMTKN-1-48yic948l8c9sme8fv8m8w71hyj22dag8zs7xxw8yg0q-7gx8j672j1migqzzbucy3pfy3 192.168.80.152:2377
You will receive a message indicating that the LXC is now a worker part of the swarm.
If you have made an error and setup an LXC as a worker that you did not intend to you can use the following command on the manager node
docker swarm leave --force
Then on the manager node run
docker node rm [NODE_NAME]
Custom Overlay Network Setup
The following command will set up the network.
Ensure to replace [YOUR_CUSTOM_NETWORK_NAME] with a memorable name as this will be used in your docker-compose.yml files to enable communication between different components.
docker network create -d overlay --attachable [YOUR_CUSTOM_NETWORK_NAME]
Let's break down that command:
docker network createis instructing Docker to create a network.-dis specifying that you want to create a detached network.--attachableis indicating that you want other services to be able to attach to it.[YOUR_CUSTOM_NETWORK_NAME]is the name of your network.
Once the command is run, you should see information about the network displayed, and Docker will inform you whether the operation was successful.
The overlay network will not show up until a service is pushed to it through the manager so do not worry if you don't see it on the worker(s) right away.
Swarm Verification
On the manager VM, we will verify that the worker nodes are present.
docker node ls
This command tells Docker that we want to list (ls) the nodes in the swarm. If everything has gone smoothly, you should see a list of all your workers and the manager.
Useful Docker Commands
docker system prune -a --volumes -f
The above command will prune all unused resources (containers, networks, images and volumes) you will need to do this at some point if you have been doing alot of testing trying to get your setup to work just how you want it.
docker service ls --format "{{.Name}}" | xargs -I {} sh -c 'echo "Service: {}"; docker service ps --format "table {{.ID}}\t{{.Name}}\t{{.Node}}\t{{.CurrentState}}" {}'
This command does the following:
- Lists all services and extracts their names.
- For each service, it runs docker service ps to display the tasks along with the nodes they are running on. The output will be grouped by service, showing the tasks and the nodes they are running on.
Here's a breakdown of the command:
- docker service ls --format "{{.Name}}": Lists all service names.
- xargs -I {} sh -c '...': Iterates over each service name.
- echo "Service: {}": Prints the service name.
- docker service ps --format "table {{.ID}}\t{{.Name}}\t{{.Node}}\t{{.CurrentState}}" {}: Shows tasks for each service, including the node and current state.
This will give you a clear and consolidated view of all services and where they are running in the swarm
docker stack rm [STACK_NAME]
This will remove a stack (and any networks it created along the way).
tail -n 100 /var/log/docker.log
This will display the last 100 lines of the docker.log file for troubleshooting issues.
You can also use the following command to display the whole log
cat /var/log/docker.log
docker ps -a --no-trunc
This will list all containers including any stopped ones.
docker exec -it [container-id] /bin/sh
This will give you a shell into that specific container so you can run commands.
wget -qO- ipconfig.io
This will allow you to get the IP address of the container that is facing the internet, useful if you are using a VPN container and want to make sure that it is getting the proper IP.
The Docker setup is now complete, and we can proceed to set up the services.