diff --git a/samples/rails/.devcontainer/Dockerfile b/samples/rails/.devcontainer/Dockerfile new file mode 100644 index 00000000..a7f39527 --- /dev/null +++ b/samples/rails/.devcontainer/Dockerfile @@ -0,0 +1,4 @@ +ARG RUBY_VERSION=3.3.4 +FROM ghcr.io/rails/devcontainer/images/ruby:$RUBY_VERSION + +RUN apt-get update && apt-get install -y postgresql-client libpq-dev diff --git a/samples/rails/.devcontainer/devcontainer.json b/samples/rails/.devcontainer/devcontainer.json new file mode 100644 index 00000000..7cc0d8d4 --- /dev/null +++ b/samples/rails/.devcontainer/devcontainer.json @@ -0,0 +1,22 @@ +{ + "build": { + "dockerfile": "Dockerfile", + "context": "." + }, + "features": { + "ghcr.io/defanglabs/devcontainer-feature/defang-cli:1.0.4": {}, + "ghcr.io/devcontainers/features/docker-in-docker:2": {} + }, + "runArgs": [ + "--env-file", ".env" + ], + "appPort": 3000, + "forwardPorts": [], + "customizations": { + "vscode": { + "settings": { + "remote.autoForwardPorts": false + } + } + } +} diff --git a/samples/rails/.env b/samples/rails/.env new file mode 100644 index 00000000..f85288e6 --- /dev/null +++ b/samples/rails/.env @@ -0,0 +1,3 @@ +SECRET_KEY_BASE=example +POSTGRES_USERNAME=postgres +POSTGRES_HOST=db diff --git a/samples/rails/.github/workflows/deploy.yaml b/samples/rails/.github/workflows/deploy.yaml index 03ea61cd..0b76cb80 100644 --- a/samples/rails/.github/workflows/deploy.yaml +++ b/samples/rails/.github/workflows/deploy.yaml @@ -17,4 +17,8 @@ jobs: uses: actions/checkout@v4 - name: Deploy - uses: DefangLabs/defang-github-action@v1.1.0 \ No newline at end of file + uses: DefangLabs/defang-github-action@v1.1.0 + with: + config-env-vars: POSTGRES_PASSWORD + env: + POSTGRES_PASSWORD: ${{ secrets.POSTGRES_PASSWORD }} diff --git a/samples/rails/README.md b/samples/rails/README.md index 16f0b5c3..b44ef8cd 100644 --- a/samples/rails/README.md +++ b/samples/rails/README.md @@ -4,27 +4,41 @@ This template is a member list project developed using Ruby on Rails, offering a starting point to help you quickly build your team management system. We have prepared all the essential files for deployment. By spending less than 10 minutes setting up the environment, as detailed in the prerequisites, and executing the commands in our step-by-step guide, your website will be ready to go live to the world! -## NOTE - -This sample showcases how you could deploy a full-stack application with Defang in Ruby on Rails. However, it uses a SQLite database, which isn't production-ready and will be reset with every deployment. For production use cases you should use a managed database like RDS, Aiven, or others. If you stick to Rail's default SQLite database, your stored data will be lost on every deployment, and in some other cases. In the future, Defang will help you provision and connect to managed databases. - ## Essential Setup Files 1. A [Dockerfile](https://docs.docker.com/develop/develop-images/dockerfile_best-practices/) to describe the basic image of your applications. 2. A [docker-compose file](https://docs.defang.io/docs/concepts/compose) to define and run multi-container Docker applications. 3. A [.dockerignore](https://docs.docker.com/build/building/context/#dockerignore-files) file to comply with the size limit (10MB). -## Prerequisite +## Development Using [Dev Containers](https://containers.dev/) + +1. Open the working directory with Visual Studio Code or any editor which supports Dev Containers. +2. Click on the bottom left corner of the window where you see "Reopen in Container". +3. Open up a shell in the VS Code terminal and run `docker compose -f compose.dev.yaml up`. + + +## Configuration + +For this sample, you will need to provide the following [configuration](https://docs.defang.io/docs/concepts/configuration). Note that if you are using the 1-click deploy option, you can set these values as secrets in your GitHub repository and the action will automatically deploy them for you. + +### `POSTGRES_PASSWORD` +This password will be used to initialize the PostgreSQL database and to connect to it. -1. Download [Defang CLI](https://github.com/DefangLabs/defang) -2. If you are using [Defang BYOC](https://docs.defang.io/docs/concepts/defang-byoc), make sure you have properly [authenticated your AWS account](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) -3. Plus, make sure that you have properly set your environment variables like `AWS_PROFILE`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, and `AWS_SECRET_ACCESS_KEY`. ## Deployment -1. Open the terminal and type `defang login` -2. Type `defang compose up` in the CLI -3. Now your application will be launched +> [!NOTE] +> Download [Defang CLI](https://github.com/DefangLabs/defang) + +### Defang Playground + +Deploy your application to the defang playground by opening up your terminal and typing `defang up`. + +### BYOC (AWS) + +If you want to deploy to your own cloud account, you can use Defang BYOC: + +1. [Authenticate your AWS account](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html), and that you have properly set your environment variables like `AWS_PROFILE`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, and `AWS_SECRET_ACCESS_KEY`. --- diff --git a/samples/rails/app/.ruby-version b/samples/rails/app/.ruby-version index 85588beb..6d5369b9 100644 --- a/samples/rails/app/.ruby-version +++ b/samples/rails/app/.ruby-version @@ -1 +1 @@ -ruby-3.0.0 +ruby-3.3.4 diff --git a/samples/rails/app/Dockerfile b/samples/rails/app/Dockerfile index 92ade196..182bd516 100644 --- a/samples/rails/app/Dockerfile +++ b/samples/rails/app/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.3.0 +ARG RUBY_VERSION=3.3.4 FROM ruby:$RUBY_VERSION-slim as base # Rails app lives here @@ -18,7 +18,7 @@ FROM base as build # Install packages needed to build gems RUN apt-get update -qq && \ - apt-get install --no-install-recommends -y build-essential git libvips pkg-config + apt-get install --no-install-recommends -y build-essential git libvips pkg-config libpq-dev # Set bundler config to force ruby platform RUN bundle config set force_ruby_platform true @@ -44,7 +44,7 @@ FROM base # Install packages needed for deployment RUN apt-get update -qq && \ - apt-get install --no-install-recommends -y curl libsqlite3-0 libvips && \ + apt-get install --no-install-recommends -y curl libvips libpq-dev && \ rm -rf /var/lib/apt/lists /var/cache/apt/archives # Copy built artifacts: gems, application diff --git a/samples/rails/app/Dockerfile.dev b/samples/rails/app/Dockerfile.dev new file mode 100644 index 00000000..8a9759e8 --- /dev/null +++ b/samples/rails/app/Dockerfile.dev @@ -0,0 +1,36 @@ +# Make sure RUBY_VERSION matches the Ruby version in .ruby-version and Gemfile +ARG RUBY_VERSION=3.3.4 +FROM ruby:$RUBY_VERSION-slim + +# Rails app lives here +WORKDIR /rails + +# Set development environment +ENV RAILS_ENV="development" \ + BUNDLE_PATH="/usr/local/bundle" \ + PORT=3000 + +# Install packages needed to build gems +RUN apt-get update -qq && \ + apt-get install --no-install-recommends -y build-essential git libvips pkg-config libpq-dev postgresql-client + +# Set bundler config to force ruby platform +RUN bundle config set force_ruby_platform true + +# Install application gems +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 + +# Copy application code +COPY . . + +RUN ls /rails + +# Entrypoint prepares the database. +ENTRYPOINT ["/rails/bin/docker-entrypoint"] + +# Start the server by default, this can be overwritten at runtime +EXPOSE 3000 +CMD ["./bin/rails", "server", "-b", "0.0.0.0"] diff --git a/samples/rails/app/Gemfile b/samples/rails/app/Gemfile index 5a1c90aa..bfc667e5 100644 --- a/samples/rails/app/Gemfile +++ b/samples/rails/app/Gemfile @@ -1,6 +1,6 @@ source "https://rubygems.org" -ruby "3.3.0" +ruby "3.3.4" # Bundle edge Rails instead: gem "rails", github: "rails/rails", branch: "main" gem "rails", "~> 7.1.3", ">= 7.1.3.2" @@ -8,8 +8,8 @@ gem "rails", "~> 7.1.3", ">= 7.1.3.2" # The original asset pipeline for Rails [https://github.com/rails/sprockets-rails] gem "sprockets-rails" -# Use sqlite3 as the database for Active Record -gem "sqlite3", "~> 1.4" +# Use postgres as the database for Active Record +gem "pg", "~> 1.5" # Use the Puma web server [https://github.com/puma/puma] gem "puma", ">= 5.0" @@ -49,6 +49,7 @@ gem 'devise', '~> 4.9', '>= 4.9.4' group :development, :test do # See https://guides.rubyonrails.org/debugging_rails_applications.html#debugging-with-the-debug-gem gem "debug", platforms: %i[ mri mswin mswin64 mingw x64_mingw ] + gem "dotenv-rails", "~> 3.1" end group :development do diff --git a/samples/rails/app/Gemfile.lock b/samples/rails/app/Gemfile.lock index c4179d0a..18420c8e 100644 --- a/samples/rails/app/Gemfile.lock +++ b/samples/rails/app/Gemfile.lock @@ -106,6 +106,10 @@ GEM railties (>= 4.1.0) responders warden (~> 1.2.3) + dotenv (3.1.2) + dotenv-rails (3.1.2) + dotenv (= 3.1.2) + railties (>= 6.1) drb (2.2.1) erubi (1.12.0) globalid (1.2.1) @@ -152,6 +156,7 @@ GEM mini_portile2 (~> 2.8.2) racc (~> 1.4) orm_adapter (0.5.0) + pg (1.5.8) psych (5.1.2) stringio public_suffix (5.0.5) @@ -218,8 +223,6 @@ GEM actionpack (>= 5.2) activesupport (>= 5.2) sprockets (>= 3.0.0) - sqlite3 (1.7.3) - mini_portile2 (~> 2.8.0) stimulus-rails (1.3.3) railties (>= 6.0.0) stringio (3.1.0) @@ -255,20 +258,21 @@ DEPENDENCIES capybara debug devise (~> 4.9, >= 4.9.4) + dotenv-rails (~> 3.1) importmap-rails jbuilder + pg (~> 1.5) puma (>= 5.0) rails (~> 7.1.3, >= 7.1.3.2) selenium-webdriver sprockets-rails - sqlite3 (~> 1.4) stimulus-rails turbo-rails tzinfo-data web-console RUBY VERSION - ruby 3.3.0p0 + ruby 3.3.4p94 BUNDLED WITH 2.2.3 diff --git a/samples/rails/app/bin/docker-entrypoint b/samples/rails/app/bin/docker-entrypoint index 67ef4931..3cfa13b6 100755 --- a/samples/rails/app/bin/docker-entrypoint +++ b/samples/rails/app/bin/docker-entrypoint @@ -5,4 +5,6 @@ if [ "${1}" == "./bin/rails" ] && [ "${2}" == "server" ]; then ./bin/rails db:prepare fi +rm -f tmp/pids/server.pid + exec "${@}" diff --git a/samples/rails/app/config/database.yml b/samples/rails/app/config/database.yml index 796466ba..863b8431 100644 --- a/samples/rails/app/config/database.yml +++ b/samples/rails/app/config/database.yml @@ -1,25 +1,23 @@ -# SQLite. Versions 3.8.0 and up are supported. -# gem install sqlite3 -# -# Ensure the SQLite 3 gem is defined in your Gemfile -# gem "sqlite3" -# default: &default - adapter: sqlite3 + adapter: postgresql pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> + username: <%= ENV["POSTGRES_USERNAME"] %> + password: <%= ENV["POSTGRES_PASSWORD"] %> + host: <%= ENV["POSTGRES_HOST"] %> + port: 5432 timeout: 5000 development: <<: *default - database: storage/development.sqlite3 + database: rails_development # 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: <<: *default - database: storage/test.sqlite3 + database: rails_test production: <<: *default - database: storage/production.sqlite3 + database: rails_production diff --git a/samples/rails/app/db/schema.rb b/samples/rails/app/db/schema.rb index 0b9188e8..42981be4 100644 --- a/samples/rails/app/db/schema.rb +++ b/samples/rails/app/db/schema.rb @@ -11,6 +11,9 @@ # It's strongly recommended that you check this file into your version control system. ActiveRecord::Schema[7.1].define(version: 2024_04_18_210923) do + # These are extensions that must be enabled in order to support this database + enable_extension "plpgsql" + create_table "members", force: :cascade do |t| t.string "first_name" t.string "last_name" diff --git a/samples/rails/compose.dev.yaml b/samples/rails/compose.dev.yaml new file mode 100644 index 00000000..371e4317 --- /dev/null +++ b/samples/rails/compose.dev.yaml @@ -0,0 +1,25 @@ +services: + rails: + extends: + file: compose.yaml + service: rails + build: + context: ./app + dockerfile: Dockerfile.dev + env_file: + - .env + environment: + - POSTGRES_PASSWORD=secret + ports: + - "3000:3000" + volumes: + - ./app:/rails/ + + db: + extends: + file: compose.yaml + service: db + volumes: + - db-data:/var/lib/postgresql/data +volumes: + db-data: diff --git a/samples/rails/compose.yaml b/samples/rails/compose.yaml index 6b81dfb8..6452117f 100644 --- a/samples/rails/compose.yaml +++ b/samples/rails/compose.yaml @@ -1,15 +1,42 @@ services: rails: + # uncomment to add your own domain + # domainname: example.com restart: unless-stopped build: context: ./app dockerfile: Dockerfile + env_file: + - .env environment: - SECRET_KEY_BASE: example # set your own key here. + POSTGRES_PASSWORD: ports: - mode: ingress target: 3000 deploy: resources: reservations: - memory: 1GB \ No newline at end of file + memory: 1GB + healthcheck: + test: ["CMD", "curl", "-f", "http://localhost:3000"] + interval: 10s + timeout: 5s + retries: 5 + db: + restart: unless-stopped + image: postgres:16 + x-defang-postgres: true + environment: + POSTGRES_PASSWORD: + ports: + - mode: host + target: 5432 + healthcheck: + test: ["CMD-SHELL", "pg_isready -U postgres"] + interval: 10s + timeout: 5s + retries: 5 + deploy: + resources: + reservations: + memory: 1GB diff --git a/starter-sample/README.md b/starter-sample/README.md index 24df7e5c..e62054dd 100644 --- a/starter-sample/README.md +++ b/starter-sample/README.md @@ -6,7 +6,7 @@ This is a sample that shows the rough structure of an actual Defang sample. This ## Prerequisites -1. Download [Defang CLI](https://github.com/DefangLabs/defang) +1. [!NOTE] Download [Defang CLI](https://github.com/DefangLabs/defang) 2. (Optional) If you are using [Defang BYOC](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html) authenticated with your AWS account 3. (Optional for local development) [Docker CLI](https://docs.docker.com/engine/install/) @@ -27,13 +27,21 @@ For this sample, you will need to provide the following [configuration](https:// ### `API_KEY` #REMOVE_ME_AFTER_EDITING An explanation of what the env var (`API_KEY`) is, etc. +## Deployment -## Deploying +> [!NOTE] +> Download [Defang CLI](https://github.com/DefangLabs/defang) -1. Open the terminal and type `defang login` -2. Use the [`defang config`](https://docs.defang.io/docs/concepts/compose#configuration) command to setup environment variables. #REMOVE_ME_AFTER_EDITING -3. Type `defang compose up` in the CLI. -4. Your app will be running within a few minutes. +### Defang Playground + +Deploy your application to the defang playground by opening up your terminal and typing `defang up`. + +### BYOC (AWS) + +If you want to deploy to your own cloud account, you can use Defang BYOC: + +1. [Authenticate your AWS account](https://docs.aws.amazon.com/cli/latest/userguide/cli-chap-configure.html), and that you have properly set your environment variables like `AWS_PROFILE`, `AWS_REGION`, `AWS_ACCESS_KEY_ID`, and `AWS_SECRET_ACCESS_KEY`. +2. Run `defang up` in a terminal that has access to your AWS environment variables. ---