In our case, we wanted to have one repository for all our services, because otherwise we would have to create and maintain ECR infrastructure for each single service.
What we did was basically creating one shared repository for all services (Cloudformation in this case):
AWSTemplateFormatVersion: "2010-09-09"
Parameters:
  registryName:
    Type: String
    Default: services
Resources:
  ecr:
    Type: AWS::ECR::Repository
    Properties:
      RepositoryName: !Ref registryName
      ImageTagMutability: MUTABLE
… and then when building the services, we would use SERVICENAME_VERSION as the convention for the actual image/version:
#!/bin/bash
set -e
export AWS_ACCOUNT="123456789000"
export AWS_DEFAULT_REGION="eu-central-1"
export SERVICE_NAME="demo-service"
export SERVICE_VERSION="${SERVICE_VERSION:-latest}"
export IMAGE_NAME="$AWS_ACCOUNT.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com/services:${SERVICE_NAME}_${SERVICE_VERSION}"
aws ecr get-login-password | docker login --username AWS --password-stdin "$AWS_ACCOUNT.dkr.ecr.$AWS_DEFAULT_REGION.amazonaws.com"
docker build -t $IMAGE_NAME .
docker push $IMAGE_NAME
(Simplified, but works.)
UPDATE:
In a real-world example, when you want to pull images into an ECS cluster that is placed in a VPC, you will need to set up VPC endpoints on the ECR. The Cloudformation code for this looks something like this:
  privateLinkEcrApi:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ecr.api"
      PrivateDnsEnabled: true
      VpcId: !ImportValue vpc
      SecurityGroupIds:
        - !ImportValue albSecurityGroup
      SubnetIds:
        - !ImportValue publicSubnetA
        - !ImportValue publicSubnetB
      VpcEndpointType: Interface
  privateLinkEcrDkr:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.ecr.dkr"
      PrivateDnsEnabled: true
      VpcId: !ImportValue vpc
      SecurityGroupIds:
        - !ImportValue albSecurityGroup
      SubnetIds:
        - !ImportValue publicSubnetA
        - !ImportValue publicSubnetB
      VpcEndpointType: Interface
  privateLinkEcrLogs:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.logs"
      PrivateDnsEnabled: true
      VpcId: !ImportValue vpc
      SecurityGroupIds:
        - !ImportValue albSecurityGroup
      SubnetIds:
        - !ImportValue publicSubnetA
        - !ImportValue publicSubnetB
      VpcEndpointType: Interface
  privateLinkEcrS3:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
      VpcId: !ImportValue vpc
      SecurityGroupIds:
        - !ImportValue albSecurityGroup
      SubnetIds:
        - !ImportValue publicSubnetA
        - !ImportValue publicSubnetB
      VpcEndpointType: Interface
  privateLinkEcrS3Gw:
    Type: AWS::EC2::VPCEndpoint
    Properties:
      ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3"
      VpcId: !ImportValue vpc
      RouteTableIds:
        - !ImportValue publicRouteTable
        - !ImportValue privateRouteTableA
        - !ImportValue privateRouteTableB
      VpcEndpointType: Gateway
(NB: You will have to adapt this code as the actual VPC, subnets etc. are set up in a different template, and the actual configuration depends very much on your own environment. But this should get you on the right track.)