Possible to use AWS ECR for image registry?

Just wondering if anyone has been able to use ECR to pull images from.

I think it should work, but you need to be logged in to ECR and use --with-registry-auth. Details here: https://beta.docker.com/docs/deploy/

Let us know if you can’t get it working, and if so, how it’s failing and how to reproduce.

Yes, I am using ECR and it works fine. As @friism said, your service create and service update commands need to include the --with-registry-auth flag. You will first need to log the manager node into ECR.

Keep in mind that the tokens provided by aws when you call aws ecr get-login are only good for 12 hours. If the manager node tries to access ECR after 12 hours (e.g., if it auto-scales your service or a container fails and it tries to repull the image from a new node), it will fail! I’m not sure how to work around this yet.

FWIW, below is a script I use to create/update services (tested with Docker for AWS betas 5 and 6). It doesn’t deal with volumes, networks or multiple replicas, but those should be relatively easy to add to the service create/update commands.

Prerequisites:

  • You need to run it from a terminal where the aws and jq commands are available.
  • Your ~/.aws/credentials file needs to contain credentials that have all the appropriate permissions.
  • The private key from the AWS key pair you used when creating the cluster is configured for the SSH ELB host name in your ~./ssh/config

Call it like so:

./deploy.sh my-cluster my-service 80:80 \
  [aws-acct-number].dkr.ecr.[aws-region].amazonaws.com/[repo-name]/[image-name]:[image-tag]

deploy.sh

#!/bin/bash

CLUSTER_NAME=$1
SERVICE_NAME=$2
PORTS=$3
FULL_IMAGE_NAME=$4

echo ""
echo "----- Deploying $SERVICE_NAME to AWS docker cluster $CLUSTER_NAME -----"

CF_STACKS=$(aws cloudformation describe-stacks --stack-name $CLUSTER_NAME)
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

ELB_QUERY=".Stacks[] | select(.StackName == \"$CLUSTER_NAME\") | .Outputs[] | select(.OutputKey == \"DefaultDNSTarget\") | .OutputValue"
SERVICE_ELB_ENDPOINT=$(echo "$CF_STACKS" | jq -r "$ELB_QUERY")
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

SSH_QUERY=".Stacks[] | select(.StackName == \"$CLUSTER_NAME\") | .Outputs[] | select(.OutputKey == \"SSH\") | .OutputValue"
MANAGER_SSH_COMMAND=$(echo "$CF_STACKS" | jq -r "$SSH_QUERY")
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

echo "Logging cluster manager into ECR..."
# remove -e option from 'docker login' returned by 'aws ecr get-login'
# because it is deprecated and produces a warning.
$MANAGER_SSH_COMMAND eval $(aws ecr get-login | sed s/"\-e none "// )
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

SERVICE_ID=$($MANAGER_SSH_COMMAND docker service ls --filter name=$SERVICE_NAME -q)
rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi

if [[ -n "$SERVICE_ID" ]]
then
  echo "Service $SERVICE_NAME exists. Updating it with new image..."
  $MANAGER_SSH_COMMAND docker service update \
    --image $FULL_IMAGE_NAME \
    --with-registry-auth \
    $SERVICE_NAME
  rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi
else
  echo "Creating service $SERVICE_NAME..."
  $MANAGER_SSH_COMMAND docker service create \
    --name $SERVICE_NAME \
    --publish $PORTS \
    --with-registry-auth \
    $FULL_IMAGE_NAME
  rc=$?; if [[ $rc != 0 ]]; then exit $rc; fi
fi

PUBLISHED_PORT=$(echo $PORTS | sed s/:.*//)

echo "Docker service $SERVICE_NAME will be available at:"
echo "  $SERVICE_ELB_ENDPOINT:$PUBLISHED_PORT"
echo ""
1 Like

Hey @jtbennett, did you happen to find a solution to the 12 hour credential expiration? Part of me wonders if we couldn’t just add the AmazonEC2ContainerRegistryReadOnly Policy to the generated <name>--ProxyRole-<unique> role that the cloud formation generates and the InstanceProfile runs using.

I tried this initially without any success so I’m guessing I’m missing something. However that works fine for EB and ECS for access to ECR, but perhaps there’s magic there I’m missing.

This is also being discussed here: https://github.com/docker/for-aws/issues/5 lets move this discussion over there so that we can have it in one place.