How to approach dynamic environments per Git feature branch workflow?
What you're after is referred to as "Review Apps" by Gitlab and Heroku. It relies on a CI/CD system that runs pipelines on every branch, and exposes the branch name to the build (usually as an environment variable). You can then use the branch name to namespace the resources created by your Infrastructure as Code.

You have mentioned Docker so I will use Kubernetes as an example, but this approach can be applied to just about any deployment method.

Normally when deploying a Docker image, you would name your deployment after the app, e.g.:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app
# ...


Using either some kind of preprocessor (Jinja, envsubst, etc.) or a tool like Helm we can pass in some parameters to make the resource include the branch name during the pipeline:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-app-${BRANCH_NAME}
# ...


This way, branches do not deploy on top of each other. The resources they deploy are isolated to the branch.

For an API or web app, you'll want some kind of DNS name and load balancer. Kubernetes handles this quite easily with Ingress and DNS controllers, so I'll use CloudFormation as an example this time.

AWSTemplateFormatVersion: '2010-09-09'
Parameters:
  Branch:
    Type: String
  Environment:
    Type: String
  Zone:
    Type: String

Resources:
# ALB resources omitted for brevity...

  Route53:
    Type: AWS::Route53::RecordSet
    Properties:
      Name: !Sub
        - "my-app-${Branch}.${Environment}.${Zone}"
      HostedZoneName: !Ref Zone
      Type: A
      AliasTarget:
        HostedZoneId: !GetAtt ALB.CanonicalHostedZoneID
        DNSName: !GetAtt ALB.DNSName


Here we create a DNS record that is very specific to the branch. The DNS record resolves to a load balancer which should point to the containers deployed by the pipeline for this branch. The stack name is also specific to the branch, so pipelines on other branches will not affect it. The end result is that each feature branch will have a dedicated URL (https://my-app-my-feature.dev.example.com) that your developers can use to test and showcase to stakeholders.


  Should we create 6 new servers/containers if we only make changes in application A?


No. This isn't specifically related to Review Apps, but microservices in general should be self-contained: decoupled from each other so that they can be deployed in isolation. Removing dependencies and making small changes will increase your development/deployment velocity.

Considerations

Cleanup

What happens when you merge or delete your branch? Without setting up some kind of cleanup, those containers and DNS records will sit around forever. You need some kind of cleanup. Something that just runs periodically and deletes resources associated to old branches is pretty simple to write, or you could take webhooks from your git server and delete those resources on an event.

Databases

Some resources may not warrant getting deployed per-branch, although this should be the exception rather than the norm. You probably don't want to deploy a new database every time someone makes a branch (perhaps unless you have a good schema management tool and DB population scripts). You can have all deployments connect back to the same DB. Ensure that any changes you make to the schema are backwards compatible at least one version behind.