Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Build a Docker image, push it to AWS EC2 Container Registry, then deploy it to AWS Elastic Beanstalk
#!/bin/bash
# usage: ./deploy.sh staging f0478bd7c2f584b41a49405c91a439ce9d944657
# license: public domain
BRANCH=$1
SHA1=$2
AWS_ACCOUNT_ID=12345678900
NAME=name-of-service-to-deploy
EB_BUCKET=aws-s3-bucket-to-hold-application-versions
VERSION=$BRANCH-$SHA1
ZIP=$VERSION.zip
aws configure set default.region us-east-1
# Authenticate against our Docker registry
eval $(aws ecr get-login)
# Build and push the image
docker build -t $NAME:$VERSION .
docker tag $NAME:$VERSION $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/$NAME:$VERSION
docker push $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/$NAME:$VERSION
# Replace the <AWS_ACCOUNT_ID> with the real ID
sed -i='' "s/<AWS_ACCOUNT_ID>/$AWS_ACCOUNT_ID/" Dockerrun.aws.json
# Replace the <NAME> with the real name
sed -i='' "s/<NAME>/$NAME/" Dockerrun.aws.json
# Replace the <TAG> with the real version number
sed -i='' "s/<TAG>/$VERSION/" Dockerrun.aws.json
# Zip up the Dockerrun file (feel free to zip up an .ebextensions directory with it)
zip -r $ZIP Dockerrun.aws.json
aws s3 cp $ZIP s3://$EB_BUCKET/$ZIP
# Create a new application version with the zipped up Dockerrun file
aws elasticbeanstalk create-application-version --application-name $NAME-application \
--version-label $VERSION --source-bundle S3Bucket=$EB_BUCKET,S3Key=$ZIP
# Update the environment to use the new application version
aws elasticbeanstalk update-environment --environment-name $NAME \
--version-label $VERSION
# Example Dockerfile
FROM hello-world
{
"AWSEBDockerrunVersion": "1",
"Image": {
"Name": "<AWS_ACCOUNT_ID>.dkr.ecr.us-east-1.amazonaws.com/<NAME>:<TAG>",
"Update": "true"
},
"Ports": [
{
"ContainerPort": "443"
}
]
}
@yefim
Copy link
Author

yefim commented Oct 4, 2016

@theseanstewart great question! I build the docker image with docker build -t $NAME:$VERSION . then push the built (and tagged) image to the Amazon EC2 Container Registry with docker push $AWS_ACCOUNT_ID.dkr.ecr.us-east-1.amazonaws.com/$NAME:$VERSION.

The way the Elastic Beanstalk application environment knows how to deploy itself is the Dockerrun.aws.json file. In that file I specify the docker image to use and create a new application version with that points to the newly built, tagged, and pushed docker image URL. Does that make sense?

@revl-ca
Copy link

revl-ca commented Oct 18, 2016

Is it possible to accomplish this with the awsebcli?

@mskutin
Copy link

mskutin commented Dec 13, 2016

https://gist.github.com/yefim/93fb5aa3291b3843353794127804976f#file-deploy-sh-L28
missing trailing slash
from:
sed -i='' "s/<NAME>/$NAME" Dockerrun.aws.json
to:
sed -i='' "s/<NAME>/$NAME/" Dockerrun.aws.json

@ericbmerritt
Copy link

ericbmerritt commented Dec 27, 2016

@yefim any chance you can explicitly specify a license for this? I am assuming its public domain, but its always nice to be explicit.

Copy link

ghost commented Dec 29, 2016

This is really helpful. Thank you!

@rootux
Copy link

rootux commented Feb 17, 2017

Would like to add a comment for new comers that you need to create a EC2 container first here that will be the $NAME param - https://console.aws.amazon.com/ecs

@sibelius
Copy link

sibelius commented Mar 21, 2017

instead of this

aws s3 cp $ZIP s3://$EB_BUCKET/$ZIP

# Create a new application version with the zipped up Dockerrun file
aws elasticbeanstalk create-application-version --application-name $NAME-application \
    --version-label $VERSION --source-bundle S3Bucket=$EB_BUCKET,S3Key=$ZIP

# Update the environment to use the new application version
aws elasticbeanstalk update-environment --environment-name $NAME \
      --version-label $VERSION

you can use awsebcli

eb deploy ${EB_ENV_NAME}

@stephen-swensen
Copy link

stephen-swensen commented Apr 9, 2017

Super helpful, thanks!

I adapted it so that it can be downloaded and executed with curl / eval as a single self-contained script with project specific env vars pulled out: https://github.com/relayfoods/aws-docker-deploy

@Alexhha
Copy link

Alexhha commented Apr 11, 2017

Note: deploy.sh script won't work for the first time. aws elasticbeanstalk update-environment command will work only for existing environment

# Replace the <NAME> with the real name
sed -i='' "s/<NAME>/$NAME" Dockerrun.aws.json

should contain trailing slash at the end

sed -i "s/<NAME>/$NAME/" Dockerrun.aws.json

@wprater
Copy link

wprater commented Jun 16, 2017

should probably be user to add node_modules to a .dockerignore file as well

@simonguldstrand
Copy link

simonguldstrand commented Jun 30, 2017

@Alexhha, would you just add the aws ecs register-task-definition to be able to use this script without existing env?

@codinronan
Copy link

codinronan commented Aug 13, 2017

@stephen-swensen unbelievable lifesaver. I spent 2 hours reading AWS docs and with your scripts completed the same in < 10 minutes.

Seriously, code shouts, documentation whispers.

@javahometech
Copy link

javahometech commented Sep 29, 2017

How elastic beanstalk knows the credentials of ECS registry?
Thanks,
Hari

@skunkworker
Copy link

skunkworker commented Jan 25, 2018

If you are using docker-compose instead of docker build

In deploy.sh
instead of

docker build -t $NAME:$VERSION .

put this

export IMAGE_NAME=$NAME:$VERSION
docker-compose -f docker-compose.yml build

and add the image: key to your docker-compose.yml file

version: '3.3'
services:
  service_name:
     image: $IMAGE_NAME

Reference:
https://stackoverflow.com/questions/33816456/how-to-tag-docker-image-with-docker-compose

@lmanzieri
Copy link

lmanzieri commented Mar 8, 2018

Hello All,

I'm doing different.
I'm using AWSEBCLI to deploy the application with the structure bellow:

  • .
  • .elasticbeanstalk/config.yml
  • Dockerrun.aws.json
  • (Dockerfile and all files of application)

So in config.yml is necessary put the keys bellow:

deploy:
  artifact: Dockerrun.aws.json

The archive will be like this:

branch-defaults:
  master:
    environment: myEnv
deploy:
  artifact: Dockerrun.aws.json
global:
  application_name: myApp
  default_ec2_keyname: myKey
  default_platform: arn:aws:elasticbeanstalk:sa-east-1::platform/Docker running on
    64bit Amazon Linux/2.8.4
  default_region: sa-east-1
  include_git_submodules: true
  instance_profile: null
  platform_name: null
  platform_version: null
  profile: null
  sc: git
  workspace_type: Application

then is just execute the command 'eb deploy' in main directory os your app.

@rich-allen-gov
Copy link

rich-allen-gov commented Jun 27, 2018

@javahometech when using elastic beanstalk ,and ecr, you set up an iam role. So then when the following was run:

eval $(aws ecr get-login)

aws ecr get-login prints out a docker login command with a temporary credential. That output then gets executed with the eval statement and that's how auth is handled.

@ivarprudnikov
Copy link

ivarprudnikov commented Nov 25, 2018

sed command contains minor "error":
sed -i='' "s/<AWS_ACCOUNT_ID>/$AWS_ACCOUNT_ID/" Dockerrun.aws.json will make a backup file called Dockerrun.aws.json= which is not what would be expected. Assume because -i was used the expectation is that file will be modified in place.

Documentation https://linux.die.net/man/1/sed
-i='' needs to be replaced with either --in-place='' or with -i '' or with a sensible backup extension -i.bak
First 2 options will not work on all systems and I found the last one -i.bak a bit more reliable when running sed on OSX and on Linux

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment