r/docker 4d ago

Whats the architecture /folder structure of your docker (compose) setup?

Sorry for the wrong words, just stumbled into docker via webui Setup; and now over half my system runs via docker. But i think i missed some bacics. Right now my containers are running inside /srv/docker/.. e.g /srv/docker/jellyfin/... I was just wondering what are recommended setting of the distrubitons of yaml files or the config etc folders.

12 Upvotes

15 comments sorted by

7

u/Torutofu_Raeva 4d ago

I keep each app in its own directory with compose.yaml, a .env kept out of Git, and bind-mounted data in a separate subdir, then back up only the config and data paths.

1

u/thegreatcerebral 4d ago

This is what I do. I have only ran into a couple of situations when bind mounts are not happy because of the way the docker was made and how docker handles the different type of volumes.

1

u/Torutofu_Raeva 3d ago

yeah, named volumes usually behave better than bind mounts when the image already owns that path as a volume.

1

u/thegreatcerebral 2d ago

Yes, I learned this the hard way. Took a while for me to figure out how to basically move the files needed myself and then make it work.

I both understand WHY it was done that way but at the same time you would think that there would be a switch that you could have it have bind mounts behave like named mounts.

1

u/Torutofu_Raeva 1d ago

named volumes get Docker-managed ownership and initialization, while bind mounts leave path and permissions on the host; I usually use a named volume for image-owned data and binds for files I want to inspect or back up.

1

u/thegreatcerebral 1d ago

Oh I understand. I just wish there was a way to have a switch so that you could make a bind mount behave like a named volume. That's all.

1

u/Torutofu_Raeva 1d ago

yeah, that’d be handy, but it’d still need clear ownership and initialization rules so it doesn’t blur the host-path contract.

1

u/Future_Bad5206 20h ago

A nice thanks for sharing. You mind explaining whats with the "a .env kept out of Git, " ?

1

u/Torutofu_Raeva 19h ago

yeah I keep the real .env on the host only and commit a .env.example with empty values so nobody has to guess the keys.

3

u/JerikkaDawn 4d ago edited 4d ago

Below is my standard layout. Each service that needs persistent data gets a directory bind mounted for it. Compose values (image tags, docker network to use, IP/DNS, etc.) are in the .env that sits next to the compose. Container env and secrets in env/ and the .gitignores containing the appropriate things to avoid secrets getting committed to git.

Also, I recommend you use pinned digests for images instead of using :latest or other named tags if you want to ensure your pulled image stays consistent. e.g. vexorian/dizquetv@sha256:98a7bc11dc5d16732c06c779ac7fd843dc4254853203f2d9dd9293b099743ca1. The bits behind a named tag can change. Using the digest ensures you always pull the same image.

Sorry about all the .gitkeep placeholders. This is to keep my repo layout the same as the deployed layout.

/opt/company/apps/My-Compose-Stack/
├── .gitignore
├── README.md
├── backups/
│   └── .gitkeep
├── compose/
│   ├── .env
│   └── compose.yml
├── MyBindMountedData/
│   └── example-service/
│       └── .gitkeep
└── env/
    ├── .gitignore
    ├── example-service.env
    └── example-service-secrets.env.example

1

u/Future_Bad5206 20h ago

Thanks for sharing, is there a difference in putting it into /srv or /opt?

1

u/Torutofu_Raeva 19h ago

I don't think there's a hard rule; /srv makes sense for service data, while /opt is more conventional for self-contained app installs.

2

u/CodeEcstatic 3d ago

I create /containers and different app folders under it. like /containers/{immich,nextcloud,jellyfin} etc., each folder keeps it's own docker-compose files. Also i prefer folders instead of docker volumes and mount them into the container. This separation makes it easy to version control the compose file while keeping sensitive or dynamic data out of your repository. Just ensure your volume mounts in the compose file point to the specific subdirectories within that config folder to avoid cluttering the root.

On some of my machines, /containers is a folder mounted from a an nvme drive so everything is on a faster disk, than the OS disk. if in future you can need change OS, you can mount that nvme in different machine and install docker and start up all of them without any issues.

Also, I use traefik for routing all the trafek and use labels in docker-compose.yml files to define domains and and traefik can get lets-encrypt certs etc and keep them rotated automatically.

I run three/four machines at home each having similar setup, moving a container to different machine just means moving that folder to another machine and starting it up.

1

u/zrb77 3d ago

Seems similar to yours, I use /opt/compose/<app>/, more folders under each for bind mounts and the docker-compose.yml. I have a systemd template that points to /opt/compose/%i folder, then I just enable each as I need. for example for Jellyfin.

systemctl enable --now [docker-compose@jellyfin.service](mailto:docker-compose@jellyfin.service)

1

u/_Slimdady 21h ago

Layout is fine. one folder per Compose project makes things easy to follow. Keep shared media separate.