How to Deploy Rails on Amazon Elastic Beanstalk on a Single Container Docking Environment

I am trying to dockerize a Rails application on an Elastic Beanstalk. There are many examples, but most of them are not suitable for my specific use case. I.e:

  • Running under one Docker container (so there is no need for docker compote / fig)
  • Running on Amazon Stretch Beanstalk.
  • Use passenger-docker as the base image (one of Ruby's options).
  • Environment variable variables set using Elastic Beanstalk (via the CLI console).
  • Nginx and passenger in a container.
  • Ability to install custom packages (extension).
  • A .dockerignore file.

The deployment process is not a question here, but the correct Docker configuration, which will work with Amazon Elastic Beanstalk with the above criteria.

What is the correct configuration to do?

+5
source share
1 answer

This is what worked for me ...

Dockerfile

In this example, I use phusion/passenger-ruby22:0.9.16 as the base image, because:

  • Your Dockerfile may be smaller.
  • This reduces the time it takes to write the correct Docker file. You do not have to worry about the base system and the stack, you can only focus on your application.
  • Correctly installs the base system . It is very easy to get the base system wrong, but this image does it right. More details ...
  • This significantly reduces the time required to launch docker build , which allows you to restart the Docker file faster and faster.
  • This reduces load times during redistribution. Docker only needs to download the base image: during the first deployment. Each subsequent deployment only loads the changes that you make over the base image.

You can find out more about this here ... anyway, on the Dockerfile .

 # The FROM instruction sets the Base Image for subsequent instructions. As such, # a valid Dockerfile must have FROM as its first instruction. We use # phusion/baseimage as a base image. To make our builds reproducible, we make # sure we lock down to a specific version, not to `latest`! FROM phusion/passenger-ruby22:0.9.16 # The MAINTAINER instruction allows you to set the Author field of the generated # images. MAINTAINER "Job King'ori Maina" < yo@kingori.co > (@itsmrwave) # The RUN instructions will execute any commands in a new layer on top of the # current image and commit the results. The resulting committed image will be # used for the next step in the Dockerfile. # === 1 === # Prepare for packages RUN apt-get update --assume-yes && apt-get install --assume-yes build-essential # For a JS runtime # http://nodejs.org/ RUN apt-get install --assume-yes nodejs # For Nokogiri gem # http://www.nokogiri.org/tutorials/installing_nokogiri.html#ubuntu___debian RUN apt-get install --assume-yes libxml2-dev libxslt1-dev # For RMagick gem # https://help.ubuntu.com/community/ImageMagick RUN apt-get install --assume-yes libmagickwand-dev # Clean up APT when done. RUN apt-get clean && rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* # === 2 === # Set correct environment variables. ENV HOME /root # Use baseimage-docker init process. CMD ["/sbin/my_init"] # === 3 ==== # By default Nginx clears all environment variables (except TZ). Tell Nginx to # preserve these variables. See nginx-env.conf. COPY nginx-env.conf /etc/nginx/main.d/rails-env.conf # Nginx and Passenger are disabled by default. Enable them (start Nginx/Passenger). RUN rm -f /etc/service/nginx/down # Expose Nginx HTTP service EXPOSE 80 # === 4 === # Our application should be placed inside /home/app. The image has an app user # with UID 9999 and home directory /home/app. Our application is supposed to run # as this user. Even though Docker itself provides some isolation from the host # OS, running applications without root privileges is good security practice. RUN mkdir -p /home/app/myapp WORKDIR /home/app/myapp # Run Bundle in a cache efficient way. Before copying the whole app, copy just # the Gemfile and Gemfile.lock into the tmp directory and ran bundle install # from there. If neither file changed, both instructions are cached. Because # they are cached, subsequent commands—like the bundle install one—remain # eligible for using the cache. Why? How? See ... # http://ilikestuffblog.com/2014/01/06/how-to-skip-bundle-install-when-deploying-a-rails-app-to-docker/ COPY Gemfile /home/app/myapp/ COPY Gemfile.lock /home/app/myapp/ RUN chown -R app:app /home/app/myapp RUN sudo -u app bundle install --deployment --without test development doc # === 5 === # Adding our web app to the image ... only after bundling do we copy the rest of # the app into the image. COPY . /home/app/myapp RUN chown -R app:app /home/app/myapp # === 6 === # Remove the default site. Add a virtual host entry to Nginx which describes # where our app is, and Passenger will take care of the rest. See nginx.conf. RUN rm /etc/nginx/sites-enabled/default COPY nginx.conf /etc/nginx/sites-enabled/myapp.conf 

Dockerrun.aws.json

 { "AWSEBDockerrunVersion": "1", "Ports": [ { "ContainerPort": "80" } ], "Logging": "/home/app/myapp/log" } 

.dockerignore

 /.bundle /.DS_Store /.ebextensions /.elasticbeanstalk /.env /.git /.yardoc /log/* /tmp !/log/.keep 

Nginx-env.conf

Note that rails-env.conf does not set any environment variables outside of Nginx, so you won’t be able to see them in the shell (i.e. Dockerfile ). You will also have to use different methods to set environment variables for the shell.

 # By default Nginx clears all environment variables (except TZ) for its child # processes (Passenger being one of them). That why any environment variables # we set with docker run -e, Docker linking and /etc/container_environment, # won't reach Nginx. To preserve these variables, place an Nginx config file # ending with *.conf in the directory /etc/nginx/main.d, in which we tell Nginx # to preserve these variables. # Set by Passenger Docker env RAILS_ENV; env RACK_ENV; env PASSENGER_APP_ENV; # Set by AWS Elastic Beanstalk (examples, change accordingly) env AWS_ACCESS_KEY_ID; env AWS_REGION; env AWS_SECRET_KEY; env DB_NAME; env DB_USERNAME; env DB_PASSWORD; env DB_HOSTNAME; env DB_PORT; env MAIL_USERNAME; env MAIL_PASSWORD; env MAIL_SMTP_HOST; env MAIL_PORT; env SECRET_KEY_BASE; 

nginx.conf

 server { listen 80; server_name _; root /home/app/myapp/public; # The following deploys your app on Passenger. # Not familiar with Passenger, and used (G)Unicorn/Thin/Puma/pure Node before? # Yes, this is all you need to deploy on Passenger! All the reverse proxying, # socket setup, process management, etc are all taken care automatically for # you! Learn more at https://www.phusionpassenger.com/. passenger_enabled on; passenger_user app; # Ensures that RAILS_ENV, RACK_ENV, PASSENGER_APP_ENV, etc are set to # "production" when your application is started. passenger_app_env production; # Since this is a Ruby app, specify a Ruby version: passenger_ruby /usr/bin/ruby2.2; } 
+4
source

All Articles