diff --git a/.dockerignore b/.dockerignore new file mode 100644 index 0000000000..fe7cd13957 --- /dev/null +++ b/.dockerignore @@ -0,0 +1,4 @@ +.git +.gitignore +log/* +tmp/* diff --git a/DOCKER.md b/DOCKER.md new file mode 100644 index 0000000000..8dc231b08c --- /dev/null +++ b/DOCKER.md @@ -0,0 +1,47 @@ +### Docker + +It is possible to setup the Open Food Network app easily with Docker and Docker Compose. +The objective is to spare configuration time, in order to help people testing the app and contribute to it. +It can also be used as documentation. It is not perfect but it is used in many other projects and many devs are used to it nowadays. + +### Install Docker + +Please check the documentation here, https://docs.docker.com/install/ to install Docker. + +For Docker Compose, information are here: https://docs.docker.com/compose/install/. + +Better to have at least 2GB free on your computer in order to download images and create containers for Open Food Network app. + + +### Use Docker with Open Food Network + +Open a terminal with a shell. + +Clone the repository: + +```sh +$ git clone git@github.com:openfoodfoundation/openfoodnetwork.git +``` + +Go at the root of the app: + +```sh +$ cd openfoodnetwork +``` + +Download the Docker images and build the containers: + +```sh +$ docker-compose build +``` + +Run the app with all the required containers: + +```sh +$ docker-compose up +``` + +This command will setup the database and seed it with sample data. The default admin user is 'ofn@example.com' with 'ofn123' password. +Check the app in the browser at `http:://localhost:3000`. + +You will then get the trace of the containers in the terminal. You can stop the containers using Ctrl-C in the terminal. diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000000..0438bc39a5 --- /dev/null +++ b/Dockerfile @@ -0,0 +1,31 @@ +FROM ubuntu:18.04 + +# Install all the requirements +RUN apt-get update && apt-get install -y curl git build-essential software-properties-common wget zlib1g-dev libssl1.0-dev libreadline-dev libyaml-dev libffi-dev libxml2-dev libxslt1-dev wait-for-it + +# Setup ENV variables +ENV PATH /usr/local/src/rbenv/shims:/usr/local/src/rbenv/bin:$PATH +ENV RBENV_ROOT /usr/local/src/rbenv +ENV RUBY_VERSION 2.1.5 +ENV CONFIGURE_OPTS --disable-install-doc + +# Rbenv & Ruby part +RUN git clone https://github.com/rbenv/rbenv.git ${RBENV_ROOT} && \ + git clone https://github.com/rbenv/ruby-build.git ${RBENV_ROOT}/plugins/ruby-build && \ + ${RBENV_ROOT}/plugins/ruby-build/install.sh && \ + echo 'eval "$(rbenv init -)"' >> /etc/profile.d/rbenv.sh && \ + rbenv install $RUBY_VERSION && \ + rbenv global $RUBY_VERSION && \ + gem install bundler --version=1.17.2 + +# Postgres +RUN sh -c "echo 'deb https://apt.postgresql.org/pub/repos/apt/ bionic-pgdg main' > /etc/apt/sources.list.d/pgdg.list" && \ + wget --quiet -O - https://apt.postgresql.org/pub/repos/apt/ACCC4CF8.asc | apt-key add - && \ + apt-get update && \ + apt-get install -yqq --no-install-recommends postgresql-client-9.5 libpq-dev + +ENV BUNDLE_PATH /bundles + +COPY . /usr/src/app/ + +WORKDIR /usr/src/app diff --git a/config/database.yml b/config/database.yml index d313dd74e4..9ef24edfd3 100644 --- a/config/database.yml +++ b/config/database.yml @@ -1,33 +1,19 @@ -development: +default: &default adapter: postgresql - encoding: unicode - database: open_food_network_dev + encoding: utf8 pool: 5 - host: localhost + timeout: 5000 + host: db + port: 5432 + +development: + <<: *default + database: open_food_network_dev username: ofn password: f00d test: - adapter: postgresql - encoding: unicode + <<: *default database: open_food_network_test - pool: 5 - host: localhost - username: ofn - password: f00d - -production: - adapter: postgresql - encoding: unicode - database: open_food_network_prod - pool: 5 - username: ofn - password: f00d - -staging: - adapter: postgresql - encoding: unicode - database: open_food_network_prod - pool: 5 username: ofn password: f00d diff --git a/docker-compose.yml b/docker-compose.yml new file mode 100644 index 0000000000..b29c858317 --- /dev/null +++ b/docker-compose.yml @@ -0,0 +1,38 @@ +version: '3' + +services: + db: + image: postgres:9.5 + restart: always + environment: + POSTGRES_PASSWORD: f00d + POSTGRES_USER: ofn + volumes: + - 'postgres:/var/lib/postgresql/data' + web: + tty: true + stdin_open: true + build: . + ports: + - 3000:3000 + volumes: + - .:/usr/src/app + - gems:/bundles + - ./config/database.yml:/usr/src/app/config/database.yml + - ./config/application.yml.example:/usr/src/app/config/application.yml + depends_on: + - db + environment: + ADMIN_EMAIL: ofn@example.com + ADMIN_PASSWORD: ofn123 + command: > + bash -c "(bundle check || bundle install) && + wait-for-it -t 30 db:5432 && + bundle exec rake db:reset db:test:prepare && + bundle exec rake ofn:sample_data || true && + rm -f tmp/pids/server.pid && + bundle exec rails s -p 3000 -b '0.0.0.0'" + +volumes: + gems: + postgres: diff --git a/lib/tasks/dev.rake b/lib/tasks/dev.rake deleted file mode 100644 index 4677a1786c..0000000000 --- a/lib/tasks/dev.rake +++ /dev/null @@ -1,305 +0,0 @@ -namespace :ofn do - namespace :dev do - desc 'load sample data' - task load_sample_data: :environment do - require_relative '../../spec/factories' - task_name = "openfoodnetwork:dev:load_sample_data" - - country = Spree::Country.find_by_iso(ENV.fetch('DEFAULT_COUNTRY_CODE')) - state = country.states.first - - # -- Shipping / payment information - unless Spree::Zone.find_by_name 'Australia' - puts "[#{task_name}] Seeding shipping / payment information" - - zone = FactoryBot.create(:zone, name: 'Australia', zone_members: []) - Spree::ZoneMember.create(zone: zone, zoneable: country) - address = FactoryBot.create( - :address, - address1: "15/1 Ballantyne Street", - zipcode: "3153", - city: "Thornbury", - country: country, - state: state - ) - enterprise = FactoryBot.create(:enterprise, address: address) - - FactoryBot.create(:shipping_method, zone: zone, distributors: [enterprise]) - end - - # -- Taxonomies - unless Spree::Taxonomy.find_by_name 'Products' - puts "[#{task_name}] Seeding taxonomies" - taxonomy = Spree::Taxonomy.find_by_name('Products') || FactoryBot.create(:taxonomy, - name: 'Products') - taxonomy_root = taxonomy.root - - taxons = ['Vegetables', 'Fruit', 'Oils', 'Preserves and Sauces', 'Dairy', 'Meat and Fish'] - taxons.each do |taxon_name| - FactoryBot.create(:taxon, - name: taxon_name, - parent_id: taxonomy_root.id, - taxonomy_id: taxonomy.id) - end - end - - # -- Addresses - unless Spree::Address.find_by_zipcode "3160" - puts "[#{task_name}] Seeding addresses" - - FactoryBot.create(:address, - address1: "25 Myrtle Street", - zipcode: "3153", - city: "Bayswater", - country: country, - state: state) - FactoryBot.create(:address, - address1: "6 Rollings Road", - zipcode: "3156", - city: "Upper Ferntree Gully", - country: country, - state: state) - FactoryBot.create(:address, - address1: "72 Lake Road", - zipcode: "3130", - city: "Blackburn", - country: country, - state: state) - FactoryBot.create(:address, - address1: "7 Verbena Street", - zipcode: "3195", - city: "Mordialloc", - country: country, - state: state) - FactoryBot.create(:address, - address1: "20 Galvin Street", - zipcode: "3018", - city: "Altona", - country: country, - state: state) - FactoryBot.create(:address, - address1: "59 Websters Road", - zipcode: "3106", - city: "Templestowe", - country: country, - state: state) - FactoryBot.create(:address, - address1: "17 Torresdale Drive", - zipcode: "3155", - city: "Boronia", - country: country, - state: state) - FactoryBot.create(:address, - address1: "21 Robina CRT", - zipcode: "3764", - city: "Kilmore", - country: country, - state: state) - FactoryBot.create(:address, - address1: "25 Kendall Street", - zipcode: "3134", - city: "Ringwood", - country: country, - state: state) - FactoryBot.create(:address, - address1: "2 Mines Road", - zipcode: "3135", - city: "Ringwood East", - country: country, - state: state) - FactoryBot.create(:address, - address1: "183 Millers Road", - zipcode: "3025", - city: "Altona North", - country: country, - state: state) - FactoryBot.create(:address, - address1: "310 Pascoe Vale Road", - zipcode: "3040", - city: "Essendon", - country: country, - state: state) - FactoryBot.create(:address, - address1: "6 Martin Street", - zipcode: "3160", - city: "Belgrave", - country: country, - state: state) - end - - # -- Enterprises - if Enterprise.count < 2 - puts "[#{task_name}] Seeding enterprises" - - 3.times do - FactoryBot.create(:supplier_enterprise, - address: Spree::Address.find_by_zipcode("3160")) - end - - FactoryBot.create(:distributor_enterprise, - name: "Green Grass", - address: Spree::Address.find_by_zipcode("3153")) - FactoryBot.create(:distributor_enterprise, - name: "AusFarmers United", - address: Spree::Address.find_by_zipcode("3156")) - FactoryBot.create(:distributor_enterprise, - name: "Blackburn FreeGrossers", - address: Spree::Address.find_by_zipcode("3130")) - FactoryBot.create(:distributor_enterprise, - name: "MegaFoods", - address: Spree::Address.find_by_zipcode("3195")) - FactoryBot.create(:distributor_enterprise, - name: "Eco Butchers", - address: Spree::Address.find_by_zipcode("3018")) - FactoryBot.create(:distributor_enterprise, - name: "Western Wines", - address: Spree::Address.find_by_zipcode("3106")) - FactoryBot.create(:distributor_enterprise, - name: "QuickFresh", - address: Spree::Address.find_by_zipcode("3155")) - FactoryBot.create(:distributor_enterprise, - name: "Fooderers", - address: Spree::Address.find_by_zipcode("3764")) - FactoryBot.create(:distributor_enterprise, - name: "Food Local", - address: Spree::Address.find_by_zipcode("3134")) - FactoryBot.create(:distributor_enterprise, - name: "Green Food Trading Corporation", - address: Spree::Address.find_by_zipcode("3135")) - FactoryBot.create(:distributor_enterprise, - name: "Better Food", - address: Spree::Address.find_by_zipcode("3025")) - FactoryBot.create(:distributor_enterprise, - name: "Gippsland Poultry", - address: Spree::Address.find_by_zipcode("3040")) - end - - # -- Enterprise users - if Spree::User.count < 2 - puts "[#{task_name}] Seeding enterprise users" - - pw = "spree123" - - u = FactoryBot.create(:user, - email: "sup@example.com", - password: pw, - password_confirmation: pw) - u.enterprises << Enterprise.is_primary_producer.first - u.enterprises << Enterprise.is_primary_producer.second - - user_enterprises = u.enterprise_roles.map{ |er| er.enterprise.name }.join(", ") - puts " Supplier User created: #{u.email}/#{pw} (" + user_enterprises + ")" - - u = FactoryBot.create(:user, - email: "dist@example.com", - password: pw, - password_confirmation: pw) - u.enterprises << Enterprise.is_distributor.first - u.enterprises << Enterprise.is_distributor.second - user_enterprises = u.enterprise_roles.map{ |er| er.enterprise.name }.join(", ") - puts " Distributor User created: #{u.email}/#{pw} (" + user_enterprises + ")" - end - - # -- Enterprise fees - if EnterpriseFee.count < 2 - Enterprise.is_distributor.each do |distributor| - FactoryBot.create(:enterprise_fee, enterprise: distributor) - end - end - - # -- Enterprise Payment Methods - if Spree::PaymentMethod.count < 2 - Enterprise.is_distributor.each do |distributor| - FactoryBot.create(:payment_method, - distributors: [distributor], - name: "Cheque (#{distributor.name})", - environment: 'development') - end - end - - # -- Products - if Spree::Product.count < 1 - puts "[#{task_name}] Seeding products" - - FactoryBot.create(:product, - name: 'Garlic', - price: 20.00, - supplier: Enterprise.is_primary_producer[0], - taxons: [Spree::Taxon.find_by_name('Vegetables')]) - - FactoryBot.create(:product, - name: 'Fuji Apple', - price: 5.00, - supplier: Enterprise.is_primary_producer[1], - taxons: [Spree::Taxon.find_by_name('Fruit')]) - - FactoryBot.create(:product, - name: 'Beef - 5kg Trays', - price: 50.00, - supplier: Enterprise.is_primary_producer[2], - taxons: [Spree::Taxon.find_by_name('Meat and Fish')]) - - FactoryBot.create(:product, - name: 'Carrots', - price: 3.00, - supplier: Enterprise.is_primary_producer[2], - taxons: [Spree::Taxon.find_by_name('Meat and Fish')]) - - FactoryBot.create(:product, - name: 'Potatoes', - price: 2.00, - supplier: Enterprise.is_primary_producer[2], - taxons: [Spree::Taxon.find_by_name('Meat and Fish')]) - - FactoryBot.create(:product, - name: 'Tomatoes', - price: 2.00, - supplier: Enterprise.is_primary_producer[2], - taxons: [Spree::Taxon.find_by_name('Meat and Fish')]) - - FactoryBot.create(:product, - name: 'Potatoes', - price: 2.00, - supplier: Enterprise.is_primary_producer[2], - taxons: [Spree::Taxon.find_by_name('Meat and Fish')]) - end - - enterprise2 = Enterprise.find_by_name('Enterprise 2') - enterprise2.sells = 'any' - enterprise2.shipping_methods << FactoryBot.create(:shipping_method, - name: 'Pickup', - zone: zone, - require_ship_address: true, - calculator_type: 'Calculator::Weight', - distributors: [enterprise2]) - enterprise2.payment_methods << Spree::PaymentMethod.last - enterprise2.save! - - variants = Spree::Variant - .joins(:product) - .where('spree_products.supplier_id = ?', enterprise2.id) - - CreateOrderCycle.new(enterprise2, variants).call - - unless EnterpriseRole.where( user_id: Spree::User.first, enterprise_id: enterprise2 ).any? - EnterpriseRole.create!(user: Spree::User.first, enterprise: enterprise2) - end - display_deprecation_warning - end - - def display_deprecation_warning - behaviour = ActiveSupport::Deprecation.behavior = :stderr - ActiveSupport::Deprecation.behavior = :stderr - ActiveSupport::Deprecation.warn(<