Skip to content

Commit

Permalink
🔨 Provide docker-compose.yml for local development
Browse files Browse the repository at this point in the history
  • Loading branch information
obecker committed Feb 19, 2024
1 parent c107cbb commit 7cbc3e2
Show file tree
Hide file tree
Showing 11 changed files with 93 additions and 37 deletions.
8 changes: 8 additions & 0 deletions .github/dependabot.yml
Original file line number Diff line number Diff line change
Expand Up @@ -32,3 +32,11 @@ updates:
- obecker
commit-message:
prefix: ":arrow_up: "
- package-ecosystem: docker
directory: scripts
schedule:
interval: weekly
assignees:
- obecker
commit-message:
prefix: ":arrow_up: "
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,9 @@ bin/
### temporary development resources ###
tmp/

### local dynamodb and s3 data
scripts/docker_data/

### environments
.env.*

Expand All @@ -49,3 +52,4 @@ terraform.tfstate.*
node_modules/
npm-debug.log*
coverage/
.eslintcache
26 changes: 15 additions & 11 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,17 +11,17 @@ Please be aware that the deployed service is presently not accessible to the pub
The [backend](backend) directory contains a Gradle project responsible for the backend service, which exposes a
REST API for the frontend. This service, implemented in Kotlin, utilizes [http4k](https://github.com/http4k/http4k)
for the API and [http4k-connect](https://github.com/http4k/http4k-connect)
for [DynamoDB](https://aws.amazon.com/dynamodb/) access.
for [DynamoDB](https://aws.amazon.com/dynamodb/) and [S3](https://aws.amazon.com/s3/) access.

To run the service locally, a local DynamoDB instance on `http://localhost:8000` is required.
You can achieve this by using tools like [NoSQL Workbench for DynamoDB](https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/workbench.html)
or by running a [DynamoDB docker image](https://hub.docker.com/r/amazon/dynamodb-local).
The scripts in [backend/scripts](backend/scripts) facilitate the creation of the two tables `Users` and `Cases` in
the local DynamoDB instance.
To run the service locally, local instances of DynamoDB and S3 are required.
There is a [docker compose](scripts/docker-compose.yml) file that starts a local DynamoDB and a [MinIO](https://min.io)
server (for S3).
The scripts [init-local-dynamodb.sh](scripts/init-local-dynamodb.sh) and [init-local-s3.sh](scripts/init-local-s3.sh)
facilitate the initial creation of the required local DynamoDB tables and the local S3 bucket.

Execute the command `gradle runShadow` to launch the application at `http://localhost:9000`.
Execute the command `gradle runShadow` to launch the application at `http://localhost:4000`.

Visit http://localhost:9000/api/ to access a Swagger UI providing documentation for the service's API.
Visit http://localhost:4000/api/ to access a Swagger UI providing documentation for the service's API.


## Frontend
Expand All @@ -32,7 +32,7 @@ with the backend service. This application is developed in JavaScript, employing

To initiate a server delivering the frontend, execute the command `npm run start`.
The frontend will be accessible at http://localhost:3000, while it will interact with the backend service at
`http://localhost:9000`.
`http://localhost:4000`.


## Infrastructure
Expand All @@ -46,6 +46,10 @@ for deploying the service on AWS. Before the first deployment you need to:

To execute an AWS deployment, follow these steps:

1. Run `gradle build` in the backend directory.
1. Run `gradle assemble` in the backend directory.
2. Run `npm run build` in the frontend directory.
3. Execute `./deploy.sh prod` or `./deploy.sh stage` in the infrastructure directory.
3. Execute `scripts/deploy.sh prod` or `scripts/deploy.sh stage`.

Note: Every AWS Lambda deployment creates a new function version, however
[terraform currently doesn't remove previous function versions](https://github.com/hashicorp/terraform-provider-aws/issues/17668).
To get rid of unused functions versions, execute the script [cleanup-lambda.sh](scripts/cleanup-lambda.sh).
2 changes: 1 addition & 1 deletion backend/src/main/kotlin/de/obqo/causalist/app/Main.kt
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ fun main() {
val response = api(Request(method = Method.POST, "/api/login").body("""{"username":"foo","password":""}"""))
check(response.status == Status.FORBIDDEN) { response }

api.asServer(SunHttp(9000)).start().also {
api.asServer(SunHttp(4000)).start().also {
println("Server started${env?.let { " with environment $env" }.orEmpty()}")
}.block()
}
Expand Down
17 changes: 8 additions & 9 deletions backend/src/main/resources/.env
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
# default (development) environment with localstack
# default (development) environment with local docker-compose.yml
AWS_REGION=eu-central-1
AWS_ACCESS_KEY_ID=dummy
AWS_SECRET_ACCESS_KEY=dummy
AWS_ACCESS_KEY_ID=dummyAccessKey
AWS_SECRET_ACCESS_KEY=dummyAccessSecret
CAUSALIST_ENCRYPTION_KEY=YeXHqscqShyHU9HRJUm/n2s3DN0ilLbTzhVTb9QeVV0\=
CAUSALIST_PASSWORD_SALT=salt
CAUSALIST_SIGNING_SECRET=secret
CAUSALIST_USERS_TABLE=Users
CAUSALIST_CASES_TABLE=Cases
CAUSALIST_CASE_DOCUMENTS_TABLE=CaseDocuments
# bucket name must contain a dot to force path-style requests to localstack
CAUSALIST_CASE_DOCUMENTS_BUCKET=case.documents
# DynamoDB on localstack
DYNAMODB_URI=http://localhost:4566
# S3 on localstack
S3_URI=http://localhost:4566
CAUSALIST_CASE_DOCUMENTS_BUCKET=case-documents
# DynamoDB in local docker
DYNAMODB_URI=http://localhost:8000
# S3 (MinIO) in local docker
S3_URI=http://localhost:9000
2 changes: 1 addition & 1 deletion frontend/vite.config.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ export default defineConfig(() => {
strictPort: true,
open: true,
proxy: {
'/api': 'http://localhost:9000',
'/api': 'http://localhost:4000',
},
},
define: {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
#!/usr/bin/env bash
# see https://github.com/karl-cardenas-coding/go-lambda-cleanup
# terraform doesn't delete old function versions automatically, see https://github.com/hashicorp/terraform-provider-aws/issues/17668
# this docker image will do the cleanup, see https://github.com/karl-cardenas-coding/go-lambda-cleanup
docker run -e AWS_ACCESS_KEY_ID="$(aws configure get aws_access_key_id)" -e AWS_SECRET_ACCESS_KEY="$(aws configure get aws_secret_access_key)" ghcr.io/karl-cardenas-coding/go-lambda-cleanup:2.0.12 clean -r "$(aws configure get region)"
15 changes: 10 additions & 5 deletions infrastructure/deploy.sh → scripts/deploy.sh
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
#!/usr/bin/env zsh

# Perform an AWS deployment using terraform

environment=$1
if [[ "$environment" != "prod" && "$environment" != "stage" ]]
then
Expand All @@ -8,15 +10,18 @@ then
exit 1
fi

terraformApply() {
chdir=$(dirname "$0")/../infrastructure
alias tf='terraform -chdir="$chdir"'

tfApply() {
setopt local_traps local_options
trap : INT
terraform apply --var-file="$1".tfvars
tf apply --var-file="$1".tfvars
}

workspace=$(terraform workspace show)

echo "Deploying $environment ..."
terraform workspace select "$environment"
terraformApply "$environment"
terraform workspace select "$workspace"
tf workspace select "$environment"
tfApply "$environment"
tf workspace select "$workspace"
26 changes: 26 additions & 0 deletions scripts/docker-compose.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
version: '3.8'

# run: docker compose up

services:

dynamodb:
image: amazon/dynamodb-local:2.2.1
command: "-jar DynamoDBLocal.jar -sharedDb -dbPath ./data"
ports:
- '8000:8000'
volumes:
- "./docker_data/dynamodb:/home/dynamodblocal/data"
working_dir: /home/dynamodblocal

minio:
image: quay.io/minio/minio:RELEASE.2024-02-17T01-15-57Z
command: server /data --console-address ":9001"
ports:
- '9000:9000'
- '9001:9001'
volumes:
- './docker_data/minio:/data'
environment:
- MINIO_ROOT_USER=dummyAccessKey
- MINIO_ROOT_PASSWORD=dummyAccessSecret
Original file line number Diff line number Diff line change
@@ -1,30 +1,27 @@
#!/usr/bin/env bash

# Initial creation of the required tables in a locally running DynamoDB

aws dynamodb create-table --table-name Users \
--attribute-definitions AttributeName=id,AttributeType=S AttributeName=username,AttributeType=S \
--key-schema AttributeName=id,KeyType=HASH \
--billing-mode PAY_PER_REQUEST \
--global-secondary-indexes "[{\"IndexName\":\"UsernameIndex\",\"KeySchema\":[{\"AttributeName\":\"username\",\"KeyType\":\"HASH\"}],\"Projection\":{\"ProjectionType\":\"ALL\"}}]" \
--output table \
--endpoint-url http://localhost:4566
--endpoint-url http://localhost:8000

aws dynamodb create-table --table-name Cases \
--attribute-definitions AttributeName=ownerId,AttributeType=S AttributeName=id,AttributeType=S AttributeName=ref,AttributeType=S AttributeName=settledOn,AttributeType=S \
--key-schema AttributeName=ownerId,KeyType=HASH AttributeName=id,KeyType=RANGE \
--billing-mode PAY_PER_REQUEST \
--local-secondary-indexes "[{\"IndexName\": \"ActiveIndex\", \"KeySchema\": [{\"AttributeName\": \"ownerId\", \"KeyType\": \"HASH\"}, {\"AttributeName\": \"ref\", \"KeyType\": \"RANGE\"}], \"Projection\": {\"ProjectionType\": \"ALL\"}}, {\"IndexName\": \"SettledIndex\", \"KeySchema\": [{\"AttributeName\": \"ownerId\", \"KeyType\": \"HASH\"}, {\"AttributeName\": \"settledOn\", \"KeyType\": \"RANGE\"}], \"Projection\": {\"ProjectionType\": \"ALL\"}}]" \
--output table \
--endpoint-url http://localhost:4566
--endpoint-url http://localhost:8000

aws dynamodb create-table --table-name CaseDocuments \
--attribute-definitions AttributeName=ownerId,AttributeType=S AttributeName=id,AttributeType=S AttributeName=ref,AttributeType=S \
--key-schema AttributeName=ownerId,KeyType=HASH AttributeName=id,KeyType=RANGE \
--billing-mode PAY_PER_REQUEST \
--local-secondary-indexes "[{\"IndexName\": \"ReferenceIndex\", \"KeySchema\": [{\"AttributeName\": \"ownerId\", \"KeyType\": \"HASH\"}, {\"AttributeName\": \"ref\", \"KeyType\": \"RANGE\"}], \"Projection\": {\"ProjectionType\": \"ALL\"}}]" \
--output table \
--endpoint-url http://localhost:4566

# bucket name must contain a dot to force path-style requests to localstack S3
aws s3api create-bucket --bucket case.documents \
--create-bucket-configuration LocationConstraint="$(aws configure get region)" \
--output table \
--endpoint-url http://localhost:4566
--endpoint-url http://localhost:8000
12 changes: 12 additions & 0 deletions scripts/init-local-s3.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
#!/usr/bin/env bash

# Initial creation of the required bucket in a locally running S3

# MinIO requires real access keys, see docker-compose.yml
export AWS_ACCESS_KEY_ID=dummyAccessKey
export AWS_SECRET_ACCESS_KEY=dummyAccessSecret

aws s3api create-bucket --bucket case-documents \
--create-bucket-configuration LocationConstraint="$(aws configure get region)" \
--output table \
--endpoint-url http://localhost:9000

0 comments on commit 7cbc3e2

Please sign in to comment.