From 75b33e760aa6bc736d2f7087ca34a55fc87e7ffb Mon Sep 17 00:00:00 2001 From: Ari Timonen Date: Sun, 5 Apr 2020 05:58:41 +0300 Subject: [PATCH] Move back to docker-compose + fix env vars Fix env vars. Rely on inheritance. Add a script to load env vars as above. Fix staging env Add nginx conf and SSL directory Reorganize .gitignore Use multi-staged docker-compose + dockerfile Substitute env vars for static values --- .dockerignore | 14 ++- .env.development | 30 +----- .env.example | 62 ------------ .env.production | 6 +- .env.staging | 33 ++---- .env.test | 18 +--- .gitignore | 53 +++++----- DEVELOPMENT.md | 91 +++++++++-------- Dockerfile | 49 +++++++-- Dockerfile.dev | 32 ------ INSTALL.md | 2 +- bin/script/entry.sh | 2 +- config/application.rb | 1 + config/database.yml | 2 +- config/environments/production.rb | 2 +- config/environments/staging.rb | 12 ++- config/puma.rb | 2 +- docker-compose.dev.yml | 111 --------------------- docker-compose.yml | 144 +++++++++++++++++++++++---- ext/nginx.conf.d/nginx.conf | 119 ---------------------- ext/nginx.conf.d/nginx.conf.template | 75 ++++++++++++++ script/env.sh | 18 ++++ spec/spec_helper.rb | 3 +- 23 files changed, 373 insertions(+), 508 deletions(-) delete mode 100644 .env.example delete mode 100644 Dockerfile.dev delete mode 100644 docker-compose.dev.yml delete mode 100644 ext/nginx.conf.d/nginx.conf create mode 100644 ext/nginx.conf.d/nginx.conf.template create mode 100755 script/env.sh diff --git a/.dockerignore b/.dockerignore index 6266abc..d9ca2ff 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,6 +1,12 @@ Dockerfile -db_data -db/data/ +docker-compose.yml +*.md +.idea dkim -log/* -public/* \ No newline at end of file +log/.log* +tmp/ +public/* +db_data +db/data +db/initdb.d/ +ext/ diff --git a/.env.development b/.env.development index 794bf50..d16656e 100644 --- a/.env.development +++ b/.env.development @@ -1,31 +1,11 @@ # This file is actually loaded by Dotenv when RAILS_ENV=development +# Development-specific ENV variables, loaded after .env and before .env*local +# Add changes only specific to dev. env. + +# These are RACK_ENV=development RAILS_ENV=development -APP_SECRET=fe837ea72667ec3d8ecb94cfba1a1bba - -DEPLOY_PATH=/var/www -FILES_PATH=/var/www/public/files - -PUMA_WORKERS=0 -PUMA_MIN_THREADS=1 -PUMA_MAX_THREADS=16 -PUMA_PORT=4000 - # Set this to higher to enable debugging -PUMA_TIMEOUT=300 - -MYSQL_HOST=db -MYSQL_DATABASE=ensl -MYSQL_USERNAME=ensl -MYSQL_PASSWORD=ensl -MYSQL_ROOT_PASSWORD=ensl -MYSQL_CONNECTION_POOL=32 - -NEW_RELIC_APP_NAME=ENSL -NEW_RELIC_LICENSE_KEY= - -GOOGLE_API_KEY= -GOOGLE_CALENDAR_ID= -GOOGLE_CALENDAR=enabled \ No newline at end of file +PUMA_TIMEOUT=300 \ No newline at end of file diff --git a/.env.example b/.env.example deleted file mode 100644 index 9a734d6..0000000 --- a/.env.example +++ /dev/null @@ -1,62 +0,0 @@ -# Read https://github.com/bkeepers/dotenv -# This is just a sample file - -# Change this depending where you are -RACK_ENV=production -RAILS_ENV=production - -# App secret for cookie encryption -APP_SECRET=randomstringhere - -# Use -# SCrypt::Engine.calibrate!(max_mem: 16 * 1024 * 1024) -# SCrypt::Engine.generate_salt -SCRYPT_SALT_OPTS= -SCRYPT_MAX_TIME=1 - -# Since this is inside Docker container, it doesn't really matter -DEPLOY_PATH=/var/www - -# Puma fails in cluster mode, so use 0 workers -PUMA_WORKERS=0 - -# Threads and port -PUMA_MIN_THREADS=1 -PUMA_MAX_THREADS=16 -PUMA_PORT=4000 - -# Use higher timeout if debug fails -PUMA_TIMEOUT=30 - -# Path to files -FILES_PATH=/var/www/files - -# Docker adds mysql to hosts -MYSQL_HOST=db - -# This is used by both rails + mysql -MYSQL_DATABASE=ensl - -# Add to allow docker image to connect -MYSQL_ROOT_HOST=% - -# Root MySQL password -MYSQL_ROOT_PASSWORD=ensl - -# These are for ENSL, edit at least password -MYSQL_USERNAME=ensl -MYSQL_PASSWORD=ensl - -# More MySQL vars -MYSQL_CONNECTION_POOL=32 - -SELENIUM_HOST=selenium -TEST_APP_HOST=localhost -TEST_APP_PORT=3005 - -NEW_RELIC_APP_NAME=ENSL -NEW_RELIC_LICENSE_KEY= - -GOOGLE_API_KEY= -GOOGLE_CALENDAR_ID= -GOOGLE_CALENDAR=enabled \ No newline at end of file diff --git a/.env.production b/.env.production index d878718..6e363b8 100644 --- a/.env.production +++ b/.env.production @@ -3,8 +3,6 @@ RACK_ENV=production RAILS_ENV=production -DEPLOY_PATH=/var/www - # FIXME Disable workers + cluster mode for now. PUMA_WORKERS=0 PUMA_MIN_THREADS=1 @@ -12,9 +10,9 @@ PUMA_MAX_THREADS=32 PUMA_PORT=4000 PUMA_TIMEOUT=30 -MYSQL_HOST=db MYSQL_DATABASE=ensl -MYSQL_USERNAME=ensl MYSQL_CONNECTION_POOL=48 +APP_DOMAIN=ensl.org + GOOGLE_CALENDAR=enabled \ No newline at end of file diff --git a/.env.staging b/.env.staging index 83654a4..610d31b 100644 --- a/.env.staging +++ b/.env.staging @@ -1,31 +1,10 @@ # This file is actually loaded by Dotenv when RAILS_ENV=development -RACK_ENV=development -RAILS_ENV=development +RACK_ENV=staging +RAILS_ENV=staging -APP_SECRET=fe837ea72667ec3d8ecb94cfba1a1bba +APP_PORT=4999 +APP_PORT_SSL=5000 +PUMA_PORT=5000 -DEPLOY_PATH=/var/www -FILES_PATH=/var/www/public/files - -PUMA_WORKERS=0 -PUMA_MIN_THREADS=1 -PUMA_MAX_THREADS=16 -PUMA_PORT=4000 - -# Set this to higher to enable debugging -PUMA_TIMEOUT=30 - -MYSQL_HOST=db -MYSQL_DATABASE=ensl_staging -MYSQL_USERNAME=ensl -MYSQL_PASSWORD=ensl -MYSQL_ROOT_PASSWORD=ensl -MYSQL_CONNECTION_POOL=32 - -NEW_RELIC_APP_NAME=ENSL -NEW_RELIC_LICENSE_KEY= - -GOOGLE_API_KEY= -GOOGLE_CALENDAR_ID= -GOOGLE_CALENDAR=enabled \ No newline at end of file +MYSQL_DATABASE=ensl_staging \ No newline at end of file diff --git a/.env.test b/.env.test index c7fb3bd..0c74f9a 100644 --- a/.env.test +++ b/.env.test @@ -7,9 +7,6 @@ APP_SECRET=fe837ea72667ec3d8ecb94cfba1a1bba DEPLOY_PATH=/var/www -PUMA_WORKERS=1 -PUMA_MIN_THREADS=1 -PUMA_MAX_THREADS=16 PUMA_PORT=4000 PUMA_TIMEOUT=30 @@ -17,21 +14,8 @@ SELENIUM_HOST=selenium TEST_APP_HOST=localhost TEST_APP_PORT=3005 -MYSQL_HOST=db MYSQL_DATABASE=ensl_test -MYSQL_USER=ensl -MYSQL_USERNAME=ensl -MYSQL_PASSWORD=ensl -MYSQL_ROOT_PASSWORD=ensl -MYSQL_CONNECTION_POOL=8 - -NEW_RELIC_APP_NAME=ENSL -NEW_RELIC_LICENSE_KEY= # Fix poltergeist issue CLIVER_NO_VERIFY=1 -OPENSSL_CONF=/etc/ssl/ - -GOOGLE_API_KEY= -GOOGLE_CALENDAR_ID= -GOOGLE_CALENDAR=enabled \ No newline at end of file +OPENSSL_CONF=/etc/ssl/ \ No newline at end of file diff --git a/.gitignore b/.gitignore index 3d0e719..a01227e 100644 --- a/.gitignore +++ b/.gitignore @@ -2,14 +2,14 @@ /log/* /tmp/* /spec/tmp/* -/env/production.sh -/env/development.sh .ruby-version .ruby-gemset .env .env*.local .tmp* .rspec + +# Cache files .sass-cache *.sassc *.rbc @@ -26,38 +26,27 @@ db/initdb.d/* # ignore dkim keys dkim +ext/dkim -# OS X -.DS_Store +# ignore SSL +ext/ssl +!ext/ssl/.placeholder + +# Nginx +ext/nginx.conf.d/default.conf # Uploaded Assets /public/system/* -/public/files/* +/public/files /public/local /public/uploads /public/assets -# RubyMine -/.idea - -# VIM -**.swp - -# Git junk -**.orig - # Bundler /.bundle /vendor/bundle/ .bundle -# Misc -/coverage/ -/backups -/index/* -rerun.txt -pickle-email-*.html - # Direnv .envrc @@ -69,10 +58,28 @@ pickle-email-*.html .rakeTasks .generators +# OS X +.DS_Store + +# RubyMine +.idea/ + +# VIM +**.swp + +# Git junk +**.orig + +# Misc +/coverage/ +/backups +/index/* +rerun.txt +pickle-email-*.html + # Gemtags *.tags *.gemtags -# Staging files -tmp/*.gz +# Debug files .byebug_history diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md index bf4a369..5adfef9 100644 --- a/DEVELOPMENT.md +++ b/DEVELOPMENT.md @@ -6,7 +6,7 @@ Install instructions in INSTALL.md Just run and open http://localhost:4000/ - docker-compose -f docker-compose.dev.yml up` + docker-compose -f docker-compose.yml up` ## Tips @@ -22,6 +22,57 @@ and it still fails a bit. https://github.com/connorshea/vscode-ruby-test-adapter 1. Do not commit too much without testing. Also keep commits small for documentation and reversability issues. 1. You need to rebuild the docker image when you change gems. +## TODO issues for dev + +1. Puma should be running (eg. spring), and if debugger is used it should be able to connect via docker-compose up +1. Should directories exist? + +# Tags in code + +FIXME, TODO, EXPLAIN, OBSOLETE + +## Handy commands + +Load env variables: + + export $(cat .env.development | xargs) && export $(cat .env | xargs) + +Start: + + docker-compose -f docker-compose.yml up -d --build` + +Build or rebuild: + + docker-compose -f docker-compose.yml build` + +Debug: + + docker attach ensl_dev + +To get inside docker web+test containers: + + docker-compose -f docker-compose.yml exec -u root web /bin/bash` + docker-compose -f docker-compose.yml exec -u web web /bin/bash` + docker-compose -f docker-compose.yml exec -u root test /bin/bash` + docker-compose -f docker-compose.yml exec -u web test /bin/bash` + +Restart the web container + + docker-compose -f docker-compose.yml restart web` + +Run some tests: + + docker-compose -f docker-compose.yml exec -u web test bundle exec rspec` + docker-compose -f docker-compose.yml exec -u web test bundle exec rspec spec/controllers/shoutmsgs_controller_spec.rb` + +# Design of ENSL Application + +Read this to understand design decisions and follow them! + +1. Env variables should be used everywhere and loaded from .env* files using Dotenv +1. The app contents are added to the docker image on build but it is mounted as **volume**. +1. Use rails / ruby best practices in section below. + ## Best practices 1. https://nvie.com/posts/a-successful-git-branching-model/ @@ -30,41 +81,3 @@ and it still fails a bit. https://github.com/connorshea/vscode-ruby-test-adapter 1. http://www.betterspecs.org/ 1. https://github.com/rubocop-hq/rspec-style-guide 1. Run rubocop - -## TODO issues for dev - -1. Puma should be running (eg. spring), and if debugger is used it should be able to connect via docker-compose up - -# Tags in code - -FIXME, TODO, EXPLAIN, OBSOLETE - -## Handy commands - -Start: - - docker-compose -f docker-compose.dev.yml up -d --build` - -Build or rebuild: - - docker-compose -f docker-compose.dev.yml build` - -Debug: - - docker attach ensl_dev - -To get inside docker web+test containers: - - docker-compose -f docker-compose.dev.yml exec -u root web /bin/bash` - docker-compose -f docker-compose.dev.yml exec -u web web /bin/bash` - docker-compose -f docker-compose.dev.yml exec -u root test /bin/bash` - docker-compose -f docker-compose.dev.yml exec -u web test /bin/bash` - -Restart the web container - - docker-compose -f docker-compose.dev.yml restart web` - -Run some tests: - - docker-compose -f docker-compose.dev.yml exec -u web test bundle exec rspec` - docker-compose -f docker-compose.dev.yml exec -u web test bundle exec rspec spec/controllers/shoutmsgs_controller_spec.rb` \ No newline at end of file diff --git a/Dockerfile b/Dockerfile index 8094c69..42d847d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,11 +1,9 @@ -FROM ruby:2.6.5 +FROM ruby:2.6.5 AS ensl_development -ENV RAILS_ENV production +ENV RAILS_ENV development -# Add 'web' user which will run the application -RUN adduser web --home /home/web --shell /bin/bash --disabled-password --gecos "" - -RUN apt-get update && apt-get -y upgrade \ +RUN adduser web --home /home/web --shell /bin/bash --disabled-password --gecos "" && \ + apt-get update && apt-get -y upgrade \ && apt-get -y install \ libmariadb-dev libmariadb-dev-compat \ libssl-dev \ @@ -20,19 +18,48 @@ RUN apt-get update && apt-get -y upgrade \ ADD Gemfile Gemfile.lock /var/www/ RUN gem install bundler && \ - mkdir -p /var/bundle && chown -R web:web /var/bundle && chown -R web:web /var/www + mkdir -p /var/bundle && chown -R web:web /var/bundle && \ + chown -R web:web /var/www WORKDIR /var/www USER web RUN bundle config github.https true && \ bundle config set path '/var/bundle' && \ - bundle install --jobs 8 && \ - bundle exec rake assets:precompile + bundle install --jobs 8 USER root -# Temporary fix for assets -RUN mv /var/www/public/assets /home/web/assets +# ENTRYPOINT ["/bin/bash"] +# CMD ["/var/www/bin/script/entry.sh"] +# Staging + +FROM ensl_development AS ensl_staging + +ENV RAILS_ENV staging + +USER root + +ENTRYPOINT ["/bin/bash"] +CMD ["/var/www/bin/script/entry.sh"] + +# Production + +FROM ensl_development AS ensl_production + +ENV RAILS_ENV production + +ADD . /var/www + +WORKDIR /var/www + +RUN chown -R web:web /var/www + +USER web +RUN bundle exec rake assets:precompile && \ + # Temporary fix for assets + mv /var/www/public/assets /home/web/assets + +ENTRYPOINT ["/bin/bash"] CMD ["/var/www/bin/script/entry.sh"] diff --git a/Dockerfile.dev b/Dockerfile.dev deleted file mode 100644 index de91ca9..0000000 --- a/Dockerfile.dev +++ /dev/null @@ -1,32 +0,0 @@ -FROM ruby:2.6.5 - -ENV RAILS_ENV development - -# Add 'web' user which will run the application -RUN adduser web --home /home/web --shell /bin/bash --disabled-password --gecos "" - -RUN apt-get update && apt-get -y upgrade \ - && apt-get -y install \ - libmariadb-dev libmariadb-dev-compat \ - libssl-dev \ - zlib1g-dev libreadline-dev libyaml-dev \ - libxslt1-dev libxml2-dev \ - imagemagick libmagickwand-dev \ - nodejs \ - phantomjs \ - firefox-esr - -# Separate Gemfile ADD so that `bundle install` can be cached more effectively -ADD Gemfile Gemfile.lock /var/www/ - -RUN gem install bundler && \ - mkdir -p /var/bundle && chown -R web:web /var/bundle && chown -R web:web /var/www - -WORKDIR /var/www -USER web - -RUN bundle config github.https true && \ - bundle config set path '/var/bundle' && \ - bundle install --jobs 8 - -CMD ["/var/www/bin/script/entry.sh"] diff --git a/INSTALL.md b/INSTALL.md index 82ca1fc..8844d6d 100644 --- a/INSTALL.md +++ b/INSTALL.md @@ -41,7 +41,7 @@ a) Then start for **production**: b) ... or start for **development**: - docker-compose -f docker-compose.dev.yml up + docker-compose -f docker-compose.yml up ## 3. Install reverse proxy (production only) diff --git a/bin/script/entry.sh b/bin/script/entry.sh index 13ca542..0f6a415 100755 --- a/bin/script/entry.sh +++ b/bin/script/entry.sh @@ -2,7 +2,7 @@ cd /var/www -source /var/www/.env +source script/env.sh .env .env.$RAILS_ENV .env.$RAILS_ENV.local .env.local if [ $RAILS_ENV = "production" ]; then rm -rf /var/www/public/assets diff --git a/config/application.rb b/config/application.rb index 9c20383..821bc14 100644 --- a/config/application.rb +++ b/config/application.rb @@ -24,6 +24,7 @@ module Ensl config.autoload_paths += Dir["#{config.root}/app/services/**/", "#{config.root}/app/models/concerns/"] # Load secrets from .env + ENV['APP_SECRET'] ||= (0...32).map { (65 + rand(26)).chr }.join config.secret_token = ENV['APP_SECRET'] # Use cookies diff --git a/config/database.yml b/config/database.yml index e042c1f..d1d39ac 100644 --- a/config/database.yml +++ b/config/database.yml @@ -3,7 +3,7 @@ base: &db encoding: utf8 host: <%= ENV['MYSQL_HOST'] %> database: <%= ENV['MYSQL_DATABASE'] %> - username: <%= ENV['MYSQL_USERNAME'] %> + username: <%= ENV['MYSQL_USER'] %> password: <%= ENV['MYSQL_PASSWORD'] %> pool: <%= Integer(ENV['MYSQL_CONNECTION_POOL'] || 8) %> wait_timeout: 90 diff --git a/config/environments/production.rb b/config/environments/production.rb index d2f0965..e52bc84 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -59,7 +59,7 @@ Ensl::Application.configure do config.action_mailer.raise_delivery_errors = true # Enable threaded mode - config.threadsafe! + # config.threadsafe! # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation can not be found) diff --git a/config/environments/staging.rb b/config/environments/staging.rb index 48ba483..7f7ee3e 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -9,10 +9,11 @@ Ensl::Application.configure do config.action_controller.perform_caching = true # Disable Rails's static asset server (Apache or nginx will already do this) - config.serve_static_assets = false + config.serve_static_assets = true # Compress JavaScripts and CSS config.assets.compress = true + config.assets.js_compressor = :uglifier # Don't fallback to assets pipeline if a precompiled asset is missed config.assets.compile = true @@ -51,9 +52,10 @@ Ensl::Application.configure do # Use sendmail config.action_mailer.delivery_method = :sendmail config.action_mailer.raise_delivery_errors = true - - # Enable threaded mode - config.threadsafe! + config.action_mailer.smtp_settings = { + address: 'smtp', + domain: 'ensl.org' + } # Enable locale fallbacks for I18n (makes lookups for any locale fall back to # the I18n.default_locale when a translation can not be found) @@ -63,7 +65,7 @@ Ensl::Application.configure do config.active_support.deprecation = :notify # Custom Session Store config to allow gathers.staging.ensl.org - config.session_store :cookie_store, key: "_ENSL_session_key_staging", expire_after: 30.days.to_i, domain: ".staging.ensl.org" + config.session_store :cookie_store, key: "_ENSL_session_key_staging", expire_after: 30.days.to_i config.eager_load = true end diff --git a/config/puma.rb b/config/puma.rb index c432b26..f129249 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -1,7 +1,7 @@ # Load dev vars # FIXME: right dev file is not loaded require "dotenv" -Dotenv.load() +Dotenv.load(".env.local", '.env' + ENV['RAILS_ENV'] + '.local', '.env' + ENV['RAILS_ENV'], '.env') tag 'ENSL' diff --git a/docker-compose.dev.yml b/docker-compose.dev.yml deleted file mode 100644 index a54b030..0000000 --- a/docker-compose.dev.yml +++ /dev/null @@ -1,111 +0,0 @@ -version: "3" - -services: - web: - command: "bundle exec puma" - tty: true - stdin_open: true - # NOtE: Use attach rather than this - # Debug - # command: /bin/bash - container_name: ensl_dev - build: - context: ./ - dockerfile: Dockerfile.dev -# args: -# buildno: 1 - volumes: - - ".:/var/www/" - ports: - - "4000:4000" - - "35729:35729" - links: - - db - - memcached - #- spring - #- selenium - #- redis - - test: - # Debug - #stdin_open: true - command: ["/bin/bash", "-c", "--", "while true; do sleep 100; done;"] - container_name: ensl_test - build: - context: ./ - dockerfile: Dockerfile.dev - args: - buildno: 1 - env_file: - - .env.test - ports: - - 3005:3005 # Capybara listens here - links: - - db - # - selenium - volumes: - - ".:/var/www" - # command: bin/spring server - environment: - TEST_APP_HOST: test - TEST_APP_PORT: 3005 - SELENIUM_HOST: selenium - RAILS_ENV: test - networks: - default: - aliases: - - test - - redis: - image: 'redis:4.0-alpine' - container_name: ensl_dev_redis - - selenium: - image: selenium/standalone-chrome-debug - container_name: ensl_dev_selenium - ports: - - 5900:5900 - - 4444:4444 - -# spring: -# build: -# context: ./ -# dockerfile: Dockerfile.dev -# args: -# buildno: 1 -# volumes: -# - .:/var/www -# command: spring server - - # This ensures that the pid namespace is shared between the host - # and the container. It's not necessary to be able to run spring - # commands, but it is necessary for "spring status" and "spring stop" - # to work properly. -# pid: host - - db: - # Debug - #command: bash - #tty: true - # command: mysqld_safe --skip-grant-tables - image: mariadb:latest - container_name: ensl_dev_db - user: "mysql:mysql" - volumes: - - "./db/data:/var/lib/mysql" - - "./db/initdb.d:/docker-entrypoint-initdb.d" - - "./ext/mysql.conf.d:/etc/mysql/conf.d" - environment: - - MYSQL_DATABASE=ensl - - MYSQL_USER=ensl - - MYSQL_USERNAME=ensl - - MYSQL_PASSWORD=ensl - - MYSQL_ROOT_PASSWORD=ensl - - MYSQL_ROOT_HOST=% - - memcached: - image: memcached:latest - container_name: ensl_dev_memcached - - #redis: - # image: redis diff --git a/docker-compose.yml b/docker-compose.yml index c0e10fb..af4a168 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,40 +1,140 @@ -version: "3" +version: "3.4" services: + # + # Main service + # web: - image: ensl/ensl.org:latest + # For debug; Use attach rather than this + # command: /bin/bash + command: "bundle exec puma" + tty: true + stdin_open: true + container_name: "ensl_${RAILS_ENV}" + user: "web:web" + build: + context: ./ + dockerfile: Dockerfile + target: ensl_${RAILS_ENV} volumes: - - "../public:/var/www/public" - - "../logs:/var/www/log" + - ".:/var/www/" + environment: + RAILS_ENV: $RAILS_ENV ports: - - "4000:4000" - depends_on: + - "${PUMA_PORT}:${PUMA_PORT}" + - "35729:35729" + links: - db - memcached - smtp - # - redis + #- spring + #- redis + + # + # Testing + # + + # Seperate test container so dev / test don't cause problems + test: + command: ["bash", "-c", "while true; do sleep 100; done;"] + container_name: ensl_test + build: + context: ./ + dockerfile: Dockerfile + target: ensl_development + env_file: + - .env.test + ports: + - ${TEST_APP_PORT}:${TEST_APP_PORT} # Capybara listens here + links: + - db + - memcached + - selenium + volumes: + - ".:/var/www" + # command: bin/spring server + environment: + RAILS_ENV: test + networks: + default: + aliases: + - test + + selenium: + image: selenium/standalone-chrome-debug + container_name: ensl_${RAILS_ENV}_selenium + ports: + - 5900:5900 + - 4444:4444 + + # + # Common services: These are shared by all envs. + # + + memcached: + image: memcached:alpine + container_name: ensl_${RAILS_ENV}_memcached + + redis: + image: 'redis:4.0-alpine' + container_name: ensl_${RAILS_ENV}_redis + db: image: mariadb:latest - command: mysqld + container_name: ensl_${RAILS_ENV}_db + user: "mysql:mysql" + # debug; command: mysqld_safe --skip-grant-tables volumes: - - "./db_data:/var/lib/mysql" + - "./db/data:/var/lib/mysql" + - "./db/initdb.d:/docker-entrypoint-initdb.d" - "./ext/mysql.conf.d:/etc/mysql/conf.d" environment: - - MYSQL_DATABASE - - MYSQL_USER - - MYSQL_USERNAME - - MYSQL_PASSWORD - - MYSQL_ROOT_PASSWORD -# - MYSQL_ROOT_HOST - memcached: - image: memcached:latest + - MYSQL_DATABASE=$MYSQL_DATABASE + - MYSQL_USER=$MYSQL_USER + - MYSQL_PASSWORD=$MYSQL_PASSWORD + - MYSQL_ROOT_PASSWORD=$MYSQL_PASSWORD + - MYSQL_ROOT_HOST=$MYSQL_ROOT_HOST + smtp: image: mwader/postfix-relay:latest + container_name: ensl_${RAILS_ENV}_smtp restart: always volumes: - - "../dkim:/etc/opendkim/keys" + - "./ext/dkim:/etc/opendkim/keys" environment: - - POSTFIX_myhostname=ensl.org - - OPENDKIM_DOMAINS=ensl.org - #redis: - # image: redis + - POSTFIX_myhostname=$APP_DOMAIN + - OPENDKIM_DOMAINS=$APP_DOMAIN + + nginx: + image: nginx:latest + command: /bin/bash + container_name: ensl_${RAILS_ENV}_nginx + volumes: + - ./ext/ssl/fullchain.pem:/etc/ssl/certs/ensl_fullchain.pem + - ./ext/ssl/privkey.pem:/etc/ssl/private/ensl_privkey.pem + - ./ext/nginx.conf.d/:/etc/nginx/conf.d/ + - ./public:/var/www + ports: + - $APP_PORT:80 + - $APP_PORT_SSL:443 + environment: + - APP_DOMAIN=$APP_DOMAIN + - APP_PORT=$APP_PORT + - PUMA_PORT=$PUMA_PORT + - RAILS_ENV=$RAILS_ENV + # command: /bin/bash -c "envsubst '$$PUMA_PORT' < /etc/nginx/conf.d/nginx.conf.template > /etc/nginx/conf.d/default.conf && nginx -g 'daemon off;'" + +# spring: +# build: +# context: ./ +# dockerfile: Dockerfile.dev +# args: +# buildno: 1 +# volumes: +# - .:/var/www +# command: spring server +# This ensures that the pid namespace is shared between the host +# and the container. It's not necessary to be able to run spring +# commands, but it is necessary for "spring status" and "spring stop" +# to work properly. +# pid: host \ No newline at end of file diff --git a/ext/nginx.conf.d/nginx.conf b/ext/nginx.conf.d/nginx.conf deleted file mode 100644 index 06fc681..0000000 --- a/ext/nginx.conf.d/nginx.conf +++ /dev/null @@ -1,119 +0,0 @@ -upstream puma { - # server unix:/srv/ensl/puma.production.sock fail_timeout=0; - server localhost:4000; -} -server { - listen *:80; - listen *:443 ssl; - - ssl_certificate /etc/letsencrypt/live/ensl.org/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/ensl.org/privkey.pem; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - - server_name ensl.org; - root /srv/ensl/root_domain; - return 301 https://www.ensl.org$request_uri; -} -server { - listen *:80; - server_name www.ensl.org; - return 301 https://www.ensl.org$request_uri; -} -server { - listen *:443 ssl default_server; - server_name www.ensl.org; - root /srv/ensl/public; - index index.html index.htm index.php; - - ssl_certificate /etc/letsencrypt/live/ensl.org/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/ensl.org/privkey.pem; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA; - ssl_session_timeout 1d; - ssl_session_cache shared:SSL:50m; - ssl_stapling on; - ssl_stapling_verify on; - #add_header Strict-Transport-Security max-age=15768000; - - access_log /var/log/nginx/ensl.access.log; - error_log /var/log/nginx/ensl.error.log; - - rewrite_log on; - client_max_body_size 20M; - keepalive_timeout 10; - - location ~ /.well-known { - allow all; - autoindex on; - } - location ^~ /assets/ { - gzip_static on; - expires max; - add_header Cache-Control public; - } - location /files/ { - try_files $uri $uri/ @puma; - alias /srv/ensl/files/; - autoindex on; - } - location @puma { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_pass http://puma; - } - - try_files $uri/index.html $uri @puma; -} - - -upstream puma_staging { - server localhost:5000; -} -server { - listen *:5000 ssl; - server_name www.ensl.org; - root /srv/ensl.org.staging/public; - index index.html index.htm index.php; - - auth_basic “ENSL Staging area”; - auth_basic_user_file /etc/nginx/.htpasswd; - - ssl_certificate /etc/letsencrypt/live/ensl.org/fullchain.pem; - ssl_certificate_key /etc/letsencrypt/live/ensl.org/privkey.pem; - ssl_protocols TLSv1 TLSv1.1 TLSv1.2; - ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA; - ssl_session_timeout 1d; - ssl_session_cache shared:SSL:50m; - ssl_stapling on; - ssl_stapling_verify on; - #add_header Strict-Transport-Security max-age=15768000; - - #access_log /var/log/nginx/ensl.access.log; - #error_log /var/log/nginx/ensl.error.log; - - rewrite_log on; - client_max_body_size 20M; - keepalive_timeout 10; - - location ~ /.well-known { - allow all; - autoindex on; - } - location ^~ /assets/ { - gzip_static on; - expires max; - add_header Cache-Control public; - } - location /files/ { - try_files $uri $uri/ @puma_staging; - alias /srv/ensl/files/; - autoindex on; - } - location @puma_staging { - proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; - proxy_set_header Host $http_host; - proxy_pass http://puma_staging; - } - - try_files $uri/index.html $uri @puma_staging; -} diff --git a/ext/nginx.conf.d/nginx.conf.template b/ext/nginx.conf.d/nginx.conf.template new file mode 100644 index 0000000..3fea65b --- /dev/null +++ b/ext/nginx.conf.d/nginx.conf.template @@ -0,0 +1,75 @@ +# Staging nginx conf +# The point of this config file is to have near-identical setup in staging. +# Use it in production or copy it over + +upstream puma { + server localhost:$PUMA_PORT; + # server unix:/var/tmp/puma.$RAILS_ENV.sock fail_timeout=0; +} + +# root-level -> www redirect +server { + listen *:80; + listen *:443 ssl; + + ssl_certificate /etc/ssl/certs/ensl_fullchain.pem; + ssl_certificate_key /etc/ssl/private/ensl_privkey.pem; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + + server_name ensl.org; + root /var/www; + return 301 https://www.ensl.org$request_uri; +} + +# HTTP -> HTTPS redirect +server { + listen *:80; + server_name www.ensl.org; + return 301 https://www.ensl.org$request_uri; +} + +server { + listen *:443 ssl default_server; + server_name www.ensl.org; + root /var/www; + index index.html index.htm index.php; + + ssl_certificate /etc/ssl/certs/ensl_fullchain.pem; + ssl_certificate_key /etc/ssl/private/ensl_privkey.pem; + ssl_protocols TLSv1 TLSv1.1 TLSv1.2; + ssl_ciphers ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES256-GCM-SHA384:DHE-RSA-AES128-GCM-SHA256:DHE-DSS-AES128-GCM-SHA256:kEDH+AESGCM:ECDHE-RSA-AES128-SHA256:ECDHE-ECDSA-AES128-SHA256:ECDHE-RSA-AES128-SHA:ECDHE-ECDSA-AES128-SHA:ECDHE-RSA-AES256-SHA384:ECDHE-ECDSA-AES256-SHA384:ECDHE-RSA-AES256-SHA:ECDHE-ECDSA-AES256-SHA:DHE-RSA-AES128-SHA256:DHE-RSA-AES128-SHA:DHE-DSS-AES128-SHA256:DHE-RSA-AES256-SHA256:DHE-DSS-AES256-SHA:DHE-RSA-AES256-SHA:AES128-GCM-SHA256:AES256-GCM-SHA384:AES128-SHA256:AES256-SHA256:AES128-SHA:AES256-SHA:AES:CAMELLIA:DES-CBC3-SHA:!aNULL:!eNULL:!EXPORT:!DES:!RC4:!MD5:!PSK:!aECDH:!EDH-DSS-DES-CBC3-SHA:!EDH-RSA-DES-CBC3-SHA:!KRB5-DES-CBC3-SHA; + ssl_session_timeout 1d; + ssl_session_cache shared:SSL:50m; + ssl_stapling on; + ssl_stapling_verify on; + #add_header Strict-Transport-Security max-age=15768000; + + access_log /var/log/nginx/ensl.access.log; + error_log /var/log/nginx/ensl.error.log; + + rewrite_log on; + client_max_body_size 20M; + keepalive_timeout 10; + + location ~ /.well-known { + allow all; + autoindex on; + } + location ^~ /assets/ { + gzip_static on; + expires max; + add_header Cache-Control public; + } + location /files/ { + # try_files $uri $uri/ @puma; + # alias root /var/www/files/; + autoindex on; + } + location @puma { + proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; + proxy_set_header Host $http_host; + proxy_pass http://puma; + } + + try_files $uri/index.html $uri @puma; +} \ No newline at end of file diff --git a/script/env.sh b/script/env.sh new file mode 100755 index 0000000..b3667a7 --- /dev/null +++ b/script/env.sh @@ -0,0 +1,18 @@ +#!/bin/bash +# use source script/env.sh + +args=("$@") + +if [[ $# -eq 1 ]]; then + args+=(.env) +fi + +for FILE in "$@" +do + echo "Loading env vars from: $FILE" + ARGS=$(cat $FILE |grep -vE '^[[:space:]]*(#.*)*$') + + export $(echo $ARGS|xargs) + echo "$ARGS\n" +done + diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 587cd15..e71b7f8 100755 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -1,7 +1,6 @@ ENV["RAILS_ENV"] ||= "test" -require 'dotenv' -Dotenv.load() +require 'dotenv/load' require "codeclimate-test-reporter" require "simplecov"