Just to share why I think it works like it does:
The profiles are for optional services not to use as filters like you would with labels in some cases. So when you define a profile for a service, it becomes optional and while the default services will always be included, services with profiles only when you allow that profile.
So when you want to use “down”, you still need to allow those profiles, but again, the defaults are included.
What you can do at the moment is define a “default” profile for all services that don’t have one. It is easy if you made the compose project, but if you don’t want to permanently add profiles to all services or it is an existing project, you can generate the default profile into a compose.override.yml with this command in a linux shell:
docker compose config --services \
| awk 'BEGIN {printf "services:\n"} \
{printf " " $0 ":\n profiles: [default]\n"}' \
> compose.override.yml
Since the main command above is docker compsoe config --services and it has no profile option, services with profiles are not allowed here either and you get only profileless services. The awk command then generates the content of the override compose file which is read by docker compose commands automatically.
Here is my test compose file:
services:
default:
image: nginx
default2:
image: nginx
a:
image: nginx
profiles:
- a
depends_on:
- default
b:
image: nginx
profiles:
- b
ab:
image: nginx
profiles:
- a
- b
And the generated override file:
services:
default:
profiles: [default]
default2:
profiles: [default]
In this example service “a” depends on “default”, so when you try to run
docker compose --profile a down
you will get:
service "a" depends on undefined service "default": invalid compose project
What's next:
Debug this Compose error with Gordon → docker ai "help me fix this compose error"
The following command would work:
docker compose --profile default --profile a down
Output:
[+] down 4/4
✔ Container profiles-a-1 Removed 0.1s
✔ Container profiles-default2-1 Removed 0.2s
✔ Container profiles-default-1 Removed 0.1s
✔ Network profiles_default Removed
Since service “b” has no dependency, you can easily delete that
docker compose --profile b down
Output:
[+] down 3/3
✔ Container profiles-ab-1 Removed 0.2s
✔ Container profiles-b-1 Removed 0.1s
✔ Network profiles_default Removed
So generating the default profile for alls ervices without other profiles can be a workaround if you don’t mind that for services with dependencies you have to allow the default profile as well, otherwise the dependency will not be found.
And of course, since all your services wil have profiles, a simply docker compose down will not delete anything.