I need to run a docker container in AWS ECS. I do NOT have access to the source code for the image. This is a private image, from a private repo that I have uploaded to AWS ECR. I have created an AWS ECS Task Definition to run the container inside a service, inside a cluster. The image shows as being up and running but I cannot hit it via my browser. I know that all the network settings are correct because I can hit a simple hello world app that I also deployed to test.
There is also a command I need to run before: docker run --env-file <environment_variables_file> <image>:<tag> rake db:reset && rake db:seed.
According to the instructions for this docker image, the run command for it is: docker run -d --name <my_image_name> --env-file <environment_variables_file> -p 8080:80 <image>:<tag>.
I can run this image locally on my laptop with no issues, deploying it to AWS is that problem.
My question is how do I provide the environment_variables_file to the image? Where do I upload the file and how do I pass it? How do I run the command to init the DB before the image runs?
Since Nov 2020, ECS does support env files (blog post), but they must be hosted on S3:
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/taskdef-envfiles.html
Pasting the essentials for reference. Under container definition:
"environmentFiles": [
{
"value": "arn:aws:s3:::s3_bucket_name/envfile_object_name.env",
"type": "s3"
}
]
The task execution role also needs the following permission:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:GetObject"
],
"Resource": [
"arn:aws:s3:::s3_bucket_name/envfile_object_name.env"
]
},
{
"Effect": "Allow",
"Action": [
"s3:GetBucketLocation"
],
"Resource": [
"arn:aws:s3:::s3_bucket_name"
]
}
]
}
Amazon ECS doesn't support environment variable files. You can set environment variables inside task definition. For example:
"environment" : [
{ "name" : "string", "value" : "string" },
{ "name" : "string", "value" : "string" }
]
Please read following instructions for more details.
Update:
AWS now provides a way -
https://docs.aws.amazon.com/AmazonECS/latest/developerguide/taskdef-envfiles.html
Related
I need to pull docker images from on premise. However, I don't have access to AWS keys to be able to perform such an action against a private repository. How can I pull ECR images without AWS authentication? I've noticed ECR public repository, however, I still need some level of restriction to protect the repos contents.
Yes, you can authenticate temporarily. As document pointed;
You can use temporary security credentials to make programmatic requests for AWS resources using the AWS CLI or AWS API (using the AWS SDKs). The temporary credentials provide the same permissions as long-term security credentials, such as IAM user credentials.
Reference : https://docs.aws.amazon.com/IAM/latest/UserGuide/id_credentials_temp_use-resources.html
Also, If there is no way to succeed the authentication this way or any other way,
You can use public registries + registry policies. You can ALLOW certain IPs/services/users to reach your registry. Example registry policy is below;
{
"Version": "2012-10-17",
"Id": "ECRPolicyId1",
"Statement": [
{
"Sid": "IPAllow",
"Effect": "Deny",
"Principal": "*",
"Action": "ecr:*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
1.2.3.4/32,
2.3.4.5/32
]
},
"IpAddress": {
"aws:SourceIp": "0.0.0.0/0"
}
}
}
]
}
I have attached the following policy to my EC2 instance
{
"Sid": "ECRPull",
"Effect": "Allow",
"Action": [
"ecr:Describe*",
"ecr:Get*",
"ecr:List*",
"ecr:BatchGetImage",
"ecr:BatchCheckLayerAvailability"
],
"Resource": [
"arn:aws:ecr:eu-west-1:123456789:repository/my-repo"
]
}
However the following docker pull from within the instance fails, why?
docker pull 123456789.dkr.ecr.eu-west-1.amazonaws.com/my-repo:sometag
no basic auth credentials
docker command doesn't call AWS IAM service as it's not part of AWS. You've to use an aws command before issuing docker commands.
aws ecr get-login gives you a temporary token.
Use the token and username as AWS to do docker login
docker login –u AWS –p <token from previous command> –e none https://<aws_account_id>.dkr.ecr.us-east-1.amazonaws.com
What is the best practice to pull a Docker image located in a repository in ECS from an EC2 instance?
I pushed Docker images into my repository located under ECS.
I would like to launch an EC2 instance and pull these images from it.
I am used to take advantage of the ECS task. To just run a Docker container for 5min, I need to go to Auto-Scale, set the minimum at 1, go to the ECS page, wait for an instance to be up and run my task. Too annoying for my personal use. I'd like to run it quickly and stop it quickly.
I wanted to simply run my Docker container but ok, that's not possible, then I am thinking of creating an EC2 template that will directly run my Docker container inside an EC2 instance.
How to do it?
How can I handle the keys/users and the AWS CLI inside my EC2? (Access/Secret Access Key are limited to 30min, I can't write it clearly in the User Data of an EC2 instance/template)
I think my need is very basic and I couldn't find the best way to do it. Blog articles mainly explain how to run Docker on Linux, not the best way to do it on AWS.
This can be accomplished with a combination of the EC2 instance role, and a script that performs docker login followed by a docker pull for your pushed image.
Pre-requisites: An EC2 instance with the AWS CLI and Docker installed.
First, you'll have to add the inbuilt AmazonEC2ContainerRegistryReadOnly IAM policy to your EC2 instance's IAM role (this grants read access to all pushed images). If you'd like things to be more restrictive, you can use the following policy instead:
{
"Version": "2012-10-17",
"Statement": [
{
"Sid": "GrantSingleImageReadOnlyAccess",
"Effect": "Allow",
"Action": [
"ecr:BatchCheckLayerAvailability",
"ecr:GetDownloadUrlForLayer",
"ecr:GetRepositoryPolicy",
"ecr:DescribeRepositories",
"ecr:ListImages",
"ecr:DescribeImages",
"ecr:BatchGetImage"
],
"Resource": "<aws-account-id>.dkr.ecr.<region>.amazonaws.com/<image-name>"
},
{
"Sid": "GrantECRAuthAccess",
"Effect": "Allow",
"Action": "ecr:GetAuthorizationToken",
"Resource": "*"
}
]
}
Next, you'll have to create a script to perform login and image pull for you. A typical script would look something like this:
$(aws ecr get-login-password --region <region>);
docker pull <aws-account-id>.dkr.ecr.<region>.amazonaws.com/<image-name>:<optional-tag>;
Note that this script will have to run as the root user for proper Docker daemon access.
Another way of solving this all together would be to look into automation options for ECS tasks.
I'm trying to deploy a GitHub project to a EC2 Instance using AWS CodeDeploy. After following 2 video tutorials an a bunch of Google answer, I'm still getting the following error:
2017-02-01 12:20:08 INFO [codedeploy-agent(1379)]: master 1379: Spawned child 1/1
2017-02-01 12:20:09 INFO [codedeploy-agent(1383)]: On Premises config file does not exist or not readable
2017-02-01 12:20:09 INFO [codedeploy-agent(1383)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandExecutor: Archives to retain is: 5}
2017-02-01 12:20:09 INFO [codedeploy-agent(1383)]: Version file found in /opt/codedeploy-agent/.version.
2017-02-01 12:20:09 ERROR [codedeploy-agent(1383)]: InstanceAgent::Plugins::CodeDeployPlugin::CommandPoller: Missing credentials - please check if this instance was started with an IAM instance profile
I have two IAM:
CodeDeployInstanceRole
CodeDeployServiceRole
CodeDeployInstanceRole for the EC2 Instance
Policy Name: AmazonEC2RoleforAWSCodeDeploy
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:GetObject",
"s3:GetObjectVersion",
"s3:ListObjects"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
Policy Name: AutoScalingNotificationAccessRole
{
"Version": "2012-10-17",
"Statement": [{
"Effect": "Allow",
"Resource": "*",
"Action": [
"sqs:SendMessage",
"sqs:GetQueueUrl",
"sns:Publish"
]
}
]
}
Trust Relationship
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"codedeploy.amazonaws.com",
"ec2.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
CodeDeployServiceRole for CodeDeploy
Policy Name: AWSCodeDeployRole
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"autoscaling:CompleteLifecycleAction",
"autoscaling:DeleteLifecycleHook",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribeLifecycleHooks",
"autoscaling:PutLifecycleHook",
"autoscaling:RecordLifecycleActionHeartbeat",
"autoscaling:CreateAutoScalingGroup",
"autoscaling:UpdateAutoScalingGroup",
"autoscaling:EnableMetricsCollection",
"autoscaling:DescribeAutoScalingGroups",
"autoscaling:DescribePolicies",
"autoscaling:DescribeScheduledActions",
"autoscaling:DescribeNotificationConfigurations",
"autoscaling:DescribeLifecycleHooks",
"autoscaling:SuspendProcesses",
"autoscaling:ResumeProcesses",
"autoscaling:AttachLoadBalancers",
"autoscaling:PutScalingPolicy",
"autoscaling:PutScheduledUpdateGroupAction",
"autoscaling:PutNotificationConfiguration",
"autoscaling:PutLifecycleHook",
"autoscaling:DescribeScalingActivities",
"autoscaling:DeleteAutoScalingGroup",
"ec2:DescribeInstances",
"ec2:DescribeInstanceStatus",
"ec2:TerminateInstances",
"tag:GetTags",
"tag:GetResources",
"sns:Publish",
"cloudwatch:DescribeAlarms",
"elasticloadbalancing:DescribeLoadBalancers",
"elasticloadbalancing:DescribeInstanceHealth",
"elasticloadbalancing:RegisterInstancesWithLoadBalancer",
"elasticloadbalancing:DeregisterInstancesFromLoadBalancer"
],
"Resource": "*"
}
]
}
Trust Relationship
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Principal": {
"Service": [
"codedeploy.amazonaws.com",
"ec2.amazonaws.com"
]
},
"Action": "sts:AssumeRole"
}
]
}
EC2 Instance
I spin my own image that I have created based on Debian so I have NodeJS already installed. When I spin the new instance I also paste the following code in the User data text area to make sure CodeDeploy is installed.
#!/bin/bash -x
REGION=$(curl 169.254.169.254/latest/meta-data/placement/availability-zone/ | sed 's/[a-z]$//') &&
sudo apt-get update -y &&
sudo apt-get install -y python-pip &&
sudo apt-get install -y ruby &&
sudo apt-get install -y wget &&
cd /home/admin &&
wget https://aws-codedeploy-$REGION.s3.amazonaws.com/latest/install &&
chmod +x ./install &&
sudo ./install auto &&
sudo apt-get remove -y wget &&
sudo service codedeploy-agent start
Debugging
If I log in in the EC2 instance that I have create, and execute the following command:
echo $(curl http://169.254.169.254/latest/meta-data/iam/security-credentials/)
I get the following response CodeDeployInstanceRole
When I then execute
curl http://169.254.169.254/latest/meta-data/iam/security-credentials/CodeDeployInstanceRole
I get the following response
{
"Code" : "Success",
"LastUpdated" : "2017-02-01T12:38:07Z",
"Type" : "AWS-HMAC",
"AccessKeyId" : "THE_KEY",
"SecretAccessKey" : "SECRET",
"Token" : "TOKEN",
"Expiration" : "2017-02-01T19:08:43Z"
}
On GitHub I see that CodeDeploy never accesses my repo even when I select deployment using GitHub, I set the right repo name, and commit ID.
Question
What am I missing?
I ran into the same issue. Briefly what caused the problem:
Launch an instance WITHOUT any roles attached to it
Then install a codedeploy-agent on that machine
Only lastly attach an IAM role to the machine
Result: I get the error: Missing credentials - please check if this instance was started with an IAM instance profile
Solution: restart the codedeploy agent. Use:
sudo service codedeploy-agent restart
The error should be gone now!
I was getting the "please check if this instance was started with an IAM instance profile". To check if your instance is launched without IAM profile go to AWS console -> your instance -> check in Description tab "IAM role" value, if it's empty then you have launched instance without IAM and here is what to do to solve the issue:
Go to IAM console -> Roles -> Create new role
Select AWS Service -> EC2 -> Next: Permissions(don't change anything) -> Next: Tags -> Next: Review -> Give the name and click Create role.
Go to AWS EC2 console -> select instance -> Actions -> Instance settings -> Attach/replace IAM role -> Select IAM role you just created
Restart codedeploy agent: sudo service codedeploy-agent restart
Try to deploy again and it should work
Turns out that by default Debian doesn't have curl installed. Installing curl before making the curl request to get the region the server is running on was the missing part in the Bash script.
The instance role permissions look good to me. But the IAM instance profile was added only at the first time when the instance was launched. Could you make sure the instances role had the right permissions before launching the instances?
This is what worked for me in 2021 on Ubuntu 16.04
Upgrade from Python 3.5.2 to 3.6
https://www.rosehosting.com/blog/how-to-install-python-3-6-on-ubuntu-16-04/
with sudo ...
cd /opt
wget https://www.python.org/ftp/python/3.6.3/Python-3.6.3.tgz
tar -xvf Python-3.6.3.tgz
cd Python-3.6.3
./configure
apt-get install zlib1g-dev
make
make install
Install latest version of aws cli v1
https://docs.aws.amazon.com/cli/latest/userguide/install-linux.html
cd ~
curl "https://s3.amazonaws.com/aws-cli/awscli-bundle.zip" -o "awscli-bundle.zip"
unzip awscli-bundle.zip
sudo ./awscli-bundle/install -i /usr/local/aws -b /usr/local/bin/aws
Modify Instance Metadata
https://docs.aws.amazon.com/cli/latest/reference/ec2/modify-instance-metadata-options.html
aws ec2 modify-instance-metadata-options \
--instance-id ${FOO_ID} \
--http-tokens optional \
--http-endpoint enabled
Install the CodeDeploy agent for Ubuntu Server
https://docs.aws.amazon.com/codedeploy/latest/userguide/codedeploy-agent-operations-install-ubuntu.html
sudo apt-get update
sudo apt-get install ruby
sudo apt-get install wget
cd /home/ubuntu
wget https://aws-codedeploy-us-west-2.s3.us-west-2.amazonaws.com/latest/install
chmod +x ./install
sudo ./install auto
sudo service codedeploy-agent restart
sudo service codedeploy-agent status
To view deployment log files on Amazon Linux, RHEL, and Ubuntu Server instances
https://docs.aws.amazon.com/codedeploy/latest/userguide/deployments-view-logs.html
tail -f /var/log/aws/codedeploy-agent/codedeploy-agent.log
tail -f /opt/codedeploy-agent/deployment-root/deployment-logs/codedeploy-agent-deployments.log
Detach the profile from EC2 and then attach it back (Actions -> Security). Finally restart the agent with
sudo service codedeploy-agent restart
My case is slightly different from other answers. My profile looks correct and it has correct policy. And the EC2 is attached to the role - at least that what I see in AWS console.
The root cause is that the EC2 do not has a correct profile with it due to some regeneration of the same-name profile role. This can confirmed with curl http://169.254.169.254/latest/meta-data/iam/info
404 means something wrong.
I am trying to download AWS Codedeploy Agent file in my Amazon Linux. I followed instructions as mentioned in http://docs.aws.amazon.com/codedeploy/latest/userguide/how-to-run-agent.html, for Amazon Linux, have created appropriate instance profile, service role etc. Everything is latest (Amazon Linux, CLI Packages, it is a brand new instance and I have tried this with at least 3 more brand new instances with same result). All instances have full outbound internet access.
But following statement for downloading install from S3 always fails,
aws s3 cp s3://aws-codedeploy-us-east-1/latest/install . --region us-east-1
With Error,
A client error (403) occurred when calling the HeadObject operation: Forbidden
Completed 1 part(s) with ... file(s) remaining
Can anyone help me with this error?
I figured out the problem, According to Codedeploy documentation for IAM Instance profile
http://docs.aws.amazon.com/codedeploy/latest/userguide/how-to-create-iam-instance-profile.html
following permissions needs to be given to your IAM instance profile.
{
"Version": "2012-10-17",
"Statement": [
{
"Action": [
"s3:Get*",
"s3:List*"
],
"Effect": "Allow",
"Resource": "*"
}
]
}
But I limited the resource to my code bucket since I don't want my instances to access other buckets directly. But turns out I also need to give additional permission for aws-codedeploy-us-east-1/* s3 resource for being able to download the agent. This is not very clear in the document for setting up IAM instance profile for Codedeploy.
More restrictive policy that works:
{
"Version": "2012-10-17",
"Statement": [
{
"Effect": "Allow",
"Action": [
"s3:Get*",
"s3:List*"
],
"Resource": [
"arn:aws:s3:::aws-codedeploy-us-east-1/*",
"arn:aws:s3:::aws-codedeploy-us-west-1/*",
"arn:aws:s3:::aws-codedeploy-us-west-2/*",
"arn:aws:s3:::aws-codedeploy-ap-south-1/*",
"arn:aws:s3:::aws-codedeploy-ap-northeast-2/*",
"arn:aws:s3:::aws-codedeploy-ap-southeast-1/*",
"arn:aws:s3:::aws-codedeploy-ap-southeast-2/*",
"arn:aws:s3:::aws-codedeploy-ap-northeast-1/*",
"arn:aws:s3:::aws-codedeploy-eu-central-1/*",
"arn:aws:s3:::aws-codedeploy-eu-west-1/*",
"arn:aws:s3:::aws-codedeploy-sa-east-1/*"
]
}
]
}