Skip to content

Commit cce3bc6

Browse files
authored
Setup Localstack AWS S3 for local development (#125)
2 parents c8e27c4 + bea5129 commit cce3bc6

File tree

15 files changed

+405
-12
lines changed

15 files changed

+405
-12
lines changed

.env.example

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,19 @@
1+
RAILS_ENV=development
2+
DATABASE_USER=postgres
3+
DATABASE_PASSWORD=postgres
4+
DATABASE_NAME=skillrx_development
5+
DATABASE_PORT=5432
6+
DATABASE_HOST=db
7+
8+
LOCALSTACK_DEBUG=1
9+
S3_SKIP_SIGNATURE_VALIDATION=0
10+
11+
AWS_ACCESS_KEY_ID=test
12+
AWS_SECRET_ACCESS_KEY=test
13+
AWS_BUCKET_NAME=skillrx-development
14+
AWS_DEFAULT_REGION=us-east-1
15+
AWS_ENDPOINT_URL=http://localstack:4566
16+
117
AZURE_STORAGE_ACCOUNT_NAME=skillrx
218
AZURE_STORAGE_ACCOUNT_KEY=skillrx
319
AZURE_STORAGE_SHARE_NAME=skillrx

.localstack/config.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"services": {
3+
"s3": {
4+
"buckets": [
5+
{
6+
"name": "dev-bucket"
7+
}
8+
]
9+
}
10+
}
11+
}

.tool-versions

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
ruby 3.4.1

Dockerfile.dev

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
# Use Ruby 3.x with Alpine as base image for smaller size
2+
FROM ruby:3.4.1-alpine
3+
4+
# Set environment variables for Rails
5+
ENV RAILS_ENV=development \
6+
RACK_ENV=development \
7+
BUNDLE_PATH=/usr/local/bundle \
8+
BUNDLE_JOBS=4 \
9+
BUNDLE_RETRY=3
10+
11+
# Install system dependencies and development tools
12+
RUN apk add --no-cache \
13+
build-base \
14+
postgresql-dev \
15+
git \
16+
tzdata \
17+
bash \
18+
nss \
19+
freetype \
20+
freetype-dev \
21+
harfbuzz \
22+
ca-certificates \
23+
ttf-freefont \
24+
chromium \
25+
chromium-chromedriver
26+
27+
# Set Chrome environment variables
28+
ENV CHROME_BIN=/usr/bin/chromium-browser \
29+
CHROME_PATH=/usr/lib/chromium/
30+
31+
# Create and set working directory
32+
WORKDIR /app
33+
34+
# Install Ruby dependencies
35+
COPY Gemfile Gemfile.lock ./
36+
RUN bundle install
37+
38+
# Add bind mount point for code
39+
VOLUME /app
40+
41+
# Port used by Rails server
42+
EXPOSE 3000
43+
44+
# Configure entrypoint to run Rails
45+
ENTRYPOINT ["./bin/docker-entrypoint.dev"]
46+
47+
# Start Rails server by default
48+
CMD ["bundle", "exec", "rails", "server", "-b", "0.0.0.0"]

Gemfile

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -49,9 +49,8 @@ gem "thruster", require: false
4949
# Use Active Storage variants [https://guides.rubyonrails.org/active_storage_overview.html#transforming-images]
5050
gem "image_processing", "~> 1.14"
5151

52-
# Add tagging functionality
5352
gem "acts-as-taggable-on"
54-
53+
gem "aws-sdk-s3", require: false
5554
gem "requestjs-rails"
5655

5756
group :development, :test do

Gemfile.lock

Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,6 +95,24 @@ GEM
9595
public_suffix (>= 2.0.2, < 7.0)
9696
annotaterb (4.14.0)
9797
ast (2.4.3)
98+
aws-eventstream (1.4.0)
99+
aws-partitions (1.1110.0)
100+
aws-sdk-core (3.225.0)
101+
aws-eventstream (~> 1, >= 1.3.0)
102+
aws-partitions (~> 1, >= 1.992.0)
103+
aws-sigv4 (~> 1.9)
104+
base64
105+
jmespath (~> 1, >= 1.6.1)
106+
logger
107+
aws-sdk-kms (1.102.0)
108+
aws-sdk-core (~> 3, >= 3.225.0)
109+
aws-sigv4 (~> 1.5)
110+
aws-sdk-s3 (1.189.0)
111+
aws-sdk-core (~> 3, >= 3.225.0)
112+
aws-sdk-kms (~> 1)
113+
aws-sigv4 (~> 1.5)
114+
aws-sigv4 (1.12.0)
115+
aws-eventstream (~> 1, >= 1.0.2)
98116
base64 (0.3.0)
99117
bcrypt (3.1.20)
100118
bcrypt_pbkdf (1.1.1)
@@ -188,6 +206,7 @@ GEM
188206
jbuilder (2.13.0)
189207
actionview (>= 5.0.0)
190208
activesupport (>= 5.0.0)
209+
jmespath (1.6.2)
191210
json (2.10.2)
192211
jwt (2.10.1)
193212
base64
@@ -473,6 +492,7 @@ DEPENDENCIES
473492
active_storage_validations
474493
acts-as-taggable-on
475494
annotaterb
495+
aws-sdk-s3
476496
azure_file_shares!
477497
bcrypt (~> 3.1.7)
478498
bootsnap

Makefile

Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
# Project configuration
2+
3+
# Docker uses the directory environment variable to set a prefix for the service's container names.
4+
# Doc: https://docs.docker.com/compose/how-tos/environment-variables/envvars/#compose_project_name
5+
PROJECT_NAME := sk
6+
7+
# Colors for terminal output (optional)
8+
BLUE := \033[34m
9+
RESET := \033[0m
10+
11+
# Commands configuration
12+
COMPOSE_CMD = COMPOSE_PROJECT_NAME=$(PROJECT_NAME) docker compose -f docker-compose.dev.yml
13+
DOCKER_TEST_CMD = $(COMPOSE_CMD) exec app bundle exec rspec --format documentation
14+
EXEC_CMD = $(COMPOSE_CMD) exec app
15+
16+
.PHONY: help build rebuild stop start restart logs shell console format test test_fast db_reset migrate clean clean_volumes
17+
18+
# Default target
19+
help:
20+
@echo "$(BLUE)Available commands:$(RESET)"
21+
@echo " make build - Build image containers"
22+
@echo " make rebuild - Clean, build, start containers and prepare database"
23+
@echo " make stop [service] - Stop all containers or a specific service"
24+
@echo " make start [service] - Start all containers or a specific service"
25+
@echo " make restart [service] - Restart all containers or a specific service"
26+
@echo " make logs [service] - View logs of all containers or a specific service"
27+
@echo " make shell - Open a bash shell in the app container"
28+
@echo " make console - Start Rails console"
29+
@echo " make format - Auto-format code with Rubocop"
30+
@echo " make test - Run all tests"
31+
@echo " make test_fast - Run all tests and stop on first failure"
32+
@echo " make migrate - Run database migrations"
33+
@echo " make db_reset - Reset and rebuild database"
34+
@echo " make clean - Remove all containers and volumes"
35+
@echo " make clean_volumes - Remove all volumes"
36+
37+
build:
38+
$(COMPOSE_CMD) build
39+
@echo "✅ Build complete!"
40+
41+
rebuild:
42+
@echo "🚀 Setting up..."
43+
make clean
44+
make build
45+
make start
46+
sleep 2
47+
$(EXEC_CMD) bundle exec rails db:reset
48+
@echo "✅ Setup complete!"
49+
50+
stop:
51+
$(COMPOSE_CMD) stop $(filter-out $@,$(MAKECMDGOALS))
52+
53+
start:
54+
$(COMPOSE_CMD) up -d $(filter-out $@,$(MAKECMDGOALS))
55+
56+
restart:
57+
$(COMPOSE_CMD) restart $(filter-out $@,$(MAKECMDGOALS))
58+
59+
logs:
60+
$(COMPOSE_CMD) logs -f $(filter-out $@,$(MAKECMDGOALS))
61+
62+
shell:
63+
$(EXEC_CMD) bash
64+
65+
console:
66+
$(EXEC_CMD) bundle exec rails console
67+
68+
format:
69+
$(EXEC_CMD) bundle exec rubocop --autocorrect-all
70+
71+
test:
72+
export RAILS_ENV=test $(DOCKER_TEST_CMD)
73+
74+
test_fast:
75+
$(DOCKER_TEST_CMD) --fail-fast
76+
77+
migrate:
78+
$(EXEC_CMD) bundle exec rails db:migrate
79+
80+
db_reset:
81+
$(EXEC_CMD) bundle exec rails db:drop db:create db:prepare
82+
83+
clean:
84+
$(COMPOSE_CMD) down -v
85+
86+
clean_volumes:
87+
docker volume rm -f $(PROJECT_NAME)_localstack_data $(PROJECT_NAME)_db_data
88+
89+
%:
90+
@:

README.md

Lines changed: 93 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ Clone the codebase
2121
git clone [email protected]:rubyforgood/skillrx.git
2222
```
2323

24-
Run the setup script to prepare DB and assets
24+
Run the setup script to prepare the DB and assets
2525
```sh
2626
bin/setup
2727
```
@@ -72,4 +72,95 @@ This project uses:
7272
* `shoulda-matchers` for expectations
7373
* `factory_bot` for making records
7474

75-
To run tests simply use `bin/rspec`. You can also you `bin/quality` to check for code style issues.
75+
To run tests, simply use `bin/rspec`. You can also use `bin/quality` to check for code style issues.
76+
77+
# Docker Development Environment
78+
79+
This project is containerised using Docker to ensure consistent development environments across the team.
80+
81+
## Prerequisites
82+
83+
- Docker Engine installed on your system
84+
- Docker Compose V2 or later
85+
86+
## Initial Setup
87+
88+
1. Copy the environment configuration file:
89+
```
90+
cp .env.example .env
91+
```
92+
93+
2. Configure the environment variables in `.env` as needed. These variables set up the containerised services. Update the `.env.example` file with any new or changed variables.
94+
95+
3. To view the uploaded files from http://localstack:4566 in your browser, add the following line to your `/etc/hosts` to resolve `localstack` to your host system:
96+
```
97+
127.0.0.1 localstack
98+
```
99+
100+
4. Build and start the containers:
101+
```
102+
docker compose up
103+
```
104+
105+
This will build the images and initialise the containers. You can exit and stop the containers using CTRL+C.
106+
107+
## Container Architecture
108+
The development environment consists of three containerised services:
109+
110+
* app : Rails application service
111+
* Handles the main application logic
112+
* Runs on Ruby on Rails
113+
* db : PostgreSQL database service
114+
* Persists application data
115+
* Runs independently from the application
116+
* localstack : AWS S3 emulator
117+
* Provides local S3-compatible storage
118+
* Enables development without actual AWS setup
119+
120+
## Development Workflow
121+
122+
We provide a Makefile to simplify common development tasks. Here are the most frequently used commands:
123+
```
124+
make build # Build image containers
125+
make start [service] # Start all containers or a specific service
126+
make stop [service] # Stop all containers or a specific service
127+
make shell # Open a bash shell in the app container
128+
make console # Start Rails console
129+
make test # Run all tests
130+
```
131+
132+
For a complete list of available commands:
133+
```bash
134+
make help
135+
```
136+
137+
## Common Tasks
138+
### Rebuilding the Environment
139+
To completely rebuild your development environment:
140+
141+
```bash
142+
make rebuild
143+
```
144+
This command will clean existing containers, rebuild images, and prepare the database.
145+
146+
### Viewing Logs
147+
To monitor service logs:
148+
```
149+
make logs # View all container logs
150+
make logs app # View only Rails application logs
151+
```
152+
153+
### Container Management
154+
Individual services can be managed using:
155+
```
156+
make start db # Start only the database container
157+
make stop app # Stop only the application container
158+
make restart db # Restart only the database container
159+
```
160+
161+
### Troubleshooting
162+
If you encounter issues:
163+
- Ensure all required ports are available on your system
164+
- Verify that your .env file contains all necessary variables
165+
- Try rebuilding the environment with make rebuild
166+
- Check container logs for specific error messages

bin/docker-entrypoint.dev

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#!/bin/bash -e
2+
3+
# Remove any existing server.pid file
4+
rm -f /app/tmp/pids/server.pid
5+
6+
# Install new gems if any
7+
bundle check || bundle install
8+
9+
# If running the rails server then create or migrate existing database
10+
./bin/rails db:prepare
11+
12+
# Execute the main command passed to docker run
13+
exec "$@"

config/database.yml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,10 @@
1515
default: &default
1616
adapter: postgresql
1717
encoding: unicode
18+
host: <%= ENV.fetch('DATABASE_HOST') { 'localhost' } %>
19+
user: <%= ENV.fetch('DATABASE_USERNAME') { 'postgres' } %>
20+
password: <%= ENV.fetch('DATABASE_PASSWORD') { 'postgres' } %>
21+
port: <%= ENV.fetch('DATABASE_PORT') { 5432 } %>
1822
# For details on connection pooling, see Rails configuration guide
1923
# https://guides.rubyonrails.org/configuring.html#database-pooling
2024
pool: <%= ENV.fetch("RAILS_MAX_THREADS") { 5 } %>

0 commit comments

Comments
 (0)