Steps in CDK#

  1. Initialize construct
  2. Zip flask code
  3. Set up options for application, env vars, and app version
  4. Set environment
  5. Make sure environment is built after CDK application
## Deploy to ElasticBeanstalkanstalk-application-packaging-through-cdk-in-typescript-e91b7ffe4928
app_name = "MyApp"
elb_flask_app = elb.CfnApplication(
    self, f"flask-appserver", application_name=app_name
)

## Move app code into S3 for ELB
elb_archive = s3_assets.Asset(
    self,
    f"elb-flask-app-{stage}",
    path=f"{str(Path(__file__).absolute().parents[2])}/app.zip",
)

## Set OptionSettingProperties
option_setting_properties = [
    elb.CfnEnvironment.OptionSettingProperty(
        namespace="aws:autoscaling:launchconfiguration",
        option_name="InstanceType",
        value="t3.small",
    ),
    elb.CfnEnvironment.OptionSettingProperty(
        namespace="aws:autoscaling:launchconfiguration",
        option_name="IamInstanceProfile",
        value="aws-elasticbeanstalk-ec2-role",
    ),
    elb.CfnEnvironment.OptionSettingProperty(
        namespace="aws:autoscaling:launchconfiguration",
        option_name="IamInstanceProfile",
        value="aws-elasticbeanstalk-servicerole",
    ),
    # This is an example of setting up an environment variable
    elb.CfnEnvironment.OptionSettingProperty(
        namespace="aws:elasticbeanstalk:application:environment",
        option_name="ES_DOMAIN",
        value=es_domain.domain_endpoint,
    ),
]

## Set app version properties
app_version_props = elb.CfnApplicationVersion(
    self,
    f"AppVersion-{stage}",
    application_name=app_name,
    source_bundle=elb.CfnApplicationVersion.SourceBundleProperty(
        s3_bucket=elb_archive.s3_bucket_name,
        s3_key=elb_archive.s3_object_key,
    ),
)

## Set environment
elb_env = elb.CfnEnvironment(
    self,
    f"elb-env",
    environment_name=f"elb-env",
    application_name=app_name,
    solution_stack_name="64bit Amazon Linux 2 v3.2.1 running Python 3.8",
    option_settings=option_setting_properties,
    version_label=app_version_props.ref,
)

## Ensure the env isn't built before the app by placing this at the end of your CDK stack file
app_version_props.add_depends_on(elb_flask_app)
elb_env.add_depends_on(elb_flask_app)

Steps in AWS Console#

  1. Launch EC2 instance
  2. SSH into it,
  3. Set up Git keys
    1. See here
    2. Add deploy key to repo
  4. Pull code from Github into instance
  5. Run Flask server
    1. Activate virutal environment
    2. Install dependencies with pip install -r requirements.txt
    3. Set environment variables:
      1. FLASK_ENV=development or FLASK_ENV=prod
    4. Set up uWSGI
      1. Install gcc
      2. Install uWSGI with pip install uwsgi
      3. Install NGinx source 1. Only do steps 1 and 2 from article:
      sudo apt update
      sudo apt install nginx
      # Test firewall
      sudo ufw app list
      sudo ufw allow 'Nginx HTTP'
      sudo ufw status
      
      1. Set up uWSGI configuration with app.ini:
      [uwsgi]
      module = wsgi:app
      master = true
      processes = 5
      socket = myproject.sock
      chmod-socket = 660
      vacuum = true
      die-on-term = true
      
      1. Set up system profile file /etc/systemd/system/myproject.service, taken from linked article
        [Unit]
        Description=uWSGI instance to serve myproject
        After=network.target
        
        [Service]
        User=sammy
        Group=www-data
        WorkingDirectory=/home/sammy/myproject
        Environment="PATH=/home/sammy/myproject/myprojectenv/bin"
        ExecStart=/home/sammy/myproject/myprojectenv/bin/uwsgi --ini myproject.ini
        
        [Install]
        WantedBy=multi-user.target
        
      2. Start with systemctl:
        1. sudo systemctl start myproject
        2. sudo systemctl enable myproject
      3. Set up nginx
        1. Edit /etc/nginx/sites-available/myapp
      server {
          listen 80;
          server_name <EC2 domain>;
      
          location / {
              include uwsgi_params;
              uwsgi_pass unix:/home/ubuntu/myapp/flask-app/myapp.sock;
          }
      }
      
      1. Then link: sudo ln -s /etc/nginx/sites-available/myproject /etc/nginx/sites-enabled
        • Restart nginx service:
          • Update firewall rules
        $ sudo ufw delete allow 5000
        $ sudo ufw allow 'Nginx Full'
        

Sources#

AWS - Deploying a Flask Application to Elastic Beanstalk Packaging a NodeJS application with CDK on Elastic Beanstalk