Exposing Elastic Beanstalk environment variables to Laravel's artisan using Docker

Asked
Active3 hr before
Viewed126 times

7 Answers

environmentvariablesexposingdockerusingbeanstalkelastic
90%

Meta Stack Overflow ,To try and get the environment variables to PHP CLI I tried doing this in my Dockerfile:, Stack Overflow Public questions & answers , Stack Overflow help chat

Most likely the mod_env doesn't pass those variables to your application. In your /var/apache2/sites-enabled/000-default.conf, or other file which is responsible for your app, you need to specify all environment parameters which should be passed like in the example below:

<VirtualHost *:80>
    DocumentRoot "${APP_DOCUMENT_ROOT}"

    <Directory "${APP_DOCUMENT_ROOT}">
        AllowOverride AuthConfig FileInfo Indexes Limit Options=All,MultiViews
        Options FollowSymLinks MultiViews
        Require all granted
    </Directory>

    CustomLog ${APACHE_LOG_DIR}/access.log combined
    ErrorLog ${APACHE_LOG_DIR}/error.log

    #here the magic begins:
    PassEnv APP_RUN_MODE
    PassEnv RDS_HOSTNAME
    PassEnv RDS_PORT
    PassEnv RDS_DB_NAME
    PassEnv RDS_USERNAME
    PassEnv RDS_PASSWORD
</VirtualHost>
load more v
88%

Type a master username and password. Elastic Beanstalk will provide these values to your application using environment properties. , Type a master username and password. Elastic Beanstalk will provide these values to your application using environment properties. ,Load balancer – An Elastic Load Balancing load balancer configured to distribute requests to the instances running your application. A load balancer also eliminates the need to expose your instances directly to the internet. , Load balancer – An Elastic Load Balancing load balancer configured to distribute requests to the instances running your application. A load balancer also eliminates the need to expose your instances directly to the internet.

...
'connections' => [

   'sqlite' => [
      'driver' => 'sqlite',
      'database' => env('DB_DATABASE', database_path('database.sqlite')),
      'prefix' => '',
   ],

   'mysql' => [
      'driver' => 'mysql',
      'host' => env('RDS_HOSTNAME', '127.0.0.1'),
      'port' => env('RDS_PORT', '3306'),
      'database' => env('RDS_DB_NAME', 'forge'),
      'username' => env('RDS_USERNAME', 'forge'),
      'password' => env('RDS_PASSWORD', ''),
      'unix_socket' => env('DB_SOCKET', ''),
      'charset' => 'utf8mb4',
      'collation' => 'utf8mb4_unicode_ci',
      'prefix' => '',
      'strict' => true,
      'engine' => null,
   ],
   ...
load more v
72%

Finally, the docker-entrypoint.sh executed when the container is launched caches the routes and the configuration of the Laravel application, setting the permissions to Alpine’s Apache’s user running the database migration, running a queue worker in the background and finally running Apache in the background.,It is setting the document root to the public folder of our Laravel application, enabling the rewrite and sessions module as well as disabling the indexes as well as the tokens that would leak the Apache version.,I chose EC2 over Fargate but the rest of the configuration of the cluster should not change much if you chose Fargate. If you do so please let me know how it went in the comments!,Next, we will create the load balancer. We need one because it will be responsible for checking the containers’ health and redirecting the traffic from the old container to the new one without downtime during a deployment.

Without further ado, here is the resulting Dockerfile that I put at the root of my repository.

# Build Stage 1
# Compile Composer dependencies
FROM composer: 1.9 AS composer
WORKDIR /
   var / www
COPY. /
   var / www
RUN composer install--ignore - platform - reqs--no - interaction--no - dev--prefer - dist--optimize - autoloader

# Build Stage 2
# Compile NPM assets
FROM node: 12.13 .0 - alpine AS build - npm
WORKDIR /
   var / www
COPY--from = composer /
   var / www /
   var / www
RUN npm install--silent--no - progress
RUN npm run prod--silent--no - progress
RUN rm - rf node_modules

# Build Stage 3
# PHP Alpine image, we install Apache on top of it
FROM alpine: 3.10

# Concatenated RUN commands
RUN apk add--no - cache zip unzip libzip - dev libpng - dev libxml2 - dev libmcrypt - dev curl gnupg apache2\
php7 php7 - apache2 php7 - mbstring php7 - session php7 - json php7 - openssl php7 - tokenizer php7 - pdo php7 - pdo_mysql php7 - fileinfo php7 - ctype\
php7 - xmlreader php7 - xmlwriter php7 - xml php7 - simplexml php7 - gd php7 - bcmath php7 - zip php7 - dom php7 - posix php7 - calendar libc6 - compat libstdc++\
   &&
   mkdir - p / run / apache2\ &&
   rm - rf / tmp
/*

# Apache configuration
COPY apache.conf /etc/apache2/conf.d

# PHP configuration
RUN wget https://elasticache-downloads.s3.amazonaws.com/ClusterClient/PHP-7.3/latest-64bit
RUN tar -zxvf latest-64bit
RUN mv amazon-elasticache-cluster-client.so /usr/lib/php7/modules/
COPY 00_php.ini /etc/php7/conf.d

# Script permission
ADD docker-entrypoint.sh /docker-entrypoint.sh
RUN chmod +x /docker-entrypoint.sh

# Copy files from NPM
WORKDIR /var/www
COPY --from=build-npm /var/www /var/www

# Run script
EXPOSE 80
ENTRYPOINT ["/docker-entrypoint.sh"]
load more v
65%

now open your elastic beanstalk tab ,choose the environment that you'd like to deploy to , then click on the upload and deploy button,choose your file give it a label and press deploy.,You can also set all your settings as environment variables in the elastic beanstalk config. ,In the AWS console, open the Elastic Beanstalk tab,The configuration of your elastic beanstalk environment should be done using the .ebextensions and .platform directories. Look it up.

open your database config file /config/database.php now edit and make three global variables

define('RDS_HOSTNAME', $_SERVER['RDS_HOSTNAME']);
define('RDS_USERNAME', $_SERVER['RDS_USERNAME']);
define('RDS_PASSWORD', $_SERVER['RDS_PASSWORD']);
define('RDS_DB_NAME', $_SERVER['RDS_DB_NAME']);
load more v
75%

If you recall my first article, I explained a bit about the worker environment and the fact that it runs its own queue daemon that interacts with SQS. We installed a package to help Laravel interface with the Amazon queue daemon so we’re already set up to work with EB worker environments.,For demonstration purposes our application is going to have one web environment and one worker environment so that Laravel can use a queue if it needs to. However, if your app doesn’t use queues then you can ignore the worker environment.,Once we have our .ebextensions config files in place it’s time to actually create our environments. Back in the EB CLI run the following command:,Let’s get started by creating the application and our initial environment in Elastic Beanstalk. As I said above we’re going to use the EB CLI for this part. In the root of your Laravel app run:

Let’s get started by creating the application and our initial environment in Elastic Beanstalk. As I said above we’re going to use the EB CLI for this part. In the root of your Laravel app run:

eb init
load more v
40%

In this article, we'll show you how to create a Docker image of a Laravel application, push it to an image registry, and use Docker in Continuous Delivery.,In theory, Dockerization means activities leading to the launch of the application in a Docker container. In case of a Laravel app, this can be translated into the following steps:,In this part of the guide, we'll add a pipeline that will build and test a Docker image, push it to the selected registry, and run it on the server.,In this guide, we're going to containerize a simple calculator written with the Laravel framework. Simply fork the repository and Dockerize Laravel with the instructions below!

php artisan serve$
load more v
22%

Since the first post the eb roadmap announced that the PHP platform had been updated making things much easier. Below the .ebextensions configuration files and the .platform files that needs to be set up are explained (otherwise nginx will throw 404 errors on all routes), To see where's the error you could connect to the EB instance and check if the service is running, if it's not then something might be wrong with the configuration file. I edited my answer with the full file that's working for me – Aridez May 4 '20 at 18:17 ,I also changed the user and group of the service to webapp since root didn't feel safe and everything works fine with webapp too.,This image uses Systemd which makes the process much easier since a supervisor is not needed anymore. Unfortunately the services keyword is not supported yet for the new images so the service has to be started and restarted using the container_commands keyword.

This file contains all the commands I execute on every production environment, remember to change them to whatever suit your needs:

\.ebextension\ 01 - setup.config
container_commands:
   01 - no_dev:
   command: "composer.phar install --optimize-autoloader --no-dev"
02 - config_clear:
   command: "php artisan config:clear"
03 - view_clear:
   command: "php artisan view:clear"
04 - route_cache:
   command: "php artisan route:cache"
05 - view_cache:
   command: "php artisan view:cache"
06 - migrate:
   command: "php artisan migrate --force"
leader_only: true
07 - queue_service_restart:
   command: "systemctl restart laravel_worker"
files:
   /opt/elasticbeanstalk / tasks / taillogs.d / laravel - logs.conf:
   content: /var/app / current / storage / logs / laravel.log
group: root
mode: "000755"
owner: root /
   etc / systemd / system / laravel_worker.service:
   mode: "000755"
owner: root
group: root
content: |
   # Laravel queue worker using systemd
#-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
#
# / lib / systemd / system / queue.service
#
# run this command to enable service:
   # systemctl enable queue.service

[Unit]
Description = Laravel queue worker

[Service]
User = nginx
Group = nginx
Restart = always
ExecStart = /usr/bin / nohup / usr / bin / php /
   var / www / html / laravel - project / artisan queue: work--daemon

[Install]
WantedBy = multi - user.target

This second file serves to set up the Laravel scheduler, it is a cron job that runs the php artisan schedule:run every minute. It must be executed as root, and since the environment variables are not available, we need to get them from /opt/elasticbeanstalk/deployment/env. Here's a great answer about the topic.

\.ebextension\ cron - linux.config
files:
   "/etc/cron.d/schedule_run":
   mode: "000644"
owner: root
group: root
content: |
   *
   * * * * root. / opt / elasticbeanstalk / deployment / env && /usr/bin / php /
   var / app / current / artisan schedule: run 1 >> /dev/null
2 > & 1

commands:
   remove_old_cron:
   command: "rm -f /etc/cron.d/*.bak"

Setting up the .platform configuration

\.platform\ nginx\ conf.d\ elasticbeanstalk\ laravel.conf
location / {
   try_files $uri $uri / /index.php?$query_string;
   gzip_static on;
}

1- Install supervisor with the packages. the python keyword uses pip and easy_install under the hood:

packages:
   python:
   supervisor: []

2- Create the supervisor configuration file:

files:
   /usr/local / etc / supervisord.conf:
   mode: "000755"
owner: root
group: root
content: | [unix_http_server]
file = /tmp/supervisor.sock;
(the path to the socket file)

[supervisord]
logfile = /tmp/supervisord.log;
(main log file;
   default $CWD / supervisord.log)
logfile_maxbytes = 50 MB;
(max main logfile bytes b4 rotation;
   default 50 MB)
logfile_backups = 10;
(num of main logfile rotation backups;
   default 10)
loglevel = info;
(log level;
   default info; others: debug, warn, trace)
pidfile = /tmp/supervisord.pid;
(supervisord pidfile;
   default supervisord.pid)
nodaemon = false;
(start in foreground
   if true;
   default false)
minfds = 1024;
(min.avail startup file descriptors;
   default 1024)
minprocs = 200;
(min.avail process descriptors;
   default 200)

[rpcinterface: supervisor]
supervisor.rpcinterface_factory = supervisor.rpcinterface: make_main_rpcinterface

[supervisorctl]
serverurl = unix: ///tmp/supervisor.sock ; use a unix:// URL  for a unix socket

   [include]
files = /etc/supervisor / conf.d
/*.conf

            [inet_http_server]
            port = 127.0.0.1:9001

3- Create the supervisor process file, from the configuring supervisor section in the laravel docs:

files:
   /etc/supervisor / conf.d / laravel - worker.conf:
   content: | [program: laravel - worker]
process_name = % (program_name) s_ % (process_num) 02 d
command = php /
   var / app / current / artisan queue: work database--sleep = 3--tries = 3
autostart = true
autorestart = true;
user = root
numprocs = 1
redirect_stderr = true;
stdout_logfile = /var/app / current / storage / logs / worker.log
stopwaitsecs = 3600

5- After all the files are created run the following commands to start the service and to add it so it can be managed:

commands:
   command - 1:
   command: "/etc/init.d/supervisord start"
command - 2:
   command: "chkconfig --add supervisord"

6- Now the services keyword should work, allowing us to set the enabled and ensurerunning flags to true.

services:
   sysvinit:
   supervisord:
   enabled: "true"
ensureRunning: "true"
files:
   -"/usr/local/etc/supervisord.conf"
load more v

Other "environment-variables" queries related to "Exposing Elastic Beanstalk environment variables to Laravel's artisan using Docker"