In docker compose a service is identified by project name and service name. Since you change neither of both, you replace the existing service. You need to change at least the project name as well. Changing the service name (which is app in your case) is not suffiecient, as compose will complain about orphaned services. By default the project name is the folder name.
Not sure how you come to this conclusion, but image: is repsonsible to determine the image. The service name you used is app. Though, service names (the node underneath ‘services:’ ) are static in a docker-compose.yml and can not be replaced with variables.
If you want to be able to use variables everywhere in the docker-compose.yml, you might want about using go templating or envsubst in the simplest case. You can render your docker-compose.yml and pipe it into docker-compose like this: envsubst < docker-compose.template | docker-compose -f - {more options} up -d. You need to export variables in order to make envsubst render them in memory for the file docker-compose.template.
sorry for the bad English but that’s what I try to express: I cannot dynamically change the service name.
And since changing image name won’t work ( I’ve tested it), I think the only way might be dynamically change the project name that you mentioned earlier.
With what is buildin in docker: yes, the project name is your only option.
Though, my suggestion to use envsubst goes beyond what is build in into docker. You can archive simple templating (without any conditional rendering) with it without fighting with complexity
is it possible to use the pre-existing volumes/network if I’m going to dynamically change the project name instead of creating projectname_volume/network everytime?
EDIT:
it seems I can’t achieve this if I didn’t separate my app service to another compose file?
let’s say my original docker-compose.yml is like: