diff --git a/.app_version b/.app_version index 3f8003cd..0aeaf413 100644 --- a/.app_version +++ b/.app_version @@ -1 +1 @@ -0.34.2 +0.34.3 diff --git a/.env.template b/.env.template deleted file mode 100644 index e69de29b..00000000 diff --git a/.github/workflows/build_and_push.yml b/.github/workflows/build_and_push.yml index 3c04cdb6..23cb3a36 100644 --- a/.github/workflows/build_and_push.yml +++ b/.github/workflows/build_and_push.yml @@ -96,7 +96,7 @@ jobs: uses: docker/build-push-action@v5 with: context: . - file: ./docker/Dockerfile.dev + file: ./docker/Dockerfile push: true tags: ${{ steps.docker_meta.outputs.tags }} labels: ${{ steps.meta.outputs.labels }} diff --git a/CHANGELOG.md b/CHANGELOG.md index 936c14ca..223aa44e 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -20,8 +20,12 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## Changed - Removed useless system tests and cover map functionality with Playwright e2e tests instead. +- S3 storage now can be used in self-hosted instances as well. Set STORAGE_BACKEND environment variable to "s3" and provide AWS_ACCESS_KEY_ID, AWS_SECRET_ACCESS_KEY, AWS_REGION, AWS_BUCKET and AWS_ENDPOINT_URL environment variables to configure it. - Number of family members on self-hosted instances is no longer limited. - Export to GPX now adds adds speed and course to each point if they are available. +- `docker-compose.yml` file updated to provide sensible defaults for self-hosted production environment. +- .env.example file added with default environment variables. +- Single Dockerfile introduced so Dawarich could be run in self-hosted mode in production environment. # [0.34.2] - 2025-10-31 diff --git a/Gemfile b/Gemfile index 16c57028..e1817622 100644 --- a/Gemfile +++ b/Gemfile @@ -48,7 +48,6 @@ gem 'sidekiq-limit_fetch' gem 'sprockets-rails' gem 'stackprof' gem 'stimulus-rails' -gem 'strong_migrations', '>= 2.4.0' gem 'tailwindcss-rails', '= 3.3.2' gem 'turbo-rails', '>= 2.0.17' gem 'tzinfo-data', platforms: %i[mingw mswin x64_mingw jruby] @@ -80,4 +79,5 @@ group :development do gem 'database_consistency', '>= 2.0.5', require: false gem 'foreman' gem 'rubocop-rails', '>= 2.33.4', require: false + gem 'strong_migrations', '>= 2.4.0' end diff --git a/README.md b/README.md index 797e2177..1f1af5ec 100644 --- a/README.md +++ b/README.md @@ -79,6 +79,8 @@ Simply install one of the supported apps on your device and configure it to send ⏹️ **To stop the app**, press `Ctrl+C`. +You can use default values or create a `.env` file based on `.env.example` to customize your setup. + --- ## 🔧 How to Install Dawarich diff --git a/config/cable.yml b/config/cable.yml index e5713aea..08d639f8 100644 --- a/config/cable.yml +++ b/config/cable.yml @@ -1,6 +1,6 @@ default: &default adapter: redis - url: <%= "#{ENV.fetch("REDIS_URL")}/#{ENV.fetch('RAILS_WS_DB', 2)}" %> + url: <%= "#{ENV.fetch("REDIS_URL", "redis://localhost:6379")}/#{ENV.fetch('RAILS_WS_DB', 2)}" %> development: <<: *default diff --git a/config/environments/development.rb b/config/environments/development.rb index c940de0e..4b5e99bf 100644 --- a/config/environments/development.rb +++ b/config/environments/development.rb @@ -86,7 +86,7 @@ Rails.application.configure do # Raise error when a before_action's only/except options reference missing actions config.action_controller.raise_on_missing_callback_actions = true - hosts = ENV.fetch('APPLICATION_HOSTS', 'localhost').split(',') + hosts = ENV.fetch('APPLICATION_HOSTS', 'localhost').split(',').map(&:strip) config.action_mailer.default_url_options = { host: ENV['DOMAIN'] || hosts.first, port: ENV.fetch('PORT', 3000) } @@ -99,5 +99,5 @@ Rails.application.configure do config.lograge.enabled = true config.lograge.formatter = Lograge::Formatters::Json.new - config.active_storage.service = ENV['SELF_HOSTED'] == 'true' ? :local : :s3 + config.active_storage.service = ENV.fetch('STORAGE_BACKEND', :local) end diff --git a/config/environments/production.rb b/config/environments/production.rb index 1e4b392a..146ec651 100644 --- a/config/environments/production.rb +++ b/config/environments/production.rb @@ -43,7 +43,7 @@ Rails.application.configure do # config.action_dispatch.x_sendfile_header = "X-Accel-Redirect" # for NGINX # Store uploaded files on the local file system (see config/storage.yml for options). - config.active_storage.service = ENV['SELF_HOSTED'] == 'true' ? :local : :s3 + config.active_storage.service = ENV.fetch('STORAGE_BACKEND', :local) config.silence_healthcheck_path = '/api/v1/health' @@ -101,7 +101,7 @@ Rails.application.configure do # ] # Skip DNS rebinding protection for the health check endpoint. config.host_authorization = { exclude: ->(request) { request.path == "/api/v1/health" } } - hosts = ENV.fetch('APPLICATION_HOSTS', 'localhost').split(',') + hosts = ENV.fetch('APPLICATION_HOSTS', 'localhost').split(',').map(&:strip) config.action_mailer.default_url_options = { host: ENV['DOMAIN'] } config.hosts.concat(hosts) if hosts.present? diff --git a/config/environments/staging.rb b/config/environments/staging.rb index ded741dc..cd248041 100644 --- a/config/environments/staging.rb +++ b/config/environments/staging.rb @@ -101,7 +101,7 @@ Rails.application.configure do # ] # Skip DNS rebinding protection for the health check endpoint. config.host_authorization = { exclude: ->(request) { request.path == '/api/v1/health' } } - hosts = ENV.fetch('APPLICATION_HOSTS', 'localhost').split(',') + hosts = ENV.fetch('APPLICATION_HOSTS', 'localhost').split(',').map(&:strip) config.action_mailer.default_url_options = { host: ENV['DOMAIN'] } config.hosts.concat(hosts) if hosts.present? diff --git a/config/initializers/strong_migrations.rb b/config/initializers/strong_migrations.rb index ec978211..dfc903e2 100644 --- a/config/initializers/strong_migrations.rb +++ b/config/initializers/strong_migrations.rb @@ -1,10 +1,15 @@ +# frozen_string_literal: true + +return unless Rails.env.development? + # Mark existing migrations as safe StrongMigrations.start_after = 20_250_122_150_500 # Set timeouts for migrations -# If you use PgBouncer in transaction mode, delete these lines and set timeouts on the database user -StrongMigrations.lock_timeout = 10.seconds -StrongMigrations.statement_timeout = 1.hour +# PgBouncer in transaction mode doesn't support SET commands +# Timeouts should be set on the database user instead +# StrongMigrations.lock_timeout = 10.seconds +# StrongMigrations.statement_timeout = 1.hour # Analyze tables after indexes are added # Outdated statistics can sometimes hurt performance diff --git a/config/storage.yml b/config/storage.yml index 0d9a1fec..78b402ab 100644 --- a/config/storage.yml +++ b/config/storage.yml @@ -7,13 +7,14 @@ local: root: <%= Rails.root.join("storage") %> # Only load S3 config if not in test environment -<% if !Rails.env.test? && ENV['AWS_ACCESS_KEY_ID'] && ENV['AWS_SECRET_ACCESS_KEY'] && ENV['AWS_REGION'] && ENV['AWS_BUCKET'] %> +<% if !Rails.env.test? && ENV['AWS_ACCESS_KEY_ID'] && ENV['AWS_SECRET_ACCESS_KEY'] && ENV['AWS_REGION'] && ENV['AWS_BUCKET'] && ENV['AWS_ENDPOINT_URL'] %> s3: service: S3 access_key_id: <%= ENV.fetch("AWS_ACCESS_KEY_ID") %> secret_access_key: <%= ENV.fetch("AWS_SECRET_ACCESS_KEY") %> region: <%= ENV.fetch("AWS_REGION") %> bucket: <%= ENV.fetch("AWS_BUCKET") %> + endpoint: <%= ENV.fetch("AWS_ENDPOINT_URL") %> <% end %> # Remember not to checkin your GCS keyfile to a repository diff --git a/db/migrate/20250926220114_create_families.rb b/db/migrate/20250926220114_create_families.rb index cbaeaf25..72098b9f 100644 --- a/db/migrate/20250926220114_create_families.rb +++ b/db/migrate/20250926220114_create_families.rb @@ -8,7 +8,7 @@ class CreateFamilies < ActiveRecord::Migration[8.0] t.timestamps end - add_foreign_key :families, :users, column: :creator_id, validate: false + add_foreign_key :families, :users, column: :creator_id add_index :families, :creator_id end end diff --git a/db/migrate/20250926220135_create_family_memberships.rb b/db/migrate/20250926220135_create_family_memberships.rb index fa8e051a..90f53947 100644 --- a/db/migrate/20250926220135_create_family_memberships.rb +++ b/db/migrate/20250926220135_create_family_memberships.rb @@ -9,8 +9,8 @@ class CreateFamilyMemberships < ActiveRecord::Migration[8.0] t.timestamps end - add_foreign_key :family_memberships, :families, validate: false - add_foreign_key :family_memberships, :users, validate: false + add_foreign_key :family_memberships, :families + add_foreign_key :family_memberships, :users add_index :family_memberships, :user_id, unique: true # One family per user add_index :family_memberships, %i[family_id role], name: 'index_family_memberships_on_family_and_role' end diff --git a/db/migrate/20250926220158_create_family_invitations.rb b/db/migrate/20250926220158_create_family_invitations.rb index be841652..b9279a5f 100644 --- a/db/migrate/20250926220158_create_family_invitations.rb +++ b/db/migrate/20250926220158_create_family_invitations.rb @@ -12,8 +12,8 @@ class CreateFamilyInvitations < ActiveRecord::Migration[8.0] t.timestamps end - add_foreign_key :family_invitations, :families, validate: false - add_foreign_key :family_invitations, :users, column: :invited_by_id, validate: false + add_foreign_key :family_invitations, :families + add_foreign_key :family_invitations, :users, column: :invited_by_id add_index :family_invitations, :token, unique: true add_index :family_invitations, %i[family_id email], name: 'index_family_invitations_on_family_id_and_email' add_index :family_invitations, %i[family_id status expires_at], diff --git a/db/migrate/20250926220345_validate_family_foreign_keys.rb b/db/migrate/20250926220345_validate_family_foreign_keys.rb index 45461b79..d0161227 100644 --- a/db/migrate/20250926220345_validate_family_foreign_keys.rb +++ b/db/migrate/20250926220345_validate_family_foreign_keys.rb @@ -1,9 +1,10 @@ class ValidateFamilyForeignKeys < ActiveRecord::Migration[8.0] def change - validate_foreign_key :families, :users - validate_foreign_key :family_memberships, :families - validate_foreign_key :family_memberships, :users - validate_foreign_key :family_invitations, :families - validate_foreign_key :family_invitations, :users + # No longer needed - foreign keys are now validated immediately in their creation migrations + # validate_foreign_key :families, :users + # validate_foreign_key :family_memberships, :families + # validate_foreign_key :family_memberships, :users + # validate_foreign_key :family_invitations, :families + # validate_foreign_key :family_invitations, :users end end diff --git a/db/migrate/20251030190924_add_utm_parameters_to_users.rb b/db/migrate/20251030190924_add_utm_parameters_to_users.rb index 6e054038..1df48ce6 100644 --- a/db/migrate/20251030190924_add_utm_parameters_to_users.rb +++ b/db/migrate/20251030190924_add_utm_parameters_to_users.rb @@ -2,12 +2,10 @@ class AddUtmParametersToUsers < ActiveRecord::Migration[8.0] def change - safety_assured do - add_column :users, :utm_source, :string - add_column :users, :utm_medium, :string - add_column :users, :utm_campaign, :string - add_column :users, :utm_term, :string - add_column :users, :utm_content, :string - end + add_column :users, :utm_source, :string + add_column :users, :utm_medium, :string + add_column :users, :utm_campaign, :string + add_column :users, :utm_term, :string + add_column :users, :utm_content, :string end end diff --git a/docker/.env.example b/docker/.env.example new file mode 100644 index 00000000..4aa738fa --- /dev/null +++ b/docker/.env.example @@ -0,0 +1,141 @@ +# Dawarich Docker Compose Configuration +# Copy this file to .env and customize for your environment + +# ============================================================================= +# ENVIRONMENT CONFIGURATION +# ============================================================================= + +# Rails environment: development, staging, or production +RAILS_ENV=development + +# ============================================================================= +# DATABASE CONFIGURATION +# ============================================================================= + +# PostgreSQL credentials +POSTGRES_USER=postgres +POSTGRES_PASSWORD=password + +# Database name +POSTGRES_DB=dawarich_development + +# Database connection settings (used by Rails app) +DATABASE_HOST=dawarich_db +DATABASE_PORT=5432 +DATABASE_USERNAME=postgres +DATABASE_PASSWORD=password +DATABASE_NAME=dawarich_development + +# ============================================================================= +# REDIS CONFIGURATION +# ============================================================================= + +# Redis connection URL +REDIS_URL=redis://dawarich_redis:6379 + +# ============================================================================= +# APPLICATION SETTINGS +# ============================================================================= + +# Port to expose the application on +DAWARICH_APP_PORT=3000 + +# Application hosts (comma-separated) +# Development: localhost +# Production: your-domain.com,www.your-domain.com +APPLICATION_HOSTS=localhost,::1,127.0.0.1 + +# Application protocol (http or https) +APPLICATION_PROTOCOL=http + +# Time zone +TIME_ZONE=Europe/London + +# Minimum minutes spent in city for statistics +MIN_MINUTES_SPENT_IN_CITY=60 + +# Self-hosted flag (true for docker deployments) +SELF_HOSTED=true + +# Store geodata (reverse geocoding results) +STORE_GEODATA=true + +# Storage backend (local or s3) +STORAGE_BACKEND=local + +# ============================================================================= +# SECURITY +# ============================================================================= + +# Secret key base for production/staging +# Generate with: openssl rand -hex 64 +# Leave empty for development (will auto-generate) +# Required for production and staging environments +SECRET_KEY_BASE= + +# ============================================================================= +# BACKGROUND JOBS +# ============================================================================= + +# Sidekiq concurrency (number of threads) +BACKGROUND_PROCESSING_CONCURRENCY=10 + +# ============================================================================= +# MONITORING & LOGGING +# ============================================================================= + +# Prometheus exporter settings +PROMETHEUS_EXPORTER_ENABLED=false +PROMETHEUS_EXPORTER_HOST=0.0.0.0 +PROMETHEUS_EXPORTER_PORT=9394 +PROMETHEUS_EXPORTER_HOST_SIDEKIQ=dawarich_app + +# Uncomment to expose Prometheus port +# PROMETHEUS_PORT=9394 + +# Rails logging +RAILS_LOG_TO_STDOUT=true + +# Docker logging settings +LOG_MAX_SIZE=100m +LOG_MAX_FILE=5 + +# ============================================================================= +# RESOURCE LIMITS +# ============================================================================= + +# CPU and memory limits for the app container +APP_CPU_LIMIT=0.50 +APP_MEMORY_LIMIT=4G + +# ============================================================================= +# EXAMPLE CONFIGURATIONS BY ENVIRONMENT +# ============================================================================= + +# --- DEVELOPMENT --- +# RAILS_ENV=development +# POSTGRES_DB=dawarich_development +# DATABASE_NAME=dawarich_development +# APPLICATION_HOSTS=localhost,::1,127.0.0.1 +# APPLICATION_PROTOCOL=http +# SECRET_KEY_BASE= +# SELF_HOSTED=true + +# --- STAGING --- +# RAILS_ENV=staging +# POSTGRES_DB=dawarich_staging +# DATABASE_NAME=dawarich_staging +# APPLICATION_HOSTS=staging.example.com +# APPLICATION_PROTOCOL=https +# SECRET_KEY_BASE=your-generated-secret-key +# SELF_HOSTED=true + +# --- PRODUCTION --- +# RAILS_ENV=production +# POSTGRES_DB=dawarich_production +# DATABASE_NAME=dawarich_production +# APPLICATION_HOSTS=dawarich.example.com,www.dawarich.example.com +# APPLICATION_PROTOCOL=https +# SECRET_KEY_BASE=your-generated-secret-key +# SELF_HOSTED=true +# PROMETHEUS_EXPORTER_ENABLED=true diff --git a/docker/Dockerfile.prod b/docker/Dockerfile similarity index 88% rename from docker/Dockerfile.prod rename to docker/Dockerfile index 29279c81..16596609 100644 --- a/docker/Dockerfile.prod +++ b/docker/Dockerfile @@ -1,11 +1,12 @@ FROM ruby:3.4.6-slim +ARG RAILS_ENV=production + ENV APP_PATH=/var/app ENV BUNDLE_VERSION=2.5.21 ENV BUNDLE_PATH=/usr/local/bundle/gems ENV RAILS_LOG_TO_STDOUT=true ENV RAILS_PORT=3000 -ENV RAILS_ENV=production RUN apt-get update -qq \ && DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -qq \ @@ -25,10 +26,14 @@ RUN apt-get update -qq \ less \ libjemalloc2 libjemalloc-dev \ cmake \ - && curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \ + ca-certificates \ + && mkdir -p $APP_PATH \ + && rm -rf /var/lib/apt/lists/* + +# Install Node.js LTS for production/staging +RUN curl -fsSL https://deb.nodesource.com/setup_lts.x | bash - \ && apt-get install -y nodejs \ && npm install -g yarn \ - && mkdir -p $APP_PATH \ && rm -rf /var/lib/apt/lists/* # Use jemalloc with check for architecture @@ -41,7 +46,7 @@ RUN if [ "$(uname -m)" = "x86_64" ]; then \ # Enable YJIT ENV RUBY_YJIT_ENABLE=1 -# Update gem system and install bundler +# Update RubyGems and install Bundler RUN gem update --system 3.6.9 \ && gem install bundler --version "$BUNDLE_VERSION" \ && rm -rf $GEM_HOME/cache/* @@ -58,7 +63,7 @@ RUN bundle config set --local path 'vendor/bundle' \ COPY ../. ./ -# Precompile assets for production +# Precompile assets RUN SECRET_KEY_BASE_DUMMY=1 bundle exec rake assets:precompile \ && rm -rf node_modules tmp/cache diff --git a/docker/Dockerfile.dev b/docker/Dockerfile.dev deleted file mode 100644 index 77553008..00000000 --- a/docker/Dockerfile.dev +++ /dev/null @@ -1,87 +0,0 @@ -FROM ruby:3.4.6-slim - -ENV APP_PATH=/var/app -ENV BUNDLE_VERSION=2.5.21 -ENV BUNDLE_PATH=/usr/local/bundle/gems -ENV RAILS_LOG_TO_STDOUT=true -ENV RAILS_PORT=3000 -ENV RAILS_ENV=development -ENV SELF_HOSTED=true -ENV SIDEKIQ_USERNAME=sidekiq -ENV SIDEKIQ_PASSWORD=password -# Resolving sqlite3 error -ENV PGSSENCMODE=disable - -RUN apt-get update -qq \ - && DEBIAN_FRONTEND=noninteractive apt-get upgrade -y -qq \ - && DEBIAN_FRONTEND=noninteractive apt-get install -y --no-install-recommends \ - curl \ - wget \ - build-essential \ - git \ - postgresql-client \ - libpq-dev \ - libxml2-dev \ - libxslt-dev \ - libyaml-dev \ - libgeos-dev libgeos++-dev \ - imagemagick \ - tzdata \ - less \ - libjemalloc2 libjemalloc-dev \ - cmake \ - ca-certificates \ - && mkdir -p $APP_PATH \ - && rm -rf /var/lib/apt/lists/* - -# Install Node.js using official NodeSource script -# NodeSource supports: amd64, arm64, armhf (arm/v7) -# For unsupported architectures, fall back to Debian's nodejs package -RUN ARCH=$(dpkg --print-architecture) && \ - if [ "$ARCH" = "amd64" ] || [ "$ARCH" = "arm64" ] || [ "$ARCH" = "armhf" ]; then \ - curl -fsSL https://deb.nodesource.com/setup_22.x | bash - && \ - apt-get install -y nodejs; \ - else \ - apt-get update && \ - apt-get install -y nodejs npm; \ - fi && \ - npm install -g yarn && \ - rm -rf /var/lib/apt/lists/* - -# Use jemalloc with check for architecture -RUN if [ "$(uname -m)" = "x86_64" ]; then \ - echo "/usr/lib/x86_64-linux-gnu/libjemalloc.so.2" > /etc/ld.so.preload; \ - else \ - echo "/usr/lib/aarch64-linux-gnu/libjemalloc.so.2" > /etc/ld.so.preload; \ - fi - -# Optional: Set YJIT explicitly (enabled by default in 3.4.1 MRI builds) -ENV RUBY_YJIT_ENABLE=1 - -# Update RubyGems and install Bundler -RUN gem update --system 3.6.9 \ - && gem install bundler --version "$BUNDLE_VERSION" \ - && rm -rf $GEM_HOME/cache/* - -WORKDIR $APP_PATH - -COPY ../Gemfile ../Gemfile.lock ../.ruby-version ../vendor ./ - -RUN bundle config set --local path 'vendor/bundle' \ - && bundle install --jobs 4 --retry 3 \ - && rm -rf vendor/bundle/ruby/3.4.0/cache/*.gem - -COPY ../. ./ - -# Create caching-dev.txt file to enable Rails caching in development -RUN mkdir -p $APP_PATH/tmp && touch $APP_PATH/tmp/caching-dev.txt - -COPY ./docker/web-entrypoint.sh /usr/local/bin/web-entrypoint.sh -RUN chmod +x /usr/local/bin/web-entrypoint.sh - -COPY ./docker/sidekiq-entrypoint.sh /usr/local/bin/sidekiq-entrypoint.sh -RUN chmod +x /usr/local/bin/sidekiq-entrypoint.sh - -EXPOSE $RAILS_PORT - -ENTRYPOINT ["bundle", "exec"] diff --git a/docker/docker-compose.production.yml b/docker/docker-compose.production.yml deleted file mode 100644 index 608a916e..00000000 --- a/docker/docker-compose.production.yml +++ /dev/null @@ -1,154 +0,0 @@ -networks: - dawarich: -services: - dawarich_redis: - image: redis:7.4-alpine - container_name: dawarich_redis - command: redis-server - networks: - - dawarich - volumes: - - dawarich_redis_data:/data - restart: always - healthcheck: - test: [ "CMD", "redis-cli", "--raw", "incr", "ping" ] - interval: 10s - retries: 5 - start_period: 30s - timeout: 10s - dawarich_db: - image: postgis/postgis:17-3.5-alpine - shm_size: 1G - container_name: dawarich_db - volumes: - - dawarich_db_data:/var/lib/postgresql/data - networks: - - dawarich - environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: password - POSTGRES_DB: dawarich_production - restart: always - healthcheck: - test: [ "CMD", "pg_isready", "-U", "postgres" ] - interval: 10s - retries: 5 - start_period: 30s - timeout: 10s - dawarich_app: - image: dawarich:prod - container_name: dawarich_app - volumes: - - dawarich_public:/var/app/public - - dawarich_watched:/var/app/tmp/imports/watched - - dawarich_storage:/var/app/storage - - dawarich_db_data:/dawarich_db_data - networks: - - dawarich - ports: - - 3000:3000 - # - 9394:9394 # Prometheus exporter, uncomment if needed - stdin_open: true - tty: true - entrypoint: web-entrypoint.sh - command: ['bin/rails', 'server', '-p', '3000', '-b', '::'] - restart: on-failure - environment: - RAILS_ENV: production - REDIS_URL: redis://dawarich_redis:6379 - DATABASE_HOST: dawarich_db - DATABASE_PORT: 5432 - DATABASE_USERNAME: postgres - DATABASE_PASSWORD: password - DATABASE_NAME: dawarich_production - MIN_MINUTES_SPENT_IN_CITY: 60 - APPLICATION_HOSTS: localhost,::1,127.0.0.1 - TIME_ZONE: Europe/London - APPLICATION_PROTOCOL: http - PROMETHEUS_EXPORTER_ENABLED: false - PROMETHEUS_EXPORTER_HOST: 0.0.0.0 - PROMETHEUS_EXPORTER_PORT: 9394 - SECRET_KEY_BASE: 1234567890 - RAILS_LOG_TO_STDOUT: "true" - STORE_GEODATA: "true" - logging: - driver: "json-file" - options: - max-size: "100m" - max-file: "5" - healthcheck: - test: [ "CMD-SHELL", "wget -qO - http://127.0.0.1:3000/api/v1/health | grep -q '\"status\"\\s*:\\s*\"ok\"'" ] - interval: 10s - retries: 30 - start_period: 30s - timeout: 10s - depends_on: - dawarich_db: - condition: service_healthy - restart: true - dawarich_redis: - condition: service_healthy - restart: true - deploy: - resources: - limits: - cpus: '0.50' # Limit CPU usage to 50% of one core - memory: '4G' # Limit memory usage to 2GB - dawarich_sidekiq: - image: dawarich:prod - container_name: dawarich_sidekiq - volumes: - - dawarich_public:/var/app/public - - dawarich_watched:/var/app/tmp/imports/watched - - dawarich_storage:/var/app/storage - networks: - - dawarich - stdin_open: true - tty: true - entrypoint: sidekiq-entrypoint.sh - command: ['bundle', 'exec', 'sidekiq'] - restart: on-failure - environment: - RAILS_ENV: production - REDIS_URL: redis://dawarich_redis:6379 - DATABASE_HOST: dawarich_db - DATABASE_PORT: 5432 - DATABASE_USERNAME: postgres - DATABASE_PASSWORD: password - DATABASE_NAME: dawarich_production - APPLICATION_HOSTS: localhost,::1,127.0.0.1 - BACKGROUND_PROCESSING_CONCURRENCY: 10 - APPLICATION_PROTOCOL: http - PROMETHEUS_EXPORTER_ENABLED: false - PROMETHEUS_EXPORTER_HOST: dawarich_app - PROMETHEUS_EXPORTER_PORT: 9394 - SECRET_KEY_BASE: 1234567890 - RAILS_LOG_TO_STDOUT: "true" - STORE_GEODATA: "true" - logging: - driver: "json-file" - options: - max-size: "100m" - max-file: "5" - healthcheck: - test: [ "CMD-SHELL", "pgrep -f sidekiq" ] - interval: 10s - retries: 30 - start_period: 30s - timeout: 10s - depends_on: - dawarich_db: - condition: service_healthy - restart: true - dawarich_redis: - condition: service_healthy - restart: true - dawarich_app: - condition: service_healthy - restart: true -volumes: - dawarich_db_data: - dawarich_redis_data: - dawarich_public: - dawarich_watched: - dawarich_storage: diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml index ca0fb27c..bc9d0e94 100644 --- a/docker/docker-compose.yml +++ b/docker/docker-compose.yml @@ -1,5 +1,6 @@ networks: dawarich: + services: dawarich_redis: image: redis:7.4-alpine @@ -16,6 +17,7 @@ services: retries: 5 start_period: 30s timeout: 10s + dawarich_db: image: postgis/postgis:17-3.5-alpine shm_size: 1G @@ -27,17 +29,18 @@ services: networks: - dawarich environment: - POSTGRES_USER: postgres - POSTGRES_PASSWORD: password - POSTGRES_DB: dawarich_development + POSTGRES_USER: ${POSTGRES_USER:-postgres} + POSTGRES_PASSWORD: ${POSTGRES_PASSWORD:-password} + POSTGRES_DB: ${POSTGRES_DB:-dawarich_development} restart: always healthcheck: - test: [ "CMD-SHELL", "pg_isready -U postgres -d dawarich_development" ] + test: [ "CMD-SHELL", "pg_isready -U ${POSTGRES_USER:-postgres} -d ${POSTGRES_DB:-dawarich_development}" ] interval: 10s retries: 5 start_period: 30s timeout: 10s # command: postgres -c config_file=/etc/postgresql/postgresql.conf # Use custom config, uncomment if you want to use a custom config + dawarich_app: image: freikin/dawarich:latest container_name: dawarich_app @@ -49,34 +52,37 @@ services: networks: - dawarich ports: - - 3000:3000 - # - 9394:9394 # Prometheus exporter, uncomment if needed + - "${DAWARICH_APP_PORT:-3000}:3000" + # - "${PROMETHEUS_PORT:-9394}:9394" # Prometheus exporter, uncomment if needed stdin_open: true tty: true entrypoint: web-entrypoint.sh command: ['bin/rails', 'server', '-p', '3000', '-b', '::'] restart: on-failure environment: - RAILS_ENV: development - REDIS_URL: redis://dawarich_redis:6379 - DATABASE_HOST: dawarich_db - DATABASE_USERNAME: postgres - DATABASE_PASSWORD: password - DATABASE_NAME: dawarich_development - MIN_MINUTES_SPENT_IN_CITY: 60 - APPLICATION_HOSTS: localhost - TIME_ZONE: Europe/London - APPLICATION_PROTOCOL: http - PROMETHEUS_EXPORTER_ENABLED: "false" - PROMETHEUS_EXPORTER_HOST: 0.0.0.0 - PROMETHEUS_EXPORTER_PORT: 9394 - SELF_HOSTED: "true" - STORE_GEODATA: "true" + RAILS_ENV: ${RAILS_ENV:-development} + REDIS_URL: ${REDIS_URL:-redis://dawarich_redis:6379} + DATABASE_HOST: ${DATABASE_HOST:-dawarich_db} + DATABASE_PORT: ${DATABASE_PORT:-5432} + DATABASE_USERNAME: ${DATABASE_USERNAME:-postgres} + DATABASE_PASSWORD: ${DATABASE_PASSWORD:-password} + DATABASE_NAME: ${DATABASE_NAME:-dawarich_development} + MIN_MINUTES_SPENT_IN_CITY: ${MIN_MINUTES_SPENT_IN_CITY:-60} + APPLICATION_HOSTS: ${APPLICATION_HOSTS:-localhost,::1,127.0.0.1} + TIME_ZONE: ${TIME_ZONE:-Europe/London} + APPLICATION_PROTOCOL: ${APPLICATION_PROTOCOL:-http} + PROMETHEUS_EXPORTER_ENABLED: ${PROMETHEUS_EXPORTER_ENABLED:-"false"} + PROMETHEUS_EXPORTER_HOST: ${PROMETHEUS_EXPORTER_HOST:-0.0.0.0} + PROMETHEUS_EXPORTER_PORT: ${PROMETHEUS_EXPORTER_PORT:-9394} + SECRET_KEY_BASE: ${SECRET_KEY_BASE:-} + RAILS_LOG_TO_STDOUT: ${RAILS_LOG_TO_STDOUT:-"true"} + SELF_HOSTED: ${SELF_HOSTED:-"true"} + STORE_GEODATA: ${STORE_GEODATA:-"true"} logging: driver: "json-file" options: - max-size: "100m" - max-file: "5" + max-size: ${LOG_MAX_SIZE:-100m} + max-file: ${LOG_MAX_FILE:-5} healthcheck: test: [ "CMD-SHELL", "wget -qO - http://127.0.0.1:3000/api/v1/health | grep -q '\"status\"\\s*:\\s*\"ok\"'" ] interval: 10s @@ -93,8 +99,9 @@ services: deploy: resources: limits: - cpus: '0.50' # Limit CPU usage to 50% of one core - memory: '4G' # Limit memory usage to 4GB + cpus: ${APP_CPU_LIMIT:-0.50} + memory: ${APP_MEMORY_LIMIT:-4G} + dawarich_sidekiq: image: freikin/dawarich:latest container_name: dawarich_sidekiq @@ -110,25 +117,28 @@ services: command: ['sidekiq'] restart: on-failure environment: - RAILS_ENV: development - REDIS_URL: redis://dawarich_redis:6379 - DATABASE_HOST: dawarich_db - DATABASE_USERNAME: postgres - DATABASE_PASSWORD: password - DATABASE_NAME: dawarich_development - APPLICATION_HOSTS: localhost - BACKGROUND_PROCESSING_CONCURRENCY: 10 - APPLICATION_PROTOCOL: http - PROMETHEUS_EXPORTER_ENABLED: "false" - PROMETHEUS_EXPORTER_HOST: dawarich_app - PROMETHEUS_EXPORTER_PORT: 9394 - SELF_HOSTED: "true" - STORE_GEODATA: "true" + RAILS_ENV: ${RAILS_ENV:-development} + REDIS_URL: ${REDIS_URL:-redis://dawarich_redis:6379} + DATABASE_HOST: ${DATABASE_HOST:-dawarich_db} + DATABASE_PORT: ${DATABASE_PORT:-5432} + DATABASE_USERNAME: ${DATABASE_USERNAME:-postgres} + DATABASE_PASSWORD: ${DATABASE_PASSWORD:-password} + DATABASE_NAME: ${DATABASE_NAME:-dawarich_development} + APPLICATION_HOSTS: ${APPLICATION_HOSTS:-localhost,::1,127.0.0.1} + BACKGROUND_PROCESSING_CONCURRENCY: ${BACKGROUND_PROCESSING_CONCURRENCY:-10} + APPLICATION_PROTOCOL: ${APPLICATION_PROTOCOL:-http} + PROMETHEUS_EXPORTER_ENABLED: ${PROMETHEUS_EXPORTER_ENABLED:-"false"} + PROMETHEUS_EXPORTER_HOST: ${PROMETHEUS_EXPORTER_HOST_SIDEKIQ:-dawarich_app} + PROMETHEUS_EXPORTER_PORT: ${PROMETHEUS_EXPORTER_PORT:-9394} + SECRET_KEY_BASE: ${SECRET_KEY_BASE:-} + RAILS_LOG_TO_STDOUT: ${RAILS_LOG_TO_STDOUT:-"true"} + SELF_HOSTED: ${SELF_HOSTED:-"true"} + STORE_GEODATA: ${STORE_GEODATA:-"true"} logging: driver: "json-file" options: - max-size: "100m" - max-file: "5" + max-size: ${LOG_MAX_SIZE:-100m} + max-file: ${LOG_MAX_FILE:-5} healthcheck: test: [ "CMD-SHELL", "pgrep -f sidekiq" ] interval: 10s