diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 00000000..dae6acc5 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,11 @@ +.git +.idea +.sass-cache +log +config/database.yml +public/assets +public/system +tmp/* +vendor/bundle +coverage +*.sql* diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 00000000..f337aafd --- /dev/null +++ b/Dockerfile @@ -0,0 +1,40 @@ +FROM ruby:2.1-slim + +RUN apt-get update && \ + apt-get install --no-install-recommends -y \ + mysql-client \ + git \ + make \ + gcc \ + g++ \ + patch \ + libsqlite3-dev \ + libv8-dev \ + libmysqlclient-dev \ + libxml2-dev \ + libxslt1-dev \ + libffi-dev \ + libreadline-dev \ + xvfb \ + iceweasel && \ + rm -rf /var/lib/apt/lists/* && \ + apt-get clean + +ENV WORKDIR /usr/src/app + +RUN mkdir -p $WORKDIR +WORKDIR $WORKDIR + +# Copy plugins before the rest to allow bundler loading gemspecs +# TODO: Move plugins to gems and add them to Gemfile instead +COPY plugins $WORKDIR/plugins + +COPY Gemfile $WORKDIR/ +COPY Gemfile.lock $WORKDIR/ +RUN bundle install --jobs 4 + +COPY . $WORKDIR + +EXPOSE 3000 + +CMD ["rails", "server"] diff --git a/bin/test b/bin/test new file mode 100755 index 00000000..590b2a13 --- /dev/null +++ b/bin/test @@ -0,0 +1,17 @@ +#!/bin/sh + +# We use TEST_DATABASE_URL to make sure we don't accidentaly overwrite dev/prod db +unset DATABASE_URL; export DATABASE_URL +[ "$TEST_DATABASE_URL" ] && export DATABASE_URL="$TEST_DATABASE_URL" +export RAILS_ENV=test + +# Start virtuals X environment to allow integration testing via firefox/iceweasel +export DISPLAY=:99 +Xvfb $DISPLAY -nolisten tcp & +XVFB_PID=$! + +# Start tests +rspec + +# Cleanup +kill $XVFB_PID diff --git a/config/environments/development.rb.SAMPLE b/config/environments/development.rb.SAMPLE index 0b84aec8..6aad5be9 100644 --- a/config/environments/development.rb.SAMPLE +++ b/config/environments/development.rb.SAMPLE @@ -39,8 +39,8 @@ Foodsoft::Application.configure do # Mailcatcher config, start mailcatcher from console with 'mailcatcher' # Mailcatcher can be installed by gem install mailcatcher config.action_mailer.delivery_method = :smtp - config.action_mailer.smtp_settings = { address: "localhost", port: 1025 } + config.action_mailer.smtp_settings = { address: ENV.fetch('MAILCATCHER_PORT_1025_TCP_ADDR', 'localhost'), port: ENV.fetch('MAILCATCHER_PORT_1025_TCP_PORT', 1025) } # Run resque tasks as part of the main app (not recommended for production) - Resque.inline = true + Resque.inline = true unless ENV['REDIS_URL'] end diff --git a/config/initializers/resque.rb b/config/initializers/resque.rb new file mode 100644 index 00000000..6301afa4 --- /dev/null +++ b/config/initializers/resque.rb @@ -0,0 +1,2 @@ +# Initializer to configure resque daemon +Resque.redis = ENV.fetch("REDIS_URL", "redis://localhost:6379") diff --git a/doc/SETUP_DEVELOPMENT.md b/doc/SETUP_DEVELOPMENT.md index c011f5db..1e507c32 100644 --- a/doc/SETUP_DEVELOPMENT.md +++ b/doc/SETUP_DEVELOPMENT.md @@ -5,6 +5,10 @@ Gratulations, if you read this file locally, you have successfully cloned the foodsoft project from the git repository. Now you are only a few steps away from trying it out and then jumping into development. +This document describes how to setup Foodsoft for development on your local system. +Alternatively, you [run Foodsoft using Docker](SETUP_DOCKER.md). + + **System requirements**: [RVM](https://rvm.io/rvm/install), [Ruby 1.9.3+](https://www.ruby-lang.org/en/downloads/), diff --git a/doc/SETUP_DOCKER.md b/doc/SETUP_DOCKER.md new file mode 100644 index 00000000..f886e316 --- /dev/null +++ b/doc/SETUP_DOCKER.md @@ -0,0 +1,69 @@ +# Foodsoft on Docker + +This document explains setting up and using Foodsoft with Docker. + +## Requirements + +* Docker (=> 1.5) +* Docker Compose (=> 1.1) +* Nothing more, no ruby, mysql, redis etc! + +For installing instructions see https://docs.docker.com/installation/. +Docker runs on every modern linux kernel, but also with a little help on MacOS +and Windows! + +## Setup + +Create docker volume for mysql data: + + mkdir -p ~/.docker-volumes/foodsoft/mysql + +Setup foodsoft development data: (This will take some time, containers needs +to be pulled from docker registry and a lot dependencies needs to be installed.) + + docker-compose run app rake foodsoft:setup_development + +## Usage + +Start containers (in foreground, stop them with `CTRL-C`) + + docker-compose up + +Run a rails/rake command + + docker-compose run app rake db:migrate + +Open a rails console + + docker-compose run app rails c + +Setup the test database + + docker-compose run app rake db:setup RAILS_ENV=test DATABASE_URL=mysql2://root:secret@mysql/test + +Run the tests + + docker-compose run app ./bin/test + +Jump in a running container for debugging. + + docker exec -ti foodsoft_app_1 bash + +## Notes + +### Gemfile updates + +This is bit tricky, as the gemfiles are stored in the container and so we have +to rebuild the container each time we change the Gemfile. To avoid installing +all the gems from scratch we can use this workaround: + +```bash +docker-compose run app bundle update rails # Update Gemfile.lock file +docker ps -a # Look for the last exited container and grab the Container ID +docker commit -m "Updated rails" foodsoft_app +``` + +### Database configuration + +To make this easier we use the environment variable `DATABASE_URL` +(and `TEST_DATABASE_URL` when using the testing script). diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 00000000..6078cd0b --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,36 @@ +app: &app + build: . + command: bundle exec rails s + volumes: + - .:/usr/src/app + ports: + - "3000:3000" + links: + - mysql + - redis + - mailcatcher + environment: + - DATABASE_URL=mysql2://root:secret@mysql/development + - REDIS_URL=redis://redis:6379 + - QUEUE=foodsoft_notifier + - TEST_DATABASE_URL=mysql2://root:secret@mysql/test + +resque: + <<: *app + command: rake resque:work + ports: [] + +mailcatcher: + image: aboutsource/mailcatcher + ports: + - "1080:1080" + +mysql: + image: mysql:5.5 + volumes: + - ~/.docker-volumes/foodsoft/mysql:/var/lib/mysql + environment: + - MYSQL_ROOT_PASSWORD=secret + +redis: + image: redis:2.8 diff --git a/lib/tasks/foodsoft_setup.rake b/lib/tasks/foodsoft_setup.rake index 74b7d6b0..da09b6a1 100644 --- a/lib/tasks/foodsoft_setup.rake +++ b/lib/tasks/foodsoft_setup.rake @@ -58,6 +58,10 @@ end def setup_database file = 'config/database.yml' + if ENV['DATABASE_URL'] + puts blue "DATABASE_URL found, please remember to also set it when running Foodsoft" + return nil + end return nil if skip?(file) database = ask("What kind of database do you use?\nOptions:\n(1) MySQL\n(2) SQLite", ["1","2"]) @@ -110,6 +114,7 @@ def setup_secret_token end def start_mailcatcher + return nil if ENV['MAILCATCHER_PORT'] # skip when it has an existing Docker container mailcatcher = ask("Do you want to start mailcatcher?\nOptions:\n(y) Yes\n(n) No", ["y","n"]) if mailcatcher === "y" puts yellow "Starting mailcatcher at http://localhost:1080..."