Search code examples
amazon-web-servicesdockeramazon-ec2amazon-ecs

Error while deploying a Docker container into EC2 Container Services via GitLab Pipeline


I am trying to deploy a Docker container into EC2 Container Services with GitLab pipelines. I have created the Cluster in AWS already and 2 instances are also running. The problem is that once the command

ecs-cli compose --file ./Documents/Development/workillence/docker-compose-test.yml service up
--container-name testContainer --container-port 8080 #--role arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceRole
--target-group-arn arn:aws:elasticloadbalancing:us-east-2:084622260700:targetgroup/TestTG/af0fbec5b9cc869f

is executed I receive the following error:

WARN[0000] Skipping unsupported YAML option for service...  option name=build service name=testContainer
ERRO[0001] Error registering task definition             error="ClientException: Container.image should not be null or empty.\n\tstatus code: 400, request id: 27277917-8d8e-11e7-8cb2-8d5ad96f4568" family=ecscompose-workillence
ERRO[0001] Create task definition failed                 error="ClientException: Container.image should not be null or empty.\n\tstatus code: 400, request id: 27277917-8d8e-11e7-8cb2-8d5ad96f4568"
FATA[0001] ClientException: Container.image should not be null or empty.

This is a screenshot from my AWS repo:

enter image description here

The image does not seem to be empty.

This is how my CI file looks like:

image: docker:latest
services:
  - docker:dind
stages:
  - build
  - deploy

testBuild:
  stage: build
  script:
    - docker version
    - docker build -t 084622260700.dkr.ecr.us-east-2.amazonaws.com/testrepo:latest app/
    - docker images 
    - docker login -u AWS -p <password> 084622260700.dkr.ecr.us-east-2.amazonaws.com
    - docker push 084622260700.dkr.ecr.us-east-2.amazonaws.com/testrepo:latest

testDeploy:
  stage: deploy
  image: python:3-alpine
  variables:
    AWS_REGION: "us-east-2"
    AWS_ACCESS_KEY_ID: "key"
    AWS_SECRET_ACCESS_KEY: "key"
    PROD_TARGET_GROUP_ARN: "arn:aws:elasticloadbalancing:us-east-2:084622260700:targetgroup/TestTG/af0fbec5b9cc869f"
    ECS_CLUSTER: "testCluster"
    AWS_KEY_PAIR: "testKP.pem"
    AWS_VPC: "vpc-0419416d"
    AWS_SUBNETS: "subnet-ad6cdfe0,subnet-ad6cdfe0,subnet-0fc1aa74"
    AWS_INSTANCE_TYPE: "t2.micro"
    AWS_INSTANCE_COUNT: "2" #Number of instances to scale to
    AWS_ROLE: "arn:aws:iam::aws:policy/service-role/AmazonEC2ContainerServiceRole"
  before_script:
##### Install AWS ECS-CLI #####
    - apk add --update curl
    - curl -o /usr/local/bin/ecs-cli https://s3.amazonaws.com/amazon-ecs-cli/ecs-cli-linux-amd64-latest
    - chmod +x /usr/local/bin/ecs-cli
  script:
##### Configure ECS-CLI, run the container and scale to 2 instances #####
    - ecs-cli configure --region $AWS_REGION --access-key $AWS_ACCESS_KEY_ID --secret-key $AWS_SECRET_ACCESS_KEY --cluster $ECS_CLUSTER
    - ecs-cli up --keypair $AWS_KEY_PAIR --capability-iam -c $ECS_CLUSTER --instance-type t2.micro --size 2 --vpc $AWS_VPC --subnets $AWS_SUBNETS --force
##### This docker-compose.yml is the one described above #####
    - ecs-cli compose --file docker-compose.yml service up --target-group-arn $PROD_TARGET_GROUP_ARN --container-name app --container-port 8080 --role $AWS_ROLE
    - ecs-cli compose --file docker-compose.yml service scale 2
  environment:
    name: ci
##### This is the URL seen under 'DNS name' when the LB was created #####
    url: TestLB-1717492587.us-east-2.elb.amazonaws.com
  only:
    - aws

And this is how the compose file looks like:

  app:
    image: 084622260700.dkr.ecr.us-east-2.amazonaws.com/testrepo:latest
    command: yarn run start-dev
    links:
      - mongodb
      - redis
      - elasticsearch
    ports:
      - '8000:8000'
      - '5858:5858'
      - '9229:9229'
      - '80:8080'
    environment:
      NODE_ENV: local
    volumes:
      - ./testrepo/.:/opt/app
  mongodb:
    build: docker/definitions/mongo
    ports:
      - "27017:27017"
  redis:
    build: docker/definitions/redis
    ports:
      - "6379:6379"
  elasticsearch:
    build: docker/definitions/elasticsearch
    ports:
      - "9200:9200"
      - "9300:9300"

Have you ever faced the same or similar issue and probably how did you solve it?


Solution

  • The issue is clear. Your compose file is for build and doesn't have image

    WARN[0000] Skipping unsupported YAML option for service...  option name=build service name=testContainer
    ERRO[0001] Error registering task definition             error="ClientException: Container.image should not be null or empty.\n\tstatus code: 400, request id: 27277917-8d8e-11e7-8cb2-8d5ad96f4568" family=ecscompose-workillence
    ERRO[0001] Create task definition failed                 error="ClientException: Container.image should not be null or empty.\n\tstatus code: 400, request id: 27277917-8d8e-11e7-8cb2-8d5ad96f4568"
    FATA[0001] ClientException: Container.image should not be null or empty.
    

    So what you need is

      mongodb:
        build: docker/definitions/mongo
        image: <image from aws or docker hub>
        ports:
          - "27017:27017"
      redis:
        build: docker/definitions/redis
        image: <image from aws or docker hub>
        ports:
          - "6379:6379"
      elasticsearch:
        build: docker/definitions/elasticsearch
        image: <image from aws or docker hub>
        ports:
          - "9200:9200"
          - "9300:9300"
    

    Once you add that it should work. If having build value creates a problem then you can use two separate compose files. One with build values and one with image values