├── .devcontainer ├── Dockerfile ├── devcontainer-lock.json ├── devcontainer.json ├── docker-compose.yml └── postCreate ├── .gitignore └── README.md /.devcontainer/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM mcr.microsoft.com/devcontainers/base:ubuntu-24.04 2 | 3 | ENV RAILS_DEVELOPMENT_HOSTS=".githubpreview.dev,.app.github.dev" 4 | 5 | # Installs postgresql-client-17 6 | RUN apt-get install curl ca-certificates git -y --no-install-recommends \ 7 | && sh -c 'echo "deb http://apt.postgresql.org/pub/repos/apt $(lsb_release -cs)-pgdg main" > /etc/apt/sources.list.d/pgdg.list' \ 8 | && curl -fsSL https://www.postgresql.org/media/keys/ACCC4CF8.asc | gpg --dearmor -o /etc/apt/trusted.gpg.d/postgresql.gpg 9 | 10 | RUN apt-get update \ 11 | && apt-get install postgresql-client-17 -y --no-install-recommends \ 12 | && apt-get clean \ 13 | && rm -rf /var/lib/apt/lists/* 14 | 15 | USER vscode 16 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer-lock.json: -------------------------------------------------------------------------------- 1 | { 2 | "features": { 3 | "ghcr.io/devcontainers-extra/features/zsh-plugins:0": { 4 | "version": "0.0.4", 5 | "resolved": "ghcr.io/devcontainers-extra/features/zsh-plugins@sha256:c8a1393b968f60d7ecf1199593fd9d88a0e0412229d21069700c4a3f52bd3722", 6 | "integrity": "sha256:c8a1393b968f60d7ecf1199593fd9d88a0e0412229d21069700c4a3f52bd3722" 7 | }, 8 | "ghcr.io/devcontainers/features/common-utils:2": { 9 | "version": "2.5.3", 10 | "resolved": "ghcr.io/devcontainers/features/common-utils@sha256:3cf7ca93154faf9bdb128f3009cf1d1a91750ec97cc52082cf5d4edef5451f85", 11 | "integrity": "sha256:3cf7ca93154faf9bdb128f3009cf1d1a91750ec97cc52082cf5d4edef5451f85" 12 | }, 13 | "ghcr.io/devcontainers/features/github-cli:1": { 14 | "version": "1.0.14", 15 | "resolved": "ghcr.io/devcontainers/features/github-cli@sha256:ca677566507c4118e4368cd76a4800807e911e5e350cc3525fb67ebc9132dfa1", 16 | "integrity": "sha256:ca677566507c4118e4368cd76a4800807e911e5e350cc3525fb67ebc9132dfa1" 17 | }, 18 | "ghcr.io/devcontainers/features/sshd:1": { 19 | "version": "1.0.10", 20 | "resolved": "ghcr.io/devcontainers/features/sshd@sha256:6e98e1977a3629e4372c41691602311b3455b682aa0e5abf29d6c33e1ee2e6e1", 21 | "integrity": "sha256:6e98e1977a3629e4372c41691602311b3455b682aa0e5abf29d6c33e1ee2e6e1" 22 | }, 23 | "ghcr.io/rocker-org/devcontainer-features/apt-packages:1": { 24 | "version": "1.0.2", 25 | "resolved": "ghcr.io/rocker-org/devcontainer-features/apt-packages@sha256:87a4d7750a596a5db034ba8508782f31aebdc2ffe955c66aaecb33d9de2ecdae", 26 | "integrity": "sha256:87a4d7750a596a5db034ba8508782f31aebdc2ffe955c66aaecb33d9de2ecdae" 27 | }, 28 | "ghcr.io/roul/devcontainer-features/mise-node:1": { 29 | "version": "1.0.3", 30 | "resolved": "ghcr.io/roul/devcontainer-features/mise-node@sha256:60470630f6acd1f775118c9bfe92580b0f289d7b339716421010f825d1e3518b", 31 | "integrity": "sha256:60470630f6acd1f775118c9bfe92580b0f289d7b339716421010f825d1e3518b", 32 | "dependsOn": [ 33 | "ghcr.io/roul/devcontainer-features/mise:latest" 34 | ] 35 | }, 36 | "ghcr.io/roul/devcontainer-features/mise-ruby:1": { 37 | "version": "1.0.2", 38 | "resolved": "ghcr.io/roul/devcontainer-features/mise-ruby@sha256:0bfa744260c880cf2905a30736b6870a6ea54bea300c372095f1d860ed83acf9", 39 | "integrity": "sha256:0bfa744260c880cf2905a30736b6870a6ea54bea300c372095f1d860ed83acf9", 40 | "dependsOn": [ 41 | "ghcr.io/roul/devcontainer-features/mise:latest" 42 | ] 43 | }, 44 | "ghcr.io/roul/devcontainer-features/mise:1": { 45 | "version": "1.0.6", 46 | "resolved": "ghcr.io/roul/devcontainer-features/mise@sha256:bcbd34b34176b6255d5aa5b881f1addc99bb3eed6049c841cb201f63fca132e4", 47 | "integrity": "sha256:bcbd34b34176b6255d5aa5b881f1addc99bb3eed6049c841cb201f63fca132e4" 48 | } 49 | } 50 | } 51 | -------------------------------------------------------------------------------- /.devcontainer/devcontainer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Devcontainer on Rails", 3 | "dockerComposeFile": "docker-compose.yml", 4 | "service": "app", // This is the name of the service in the `docker-compose.yml` file 5 | "workspaceFolder": "/workspaces/app", 6 | "features": { 7 | "ghcr.io/devcontainers/features/github-cli:1": {}, 8 | "ghcr.io/devcontainers/features/common-utils:2": { 9 | "username": "vscode", 10 | "userUid": 1001, 11 | "userGid": 1001, 12 | "installZsh": true, 13 | "installOhMyZsh": true, 14 | "configureZshAsDefaultShell": true, 15 | "upgradePackages": true 16 | }, 17 | "ghcr.io/rocker-org/devcontainer-features/apt-packages:1": { 18 | "packages": "libpq-dev, libvips" 19 | }, 20 | "ghcr.io/roul/devcontainer-features/mise:1": {}, 21 | "ghcr.io/roul/devcontainer-features/mise-ruby:1": { 22 | "version": "3.4.4" 23 | }, 24 | "ghcr.io/roul/devcontainer-features/mise-node:1": {}, 25 | "ghcr.io/devcontainers-extra/features/zsh-plugins:0": { 26 | "username": "vscode", 27 | "plugins": "bundler git rails ruby yarn" 28 | }, 29 | "ghcr.io/devcontainers/features/sshd:1": { 30 | "version": "latest" 31 | } 32 | }, 33 | // Configure tool-specific properties. 34 | "customizations": { 35 | "vscode": { 36 | "extensions": [ 37 | "Shopify.ruby-lsp", 38 | "EditorConfig.EditorConfig" 39 | ] 40 | }, 41 | "settings": { 42 | "terminal.integrated.defaultProfile.linux": "zsh" 43 | } 44 | }, 45 | // Use 'forwardPorts' to make a list of ports inside the container available locally. 46 | // This can be used to network with other containers or the host. 47 | "forwardPorts": [ 48 | 5433 49 | ], 50 | "postStartCommand": "git config --global --add safe.directory /workspaces/app", 51 | // Use 'postCreateCommand' to run commands after the container is created. 52 | "postCreateCommand": ".devcontainer/postCreate", 53 | "remoteUser": "vscode" 54 | } 55 | -------------------------------------------------------------------------------- /.devcontainer/docker-compose.yml: -------------------------------------------------------------------------------- 1 | services: 2 | app: 3 | container_name: app # This is the name of the container when you run `docker ps`, not the name of the service in the `devcontainer.json` file 4 | build: 5 | context: .. 6 | dockerfile: .devcontainer/Dockerfile 7 | volumes: 8 | - ../:/workspaces/app:cached 9 | command: sleep infinity 10 | postgres: 11 | image: postgres:17.5-alpine 12 | restart: unless-stopped 13 | volumes: 14 | - postgres-data:/var/lib/postgresql/data 15 | ports: 16 | - 5433:5432 17 | environment: 18 | POSTGRES_USER: postgres 19 | POSTGRES_DB: postgres 20 | POSTGRES_PASSWORD: postgres 21 | healthcheck: 22 | test: ["CMD", "pg_isready", "-U", "postgres", "-d", "postgres"] 23 | interval: 10s 24 | timeout: 5s 25 | retries: 5 26 | valkey: 27 | image: valkey/valkey:8.1-alpine 28 | restart: unless-stopped 29 | healthcheck: 30 | test: ["CMD", "valkey-cli", "ping"] 31 | interval: 10s 32 | timeout: 5s 33 | retries: 5 34 | ports: 35 | - 6379:6379 36 | volumes: 37 | - valkey-data:/data 38 | 39 | volumes: 40 | postgres-data: 41 | valkey-data: 42 | -------------------------------------------------------------------------------- /.devcontainer/postCreate: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | echo "Current user: $(whoami)" 4 | 5 | echo "Enable idiomatic version file..." 6 | mise settings add idiomatic_version_file_enable_tools ruby 7 | 8 | echo "Updating RubyGems..." 9 | gem update --system -N 10 | 11 | if [ -f "Gemfile" ]; then 12 | bundle install 13 | else 14 | echo "No Gemfile found, skipping dependencies installation." 15 | fi 16 | 17 | if [ -f "package.json" ]; then 18 | yarn install 19 | else 20 | echo "No package.json found, skipping JavaScript dependencies installation." 21 | fi 22 | 23 | echo "Copying database.yml..." 24 | cp --update=none config/database.yml.example config/database.yml 25 | 26 | if [ -f "bin/rails" ]; then 27 | bin/rails db:prepare 28 | else 29 | echo "bin/rails not found, skipping database preparation." 30 | fi 31 | 32 | echo "Done!" 33 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules/ 2 | yarn.lock 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Codespace on Rails 2 | 3 | ## Why? 4 | 5 | I've been trying to get some Ruby on Rails projects I have set up on Codespaces. After many tries, I've finally got it working (at least the way I wanted it to), so now I'm creating this repository to keep these changes and copy them to other projects whenever needed. 6 | 7 | I mostly copied what was done [here](https://github.com/microsoft/vscode-dev-containers/tree/main/containers/ruby-rails-postgres) and fixed some things that were not working for me or that I didn't need. 8 | 9 | ## How? 10 | 11 | 1. Copy the `.devcontainer` folder to your project 12 | 2. Customize the files to your needs 13 | 3. Open the project in Codespaces 14 | 15 | ## What's in the box? 16 | 17 | - Ruby 3.4.4 18 | - PostgreSQL 17 (exposed locally on port 5433) 19 | - Valkey 8 20 | - Node LTS 21 | - ZSH and Oh My Zsh 22 | - Mise version manager 23 | - Non root user 24 | 25 | ## Customizations 26 | 27 | There are a couple of things you _can_ customize and a couple of things you _should_ customize. 28 | 29 | ### Could 30 | 31 | You can choose different Ruby and Node versions by updating the `devcontainer.json` file. Currently, it will install Ruby 3.4.x and Node LTS You can also change the PostgreSQL username and password, although I don't think it matters too much. 32 | 33 | You can also change the project's name under `devcontainer.json` and `docker-compose.yml` if you want to. I've left it as `Your Project Name` for now. 34 | 35 | If you change the `service` name (defaults to `app` right now), remember to update the app section in docker-compose.yml. They have to match. 36 | 37 | ### Should 38 | 39 | You should, however, update your `database.yml` file if you use one. Here is what mine looks like: 40 | 41 | ```yaml 42 | default: &default 43 | adapter: postgresql 44 | encoding: unicode 45 | host: postgres # This is the name of the container in the docker-compose.yml file 46 | username: postgres # This is the default username for the postgres image 47 | password: postgres # This is the default password for the postgres image 48 | pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %> 49 | 50 | development: 51 | <<: *default 52 | database: app_development 53 | 54 | test: 55 | <<: *default 56 | database: app_test 57 | 58 | production: 59 | <<: *default 60 | url: <%= ENV["DATABASE_URL"] %> 61 | ``` 62 | 63 | Notice the `host: postgres`? That's the name of the container in the `docker-compose.yml` file. If you change it to `db`, you must update the `database.yml` file too. 64 | 65 | ## How do I SSH into the Codespace instance? 66 | 67 | This configuration includes an SSH server. To access your codespace instance, you should install the `gh` CLI and run `gh codespace ssh` and select your codespace. 68 | 69 | ## How do I attach to my container if I'm not using Codespaces? 70 | 71 | ```bash 72 | docker exec -it --user vscode app /bin/zsh 73 | ``` 74 | 75 | or 76 | 77 | ```bash 78 | devcontainer exec --workspace-folder . zsh 79 | ``` 80 | 81 | (or use DevContainer VSCode extension) 82 | 83 | ## Using devcontainer CLI 84 | 85 | Install with `npm install -g @devcontainers/cli` 86 | 87 | ### Setting it up 88 | ```bash 89 | devcontainer up --workspace-folder . 90 | ``` 91 | 92 | ### Checking for outdated dependencies 93 | 94 | ```bash 95 | devcontainer --workspace-folder . outdated 96 | ``` 97 | 98 | ### Upgrading your dependencies 99 | 100 | ```bash 101 | devcontainer upgrade --workspace-folder . 102 | ``` 103 | 104 | ### Removing everything 105 | 106 | ```bash 107 | docker stop $(docker ps -q) 108 | docker system prune -a --volumes --force 109 | ``` 110 | --------------------------------------------------------------------------------