Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AWS Elastic Beanstalk Container Commands Failing

I've been having a hard time trying to get a successful deployment of my Django Web App to AWS' Elastic Beanstalk. I am able to deploy my app from the EB CLI on my local machine with no problem at all until I add a list of container_commands config file inside a .ebextensions folder.

Here are the contents of my config file:

container_commands:
  01_makeAppMigrations:
    command: "django-admin.py makemigrations"
    leader_only: true
  02_migrateApps:
    command: "django-admin.py migrate"
    leader_only: true
  03_create_superuser_for_django_admin:
    command: "django-admin.py createfirstsuperuser"
    leader_only: true
  04_collectstatic:
    command: "django-admin.py collectstatic --noinput"

I've dug deep into the logs and found these messages in the cfn-init-cmd.log to be the most helpful:

2020-06-18 04:01:49,965 P18083 [INFO] Config postbuild_0_DjangoApp_smt_prod
2020-06-18 04:01:49,991 P18083 [INFO] ============================================================
2020-06-18 04:01:49,991 P18083 [INFO] Test for Command 01_makeAppMigrations
2020-06-18 04:01:49,995 P18083 [INFO] Completed successfully.
2020-06-18 04:01:49,995 P18083 [INFO] ============================================================
2020-06-18 04:01:49,995 P18083 [INFO] Command 01_makeAppMigrations
2020-06-18 04:01:49,998 P18083 [INFO] -----------------------Command Output-----------------------
2020-06-18 04:01:49,998 P18083 [INFO]   /bin/sh: django-admin.py: command not found
2020-06-18 04:01:49,998 P18083 [INFO] ------------------------------------------------------------
2020-06-18 04:01:49,998 P18083 [ERROR] Exited with error code 127

I'm not sure why it can't find that command in this latest environment. I've deployed this same app with this same config file to a prior beanstalk environment with no issues at all. The only difference now is that this new environment was launched within a VPC and is using the latest recommended platform.

Old Beanstalk environment platform: Python 3.6 running on 64bit Amazon Linux/2.9.3

New Beanstalk environment platform: Python 3.7 running on 64bit Amazon Linux 2/3.0.2

I've ran into other issues during this migration related to syntax updates with this latest platform. I'm hoping this issue is also just a simple syntax issue, but I've dug far and wide with no luck...

If someone could point out something obvious that I'm missing here, I would greatly appreciate it! Please let me know if I can provide some additional info!

like image 565
Yamen Alghrer Avatar asked Jun 18 '20 04:06

Yamen Alghrer


2 Answers

Finally got to the bottom of it all, after deep-diving through the AWS docs and forums...

Essentially, there were a lot of changes that came along with Beanstalk moving from Amazon Linux to Amazon Linux 2. A lot of these changes are vaguely mentioned here.

One major difference for the Python platform as mentioned in the link above is that "the path to the application's directory on Amazon EC2 instances of your environment is /var/app/current. It was /opt/python/current/app on Amazon Linux AMI platforms." This is crucial for when you're trying to create the Django migrate scripts as I'll explain further in detail below, or when you eb ssh into the Beanstalk instance and navigate it yourself.

Another major difference is the introduction of Platform hooks, which is mentioned in this wonderful article here. According to this article, "Platform hooks are a set of directories inside the application bundle that you can populate with scripts." Essentially these scripts will now handle what the previous container_commands handled in the .ebextensions config files. Here is the directory structure of these Platform hooks: Platform hooks directory structure

Knowing this, and walking through this forum here, where wonderful community members went through the trouble of filling in the gaps in Amazon's docs, I was able to successfully deploy with the following file set up:

(Please note that "MDGOnline" is the name of my Django app)

.ebextensions\01_packages.config:

packages:
  yum:
    git: []
    postgresql-devel: []
    libjpeg-turbo-devel: []

.ebextensions\django.config:

container_commands:
  01_sh_executable:
    command: find .platform/hooks/ -type f -iname "*.sh" -exec chmod +x {} \;
option_settings:
  aws:elasticbeanstalk:application:environment:
    DJANGO_SETTINGS_MODULE: MDGOnline.settings
  aws:elasticbeanstalk:environment:proxy:staticfiles:    
    /static: static
    /static_files: static_files
  aws:elasticbeanstalk:container:python:
    WSGIPath: MDGOnline.wsgi:application

.platform\hooks\predeploy\01_migrations.sh:

#!/bin/bash

source /var/app/venv/*/bin/activate
cd /var/app/staging

python manage.py makemigrations
python manage.py migrate
python manage.py createfirstsuperuser
python manage.py collectstatic --noinput

Please note that the '.sh' scripts need to be linux-based. I ran into an error for a while where the deployment would fail and provide this message in the logs: .platform\hooks\predeploy\01_migrations.sh failed with error fork/exec .platform\hooks\predeploy\01_migrations.sh: no such file or directory . Turns out this was due to the fact that I created this script on my windows dev environment. My solution was to create it on the linux environment, and copy it over to my dev environment directory within Windows. There are methods to convert DOS to Unix out there I'm sure. This one looks promising dos2unix!

I really wish AWS could document this migration better, but I hope this answer can save someone the countless hours I spent getting this deployment to succeed.

Please feel free to ask me for clarification on any of the above!

EDIT: I've added a "container_command" to my config file above as it was brought to my attention that another user also encountered the "permission denied" error for the platform hook when deploying. This "01_sh_executable" command is to chmod all of the .sh scripts within the hooks directory of the app, so that Elastic Beanstalk can have the proper permission to execute them during the deployment process. I found this container command solution in this forum here:

like image 155
Yamen Alghrer Avatar answered Nov 20 '22 01:11

Yamen Alghrer


This might work .ebextensions/django.config

   option_settings:
  aws:elasticbeanstalk:container:python:
    WSGIPath: mysite.wsgi:application
  aws:elasticbeanstalk:environment:proxy:staticfiles:
    /static: static
packages: 
  yum:
    python3-devel: []
    mariadb-devel: []
container_commands:
  01_collectstatic:
    command: "source /var/app/venv/staging-LQM1lest/bin/activate && python manage.py collectstatic --noinput"
  02_migrate:
    command: "source /var/app/venv/staging-LQM1lest/bin/activate && python manage.py migrate --noinput"
    leader_only: true
like image 33
Prajwol KC Avatar answered Nov 20 '22 03:11

Prajwol KC