LXD (Linux Container Daemon) is an advanced version of LXC (Linux Containers). LXD was created by Canonical which is the same company that makes Ubuntu. Although LXD runs on many Distros, I find that Ubuntu (even the server version) has a lot more support articles because of its wide use. Ubuntu Server lacks the desktop GUI and the desktop apps, meaning that it is a command line only Interface.
This means that Ubuntu server is very lightweight, fast and configured with minimal overhead. LXD containers in Ubuntu are essentially the server version and that’s what I use most of the time on the channel. You can run docker containers directly on your host. The advantage to running Docker containers inside of a LXD image is that you can bridge or macvlan your LXD containers to have any address on your LAN or any VLAN on your network.
My channel covers this extensively. One of the shortcomings of presenting all of your docker containers on one host is that each application shares the docker host IP address and so each docker container must be configured with unique TCP/IP port numbers that are unique on the docker host. Docker networking can alleviate this but is not as full functioned as LXD profiles for network settings.
If you had a webserver and a chat server that you wanted to run on the same docker host and they both wanted to use port 80 and port 443, you would have to remap the ports on one of the applications to use something different. In reality, I have maybe 5 apps that are just straight forward single docker containers that I offer at my host level. I have about 30 apps that are offered in 30 LXD containers inside the host. Some of these LXD containers run docker and have a docker application inside of LXD.
The advantage of this for me is that I have a single entity (one LXD container) that represents that app and I can snapshot or export a backup from it as featured on my channel. This rationale serves me very well with docker apps that have 10-15 containers that comprise them. Another good example is my Discourse server (https://discussion.scottibyte.com).
The discourse app has its key components running as a Linux application and then it has a docker container in which it runs some of its components. That’s the design of the discourse app. You can run multiple docker containers inside of one LXD or have multiple LXD containers. The design is up to you.
I just know that if I wanted to update my version of Docker, I would not want all my docker apps to have to be down at the same time. So, I have multiple LXD containers that run docker. The downside to this is that means that I might have 25 docker instances that need to be updated. I have gone with this design because I have discovered that some apps have very different dependencies than others and so a single docker host is not always optimal.
For me, I like having all my LXD containers because they are separate, manageable server instances. If you use LXDWare LXD Dashboard and Portainer, both can be configured to manage multiple LXD servers and multiple Docker servers. So, bottom line, the design is up to you.
I think the most important issue is resources. Both LXD and Docker are really lightweight and lean. Realize that LXD can provide upper boundary limits on memory and CPU utilization as often detailed on my channel. This is a fantastic feature because it prevents any one application from using too much of the host.
With that in mind, if you configure a LXD container with Multiple Docker apps, just be aware that all these apps together comprise a total memory requirement for the LXD container. In my case, my simple docker containers are at my host level where my multiple LXD containers are hosted.
My more complex apps with a docker requirement each have a dedicated LXD container with docker nested inside them. This provides superior application isolation, better performance monitoring, and isolated environments to snapshot and backup.
There is no right way in self hosting. Brian at Awesome Open Source has a single docker host in which he places all of his docker apps. He has their persistent data stored in unique folders for each app and that is his preference. He realizes the utility in going to one place for all his docker-compose and persistent data. This is a good design too. When you design a system, the choices you make are based on your experience with the technology.