From 567bd3ea255499552b8f33af94f42f50f7186e85 Mon Sep 17 00:00:00 2001 From: NoRePercussions Date: Mon, 3 Jun 2024 19:36:18 -0400 Subject: [PATCH 1/9] Minimum Working Dockerfile A mostly-functional Docker environment for tracker. Some things this doesn't include: * PDF generation (grover/puppeteer/chromium) * Production environment * Static asset serving documentation --- Dockerfile | 30 ++++++++++++++---------- README.md | 56 +++++++++++++++++++++++++++++++-------------- config/database.yml | 28 +++++++++++++---------- config/puma.rb | 2 +- 4 files changed, 74 insertions(+), 42 deletions(-) diff --git a/Dockerfile b/Dockerfile index ac32bef0..cd6ddafb 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,7 +1,7 @@ # syntax = docker/dockerfile:1 # Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile -ARG RUBY_VERSION=3.2.2 +ARG RUBY_VERSION=3.0.6 FROM registry.docker.com/library/ruby:$RUBY_VERSION-slim as base # Rails app lives here @@ -19,10 +19,14 @@ FROM base as build # Install packages needed to build gems and node modules RUN apt-get update -qq && \ - apt-get install --no-install-recommends -y build-essential curl git libpq-dev libvips node-gyp pkg-config python-is-python3 + apt-get install --no-install-recommends -y \ + build-essential \ + curl \ + libmariadb-dev `# Needed by ActiveRecord` \ + chromium # Needed by grover # Install JavaScript dependencies -ARG NODE_VERSION=18.18.2 +ARG NODE_VERSION=16.13.1 ARG YARN_VERSION=1.22.19 ENV PATH=/usr/local/node/bin:$PATH RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz -C /tmp/ && \ @@ -31,7 +35,7 @@ RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz rm -rf /tmp/node-build-master # Install application gems -COPY Gemfile Gemfile.lock ./ +COPY Gemfile Gemfile.lock .ruby-version ./ RUN bundle install && \ rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \ bundle exec bootsnap precompile --gemfile @@ -57,12 +61,8 @@ RUN bundle exec bootsnap precompile app/ lib/ # container. RUN /bin/bash -c 'if [[ "$RAILS_ENV" == "production" ]]; then \ - mv config/credentials.yml.enc config/credentials.yml.enc.backup && \ mv config/credentials/production.yml.enc config/credentials/production.yml.enc.backup && \ - mv config/credentials/sample.yml.enc config/credentials.yml.enc && \ - mv config/credentials/sample.key config/master.key && \ - SECRET_KEY_BASE_DUMMY=1 ./bin/rails assets:precompile && \ - mv config/credentials.yml.enc.backup config/credentials.yml.enc && \ + SECRET_KEY_BASE_DUMMY=1 RAILS_ENV=development ./bin/rails assets:precompile && \ mv config/credentials/production.yml.enc.backup config/credentials/production.yml.enc && \ rm -f config/master.key; \ fi' @@ -73,7 +73,12 @@ FROM base # Install packages needed for deployment RUN apt-get update -qq && \ - apt-get install --no-install-recommends -y curl libvips postgresql-client rsync && \ + apt-get install --no-install-recommends -y \ + curl \ + rsync `# Asset syncing` \ + libmariadb-dev `# activerecord` \ + nodejs `# js runtime` \ + chromium `# grover` && \ rm -rf /var/lib/apt/lists /var/cache/apt/archives # Copy built artifacts: gems, application @@ -88,12 +93,13 @@ USER rails:rails # https://serverfault.com/a/984599 USER root RUN mkdir -p /srv/public \ - && chown -R rails:rails /srv/public + && chown -R rails:rails /srv/public \ + && chmod +x -R /rails/bin USER rails:rails # Entrypoint prepares the database. ENTRYPOINT ["/rails/bin/docker-sync-assets-entrypoint"] # Start the server by default, this can be overwritten at runtime -EXPOSE 3000 +EXPOSE 80 CMD ["./bin/rails", "server"] diff --git a/README.md b/README.md index e91aaf29..c762bc94 100644 --- a/README.md +++ b/README.md @@ -16,27 +16,49 @@ You must install and configure a sendmail provider if you wish to send emails fr ## Development Setup -1. Clone the repo and checkout the intended branch. -2. Install MySQL. -3. Install rbenv and initialize it. -4. `rbenv install` -5. `gem install bundler` (ensure this runs in your rbenv environment) -6. `rbenv rehash` -7. `RAILS_ENV=development bundle install` -8. `rbenv rehash` -9. `EDITOR=nano ../rbenv/shims/bundle exec rails credentials:edit`. If you want to test out email or Slack integrations, then copy in the example at [config/credentials/credentials.example.yml](./config/credentials/credentials.example.yml) and update the values for your specific instance. -10. Install Node and Yarn (included in recent versions via corepack). -11. `yarn install` -12. `RAILS_ENV=development rails assets:precompile` -13. Create MySQL databases `abtt_development_master` and `abtt_test`. Use an existing user or create a new user and give it access to these databases. Update `config/database.yml` to match your local install for both the `development` and `test` environments. **Be sure not to commit this file with your specific environmental changes.** -14. `RAILS_ENV=development rails db:schema:load` -15. `RAILS_ENV=development rails db:seed` -16. Run the rails console to create an initial user: `RAILS_ENV=development rails c` +### Initial Setup + +1. Install Docker +1. Install MySQL +1. Create MySQL databases `abtt_development_master` and `abtt_test` +1. Create a MySQL user `abtt` with a password of your choice, and +give it access to those databases. + +### Making Changes + +1. Clone the repo and checkout the intended branch +1. Make changes +1. Build the Docker image: `docker build --tag "tracker" .` +1. Run the image: + ``` + docker run -d \ + -e RAILS_ENV=development \ + -e DATABASE_URL='mysql2://abtt:mypassword@host.docker.internal/abtt_development_master' \ + -p 3000:80 tracker + ``` +1. Now you can open tracker at `http://localhost:3000` + + +If this is your first run, do the following: + +1. Set a variable with the output of the run command: + `export CONTAINER=paste_output_here` +1. Load the DB schema: `docker exec $CONTAINER ./bin/rails db:schema:load` +1. Load the DB schema: `docker exec $CONTAINER ./bin/rails db:seed` +1. Enter Rails console: `docker exec -it $CONTAINER ./bin/rails c` +1. Create an initial user: ```ruby Member.create(namefirst: "Sam", namelast: "Abtek", email: "abtech@andrew.cmu.edu", phone: "5555555555", password: "password", password_confirmation: "password", payrate: 0.0, tracker_dev: true) exit ``` -17. Start the development server: `RAILS_ENV=development puma` + +### Configuration + +You may use the following environment variables when running the image: + +- `RAILS_ENV` - development, staging, production, etc. +- `DATABASE_URL` - e.g. `mysql2://abtt:password@host.docker.internal/abtt_development_master` + ## Deployment diff --git a/config/database.yml b/config/database.yml index 1808fdc6..b1c2dabe 100755 --- a/config/database.yml +++ b/config/database.yml @@ -8,28 +8,32 @@ # # And be sure to use new-style password hashing: # http://dev.mysql.com/doc/refman/5.0/en/old-client.html + development: adapter: mysql2 encoding: utf8mb4 - database: abtt_development_master - pool: 5 - username: deploy-abtech-tracker - password: - socket: /var/run/mysqld/mysqld.sock + # Use DATABASE_URL environment variable, see example.env file + # database: abtech_tracker_staging-01 + # pool: 5 + # username: root + # password: + # socket: /var/run/mysqld/mysqld.sock collation: utf8mb4_bin # Warning: The database defined as "test" will be erased and # re-generated from your development database when you run "rake". # Do not set this db to the same as development or production. + test: adapter: mysql2 - encoding: utf8 - database: abtt_test - pool: 5 - username: deploy-abtech-tracker - password: - socket: /var/run/mysqld/mysqld.sock - collation: utf8_unicode_ci + encoding: utf8mb4 + # Use DATABASE_URL environment variable, see example.env file + # database: abtech_tracker_staging-01 + # pool: 5 + # username: root + # password: + # socket: /var/run/mysqld/mysqld.sock + collation: utf8mb4_bin staging: adapter: mysql2 diff --git a/config/puma.rb b/config/puma.rb index d9b3e836..7fbcb096 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -15,7 +15,7 @@ # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # -port ENV.fetch("PORT") { 3000 } +bind "tcp://0.0.0.0:80" # Specifies the `environment` that Puma will run in. # From f64f494afb780cd8d8c612b44e4aa78972eb1c8a Mon Sep 17 00:00:00 2001 From: NoRePercussions Date: Tue, 4 Jun 2024 11:58:58 -0400 Subject: [PATCH 2/9] Fix Entrypoint Mode --- Dockerfile | 3 +-- bin/docker-entrypoint | 0 2 files changed, 1 insertion(+), 2 deletions(-) mode change 100644 => 100755 bin/docker-entrypoint diff --git a/Dockerfile b/Dockerfile index cd6ddafb..57d1aa2b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -93,8 +93,7 @@ USER rails:rails # https://serverfault.com/a/984599 USER root RUN mkdir -p /srv/public \ - && chown -R rails:rails /srv/public \ - && chmod +x -R /rails/bin + && chown -R rails:rails /srv/public USER rails:rails # Entrypoint prepares the database. diff --git a/bin/docker-entrypoint b/bin/docker-entrypoint old mode 100644 new mode 100755 From e9c80e03650ef872c550c6d2b63d19710be17e91 Mon Sep 17 00:00:00 2001 From: NoRePercussions Date: Tue, 4 Jun 2024 12:44:18 -0400 Subject: [PATCH 3/9] Add Asset Building Note --- Dockerfile | 1 + 1 file changed, 1 insertion(+) diff --git a/Dockerfile b/Dockerfile index 57d1aa2b..1bc5e7f2 100644 --- a/Dockerfile +++ b/Dockerfile @@ -60,6 +60,7 @@ RUN bundle exec bootsnap precompile app/ lib/ # into the container. We will inject RAILS_MASTER_KEY env var when starting the # container. +# TODO: resolve this in a way that does not require running in development mode. RUN /bin/bash -c 'if [[ "$RAILS_ENV" == "production" ]]; then \ mv config/credentials/production.yml.enc config/credentials/production.yml.enc.backup && \ SECRET_KEY_BASE_DUMMY=1 RAILS_ENV=development ./bin/rails assets:precompile && \ From fed499c86f1bc2bed458465f6e2fa14be7e0de68 Mon Sep 17 00:00:00 2001 From: NoRePercussions Date: Tue, 4 Jun 2024 12:57:53 -0400 Subject: [PATCH 4/9] Bind 0.0.0.0 Only In Container * Bind 0.0.0.0 only in container * Use port 3000 in container instead of 80 * Use default rails configuration --- Dockerfile | 2 +- README.md | 2 +- config/puma.rb | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index 1bc5e7f2..eae8ae22 100644 --- a/Dockerfile +++ b/Dockerfile @@ -102,4 +102,4 @@ ENTRYPOINT ["/rails/bin/docker-sync-assets-entrypoint"] # Start the server by default, this can be overwritten at runtime EXPOSE 80 -CMD ["./bin/rails", "server"] +CMD ["./bin/rails", "server", "-b", "0.0.0.0"] diff --git a/README.md b/README.md index c762bc94..417150d0 100644 --- a/README.md +++ b/README.md @@ -34,7 +34,7 @@ give it access to those databases. docker run -d \ -e RAILS_ENV=development \ -e DATABASE_URL='mysql2://abtt:mypassword@host.docker.internal/abtt_development_master' \ - -p 3000:80 tracker + -p 3000:3000 tracker ``` 1. Now you can open tracker at `http://localhost:3000` diff --git a/config/puma.rb b/config/puma.rb index 7fbcb096..d9b3e836 100644 --- a/config/puma.rb +++ b/config/puma.rb @@ -15,7 +15,7 @@ # Specifies the `port` that Puma will listen on to receive requests; default is 3000. # -bind "tcp://0.0.0.0:80" +port ENV.fetch("PORT") { 3000 } # Specifies the `environment` that Puma will run in. # From 5f1b9e1b1d414504916dc573d70877996401d39a Mon Sep 17 00:00:00 2001 From: NoRePercussions Date: Tue, 4 Jun 2024 13:03:40 -0400 Subject: [PATCH 5/9] Drop .ruby-version Bundler Check Keep it for rvm, but don't check that the ruby version is correct, so it isn't needed in the Docker image. --- Dockerfile | 2 +- Gemfile | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/Dockerfile b/Dockerfile index eae8ae22..18756570 100644 --- a/Dockerfile +++ b/Dockerfile @@ -35,7 +35,7 @@ RUN curl -sL https://github.com/nodenv/node-build/archive/master.tar.gz | tar xz rm -rf /tmp/node-build-master # Install application gems -COPY Gemfile Gemfile.lock .ruby-version ./ +COPY Gemfile Gemfile.lock ./ RUN bundle install && \ rm -rf ~/.bundle/ "${BUNDLE_PATH}"/ruby/*/cache "${BUNDLE_PATH}"/ruby/*/bundler/gems/*/.git && \ bundle exec bootsnap precompile --gemfile diff --git a/Gemfile b/Gemfile index d6bc6b0e..b148d871 100644 --- a/Gemfile +++ b/Gemfile @@ -1,7 +1,5 @@ source 'https://rubygems.org' -ruby File.read(".ruby-version").strip - # Bundle edge Rails instead: gem 'rails', github: 'rails/rails' gem 'rails', '~> 6.1.7.1' From 69e03235198f1544fb34fac970ab1ef1cdf7912f Mon Sep 17 00:00:00 2001 From: NoRePercussions Date: Tue, 4 Jun 2024 13:16:16 -0400 Subject: [PATCH 6/9] Lock to Amd64 for Puppeteer Puppeteer cannot provide its own headless chromium on amd64, and has compatability and versioning issues with installed chromium. Additionally, chromium has unwanted graphical packages. Therefore, we just lock everything to amd64. --- Dockerfile | 6 ++---- README.md | 2 +- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/Dockerfile b/Dockerfile index 18756570..d47b692e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -22,8 +22,7 @@ RUN apt-get update -qq && \ apt-get install --no-install-recommends -y \ build-essential \ curl \ - libmariadb-dev `# Needed by ActiveRecord` \ - chromium # Needed by grover + libmariadb-dev # Needed by ActiveRecord # Install JavaScript dependencies ARG NODE_VERSION=16.13.1 @@ -78,8 +77,7 @@ RUN apt-get update -qq && \ curl \ rsync `# Asset syncing` \ libmariadb-dev `# activerecord` \ - nodejs `# js runtime` \ - chromium `# grover` && \ + nodejs `# js runtime` && \ rm -rf /var/lib/apt/lists /var/cache/apt/archives # Copy built artifacts: gems, application diff --git a/README.md b/README.md index 417150d0..7655be0a 100644 --- a/README.md +++ b/README.md @@ -28,7 +28,7 @@ give it access to those databases. 1. Clone the repo and checkout the intended branch 1. Make changes -1. Build the Docker image: `docker build --tag "tracker" .` +1. Build the Docker image: `docker build --tag "tracker" --platform linux/amd64 .` 1. Run the image: ``` docker run -d \ From b491c0606dce84ea714c7150979e23d9f1ca2e18 Mon Sep 17 00:00:00 2001 From: NoRePercussions Date: Tue, 4 Jun 2024 13:25:05 -0400 Subject: [PATCH 7/9] Name Containers for Convenience Developers will need to create, run commands in, and stop containers constantly. Since only one development instance of tracker should run at a time due to port binding anyways, we recommend developers name their containers for convenient operations on them. --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 7655be0a..3a84e75a 100644 --- a/README.md +++ b/README.md @@ -29,23 +29,22 @@ give it access to those databases. 1. Clone the repo and checkout the intended branch 1. Make changes 1. Build the Docker image: `docker build --tag "tracker" --platform linux/amd64 .` +1. If you are already running tracker, remove it: `docker rm tracker` 1. Run the image: ``` docker run -d \ -e RAILS_ENV=development \ -e DATABASE_URL='mysql2://abtt:mypassword@host.docker.internal/abtt_development_master' \ - -p 3000:3000 tracker + -p 3000:3000 --platform linux/amd64 --name tracker tracker ``` 1. Now you can open tracker at `http://localhost:3000` If this is your first run, do the following: -1. Set a variable with the output of the run command: - `export CONTAINER=paste_output_here` -1. Load the DB schema: `docker exec $CONTAINER ./bin/rails db:schema:load` -1. Load the DB schema: `docker exec $CONTAINER ./bin/rails db:seed` -1. Enter Rails console: `docker exec -it $CONTAINER ./bin/rails c` +1. Load the DB schema: `docker exec tracker ./bin/rails db:schema:load` +1. Load the DB schema: `docker exec tracker ./bin/rails db:seed` +1. Enter Rails console: `docker exec -it tracker ./bin/rails c` 1. Create an initial user: ```ruby Member.create(namefirst: "Sam", namelast: "Abtek", email: "abtech@andrew.cmu.edu", phone: "5555555555", password: "password", password_confirmation: "password", payrate: 0.0, tracker_dev: true) From ba13afc2170dbf2aa2e40b7f03a4b64b924b6f1a Mon Sep 17 00:00:00 2001 From: Tucker Shea Date: Tue, 4 Jun 2024 13:28:19 -0400 Subject: [PATCH 8/9] Expose 3000 as Default Port Co-authored-by: Perry Naseck <4472083+DaAwesomeP@users.noreply.github.com> --- Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Dockerfile b/Dockerfile index d47b692e..fe67ae82 100644 --- a/Dockerfile +++ b/Dockerfile @@ -99,5 +99,5 @@ USER rails:rails ENTRYPOINT ["/rails/bin/docker-sync-assets-entrypoint"] # Start the server by default, this can be overwritten at runtime -EXPOSE 80 +EXPOSE 3000 CMD ["./bin/rails", "server", "-b", "0.0.0.0"] From 1a7e48f70586f2b7c3d6e11aed05fedc1bf63310 Mon Sep 17 00:00:00 2001 From: NoRePercussions Date: Tue, 4 Jun 2024 13:43:11 -0400 Subject: [PATCH 9/9] Include Templated Requirements --- Dockerfile | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Dockerfile b/Dockerfile index fe67ae82..56c7d276 100644 --- a/Dockerfile +++ b/Dockerfile @@ -20,6 +20,10 @@ FROM base as build # Install packages needed to build gems and node modules RUN apt-get update -qq && \ apt-get install --no-install-recommends -y \ + libpq-dev `# Part of generated dockerfile` \ + libvips `# Generated for ActiveRecord` \ + node-gyp `# Generated for Node` \ + pkg-config `# Generated for Node` \ build-essential \ curl \ libmariadb-dev # Needed by ActiveRecord @@ -74,6 +78,7 @@ FROM base # Install packages needed for deployment RUN apt-get update -qq && \ apt-get install --no-install-recommends -y \ + libvips `# Generated for ActiveRecord` \ curl \ rsync `# Asset syncing` \ libmariadb-dev `# activerecord` \