Docker Community Forums

Share and learn in the Docker community.

Labels in docker compose not supported by AWS ECS

I’m trying to deploy a (simple) app stack consisting of a front-end, back-end, database and Traefik reverse proxy into AWS ECS. Everything put together in a Docker compose file.

I followed the docs and looked up carefully the supported features here: ECS integration Compose features | Docker Documentation.

Everything runs smoothly locally, incl. the Traefik configuration using labels. However, Traefik does not recognise any services in ECS (despite running with the proper role as described in Traefic docs). I think it is because labels are not defined in the ECS tasks, although they should be supported. When I run docker compose up in the ECS context, I get

WARNING services.deploy.labels: unsupported attribute

Here is the compose file (a bit shorten):

version: "3"

services:
  proxy:
    image: traefik:v2.5
    networks:
      - ${TRAEFIK_PUBLIC_NETWORK?Variable not set}
      - default
    ports:
      - "8080:8080"
      - "80:80"
    command:
      - --providers.ecs=true
      - --providers.ecs.clusters=mycluster
      - --providers.ecs.constraints=Label(`traefik.constraint-label-stack`, `${TRAEFIK_TAG?Variable not set}`)
      - --providers.ecs.exposedbydefault=false
      - --accesslog
      - --log
      - --log.level=DEBUG
      - --api
    x-aws-role:
      Version: "2012-10-17"
      Statement:
        Effect: "Allow"
        Action:
          - "ecs:ListClusters"
          - "ecs:DescribeClusters"
          - "ecs:ListTasks"
          - "ecs:DescribeTasks"
          - "ecs:DescribeContainerInstances"
          - "ecs:DescribeTaskDefinition"
          - "ec2:DescribeInstances"
        Resource:
          - "*"
    deploy:
      labels:
        - traefik.enable=true
        - traefik.docker.network=${TRAEFIK_PUBLIC_NETWORK?Variable not set}
        - traefik.constraint-label=${TRAEFIK_PUBLIC_TAG?Variable not set}
        - traefik.http.middlewares.${STACK_NAME?Variable not set}-https-redirect.redirectscheme.scheme=https
        - traefik.http.middlewares.${STACK_NAME?Variable not set}-https-redirect.redirectscheme.permanent=true
        - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-http.rule=Host(`${DOMAIN?Variable not set}`) || Host(`www.${DOMAIN?Variable not set}`)
        - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-http.entrypoints=http
        - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.rule=Host(`${DOMAIN?Variable not set}`) || Host(`www.${DOMAIN?Variable not set}`)
        - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.entrypoints=https
        - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.tls=true
        - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.tls.certresolver=le
        - traefik.http.services.${STACK_NAME?Variable not set}-proxy.loadbalancer.server.port=80
        - traefik.http.middlewares.${STACK_NAME?Variable not set}-www-redirect.redirectregex.regex=^https?://(www.)?(${DOMAIN?Variable not set})/(.*)
        - traefik.http.middlewares.${STACK_NAME?Variable not set}-www-redirect.redirectregex.replacement=https://${DOMAIN?Variable not set}/$${3}
        - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-https.middlewares=${STACK_NAME?Variable not set}-www-redirect
        - traefik.http.routers.${STACK_NAME?Variable not set}-proxy-http.middlewares=${STACK_NAME?Variable not set}-www-redirect,${STACK_NAME?Variable not set}-https-redirect

  db:
    image: postgres:13
    env_file:
      - .env.local
    environment:
      - PGDATA=/var/lib/postgresql/data/pgdata
    ports:
      - "${POSTGRES_PORT-5432}:5432"
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 1024M

  backend:
    image: '${DOCKER_IMAGE_BACKEND?Variable not set}:${TAG-latest}'
    depends_on:
      - db
    env_file:
      - .env.local
    environment:
      - SERVER_NAME=${DOMAIN?Variable not set}
      - SERVER_HOST=https://${DOMAIN?Variable not set}
    build:
      context: ./
      dockerfile: backend.dockerfile
      args:
        INSTALL_DEV: ${INSTALL_DEV-"false"}
    ports:
      - "${BACKEND_PORT-8000}:8000"
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 1024M
      labels:
        - traefik.enable=true
        - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set}
        - traefik.http.routers.${STACK_NAME?Variable not set}-backend-http.rule=PathPrefix(`/api`) || PathPrefix(`/docs`) || PathPrefix(`/redoc`)
        - traefik.http.services.${STACK_NAME?Variable not set}-backend.loadbalancer.server.port=8000

  frontend:
    image: '${DOCKER_IMAGE_FRONTEND?Variable not set}:${TAG-latest}'
    env_file:
      - .env.local
    build:
      context: ./
      dockerfile: frontend.dockerfile
      args:
        FRONTEND_ENV: ${FRONTEND_ENV-production}
    ports:
      - "${FRONTEND_PORT-3000}:3000"
    deploy:
      resources:
        limits:
          cpus: '0.5'
          memory: 1024M
      labels:
        - traefik.enable=true
        - traefik.constraint-label-stack=${TRAEFIK_TAG?Variable not set}
        - traefik.http.routers.${STACK_NAME?Variable not set}-frontend-http.rule=PathPrefix(`/`)
        - traefik.http.services.${STACK_NAME?Variable not set}-frontend.loadbalancer.server.port=3000


networks:
  traefik-public:
    external: ${TRAEFIK_PUBLIC_NETWORK_IS_EXTERNAL-true}
    name: "sg-mycluster"

Any hints much appreciated!

Thanks!
Jakub