19 finish docker integration for reitti (#20)

* feat: enable actuator health endpoint and add Docker healthcheck

* - added application-docker.properties
- update Dockerfile and corrosponding docker-compose.yml

* - removed init.sql

* docs: update environment variables in README and Docker Hub description

* docs: update environment variables section to table format

* - removed generated-requests.http
- updated application-docker.properties
This commit is contained in:
Daniel Graf
2025-06-04 21:53:34 +02:00
committed by GitHub
parent aa1fcd783b
commit 905bed840d
10 changed files with 109 additions and 176 deletions

View File

@@ -15,10 +15,12 @@ Reitti is a self-hosted application for tracking, analyzing, and visualizing you
```bash
docker pull reitti/reitti:latest
docker run -p 8080:8080 \
-e SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/reitti \
-e SPRING_DATASOURCE_USERNAME=postgres \
-e SPRING_DATASOURCE_PASSWORD=postgres \
-e SPRING_RABBITMQ_HOST=rabbitmq \
-e POSTGIS_HOST=postgres \
-e POSTGIS_PORT=5432 \
-e POSTGIS_DB=reittidb \
-e POSTGIS_USER=reitti \
-e POSTGIS_PASSWORD=reitti \
-e RABBITMQ_HOST=rabbitmq \
reitti/reitti:latest
```
@@ -26,16 +28,20 @@ For production use, we recommend using the provided docker-compose file that inc
## Environment Variables
- `SPRING_DATASOURCE_URL` - JDBC URL for PostgreSQL database
- `SPRING_DATASOURCE_USERNAME` - Database username
- `SPRING_DATASOURCE_PASSWORD` - Database password
- `SPRING_RABBITMQ_HOST` - RabbitMQ host
- `SPRING_RABBITMQ_PORT` - RabbitMQ port
- `SPRING_RABBITMQ_USERNAME` - RabbitMQ username
- `SPRING_RABBITMQ_PASSWORD` - RabbitMQ password
- `APP_UID` - User ID to run the application as (default: 1000)
- `APP_GID` - Group ID to run the application as (default: 1000)
- `JAVA_OPTS` - JVM options for the application
| Variable | Description | Default |
|----------|-------------|---------|
| `POSTGIS_HOST` | PostgreSQL database host | postgis |
| `POSTGIS_PORT` | PostgreSQL database port | 5432 |
| `POSTGIS_DB` | PostgreSQL database name | reittidb |
| `POSTGIS_USER` | Database username | reitti |
| `POSTGIS_PASSWORD` | Database password | reitti |
| `RABBITMQ_HOST` | RabbitMQ host | rabbitmq |
| `RABBITMQ_PORT` | RabbitMQ port | 5672 |
| `RABBITMQ_USER` | RabbitMQ username | reitti |
| `RABBITMQ_PASSWORD` | RabbitMQ password | reitti |
| `APP_UID` | User ID to run the application as | 1000 |
| `APP_GID` | Group ID to run the application as | 1000 |
| `JAVA_OPTS` | JVM options for the application | |
## Tags

View File

@@ -34,14 +34,18 @@ RUN echo '#!/bin/sh' > /entrypoint.sh && \
echo ' # Fix ownership of all files' >> /entrypoint.sh && \
echo ' chown -R reitti:reitti $APP_HOME' >> /entrypoint.sh && \
echo 'fi' >> /entrypoint.sh && \
echo 'exec su-exec reitti java $JAVA_OPTS -jar $APP_HOME/app.jar "$@"' >> /entrypoint.sh && \
echo 'exec su-exec reitti java $JAVA_OPTS -jar $APP_HOME/app.jar -Dspring.profiles.active=docker "$@"' >> /entrypoint.sh && \
chmod +x /entrypoint.sh
# Expose the application port
EXPOSE 8080
# Install su-exec for proper user switching
RUN apk add --no-cache su-exec
# Add healthcheck
HEALTHCHECK --interval=30s --timeout=3s --start-period=5s --retries=3 \
CMD wget --no-verbose --tries=1 --spider http://localhost:8080/actuator/health || exit 1
# Install su-exec for proper user switching and wget for healthcheck
RUN apk add --no-cache su-exec wget
# Run as root initially to allow UID/GID changes
USER root

View File

@@ -67,10 +67,12 @@ docker-compose up -d
# Or run standalone with environment variables
docker run -p 8080:8080 \
-e SPRING_DATASOURCE_URL=jdbc:postgresql://postgres:5432/reitti \
-e SPRING_DATASOURCE_USERNAME=postgres \
-e SPRING_DATASOURCE_PASSWORD=postgres \
-e SPRING_RABBITMQ_HOST=rabbitmq \
-e POSTGIS_HOST=postgres \
-e POSTGIS_PORT=5432 \
-e POSTGIS_DB=reittidb \
-e POSTGIS_USER=reitti \
-e POSTGIS_PASSWORD=reitti \
-e RABBITMQ_HOST=rabbitmq \
reitti/reitti:latest
```
@@ -78,13 +80,15 @@ docker run -p 8080:8080 \
| Variable | Description | Default |
|----------|-------------|---------|
| `SPRING_DATASOURCE_URL` | JDBC URL for PostgreSQL database | jdbc:postgresql://localhost:5432/reitti |
| `SPRING_DATASOURCE_USERNAME` | Database username | postgres |
| `SPRING_DATASOURCE_PASSWORD` | Database password | postgres |
| `SPRING_RABBITMQ_HOST` | RabbitMQ host | localhost |
| `SPRING_RABBITMQ_PORT` | RabbitMQ port | 5672 |
| `SPRING_RABBITMQ_USERNAME` | RabbitMQ username | guest |
| `SPRING_RABBITMQ_PASSWORD` | RabbitMQ password | guest |
| `POSTGIS_HOST` | PostgreSQL database host | postgis |
| `POSTGIS_PORT` | PostgreSQL database port | 5432 |
| `POSTGIS_DB` | PostgreSQL database name | reittidb |
| `POSTGIS_USER` | Database username | reitti |
| `POSTGIS_PASSWORD` | Database password | reitti |
| `RABBITMQ_HOST` | RabbitMQ host | rabbitmq |
| `RABBITMQ_PORT` | RabbitMQ port | 5672 |
| `RABBITMQ_USER` | RabbitMQ username | reitti |
| `RABBITMQ_PASSWORD` | RabbitMQ password | reitti |
| `SERVER_PORT` | Application server port | 8080 |
| `APP_UID` | User ID to run the application as | 1000 |
| `APP_GID` | Group ID to run the application as | 1000 |
@@ -95,15 +99,6 @@ docker run -p 8080:8080 \
- `latest` - Latest stable release
- `x.y.z` - Specific version releases
## API Endpoints
| Endpoint | Method | Description |
|----------|--------|-------------|
| `/api/v1/import/gpx` | POST | Import GPX data files |
| `/api/v1/queue-stats` | GET | Get processing queue statistics |
| `/settings/import/gpx` | POST | Web interface for GPX import |
| `/api/v1/timeline` | GET | Get timeline data |
## Data Flow
1. Location data is imported via API or web interface
@@ -119,7 +114,7 @@ docker run -p 8080:8080 \
- **Message Queue**: RabbitMQ for asynchronous processing
- **Frontend**: Thymeleaf, JavaScript
- **Testing**: JUnit 5, Testcontainers
- **Containerization**: Docker, Spring Boot Docker plugin
- **Containerization**: Docker
## Contributing

36
docker-compose-dev.yml Normal file
View File

@@ -0,0 +1,36 @@
services:
postgis:
image: postgis/postgis:17-3.5-alpine
environment:
POSTGRES_USER: reitti
POSTGRES_PASSWORD: reitti
POSTGRES_DB: reittidb
ports:
- "5432:5432"
volumes:
- postgis-data:/var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U reitti -d reittidb"]
interval: 10s
timeout: 5s
retries: 5
rabbitmq:
image: rabbitmq:3-management-alpine
ports:
- "5672:5672" # AMQP protocol port
- "15672:15672" # Management UI port
environment:
RABBITMQ_DEFAULT_USER: reitti
RABBITMQ_DEFAULT_PASS: reitti
volumes:
- rabbitmq-data:/var/lib/rabbitmq
healthcheck:
test: ["CMD", "rabbitmq-diagnostics", "check_port_connectivity"]
interval: 30s
timeout: 10s
retries: 5
volumes:
postgis-data:
redis-data:
rabbitmq-data:

View File

@@ -1,8 +1,16 @@
services:
# PostgreSQL with PostGIS and TimescaleDB extensions
reitti:
image: dedicatedcode/reitti:latest
ports:
- 8080:8080
depends_on:
rabbitmq:
condition: service_healthy
postgis:
condition: service_healthy
restart: true
postgis:
image: postgis/postgis:17-3.5-alpine
container_name: reitti-postgis
environment:
POSTGRES_USER: reitti
POSTGRES_PASSWORD: reitti
@@ -11,32 +19,13 @@ services:
- "5432:5432"
volumes:
- postgis-data:/var/lib/postgresql/data
- ./init-db:/docker-entrypoint-initdb.d
healthcheck:
test: ["CMD-SHELL", "pg_isready -U reitti -d reittidb"]
interval: 10s
timeout: 5s
retries: 5
# Redis for caching
redis:
image: redis:7-alpine
container_name: reitti-redis
ports:
- "6379:6379"
volumes:
- redis-data:/data
command: redis-server --appendonly yes
healthcheck:
test: ["CMD", "redis-cli", "ping"]
interval: 10s
timeout: 5s
retries: 5
# RabbitMQ for message queuing
rabbitmq:
image: rabbitmq:3-management-alpine
container_name: reitti-rabbitmq
ports:
- "5672:5672" # AMQP protocol port
- "15672:15672" # Management UI port
@@ -53,5 +42,4 @@ services:
volumes:
postgis-data:
redis-data:
rabbitmq-data:

View File

@@ -1,90 +0,0 @@
###
# @name Create new User Token
POST http://localhost:8080/api/v1/tokens
Content-Type: application/json
{
"name": "test-token",
"username": "daniel"
}
###
# @name Upload Whole Google Takeout Records.json
POST http://localhost:8080/api/v1/import/google-takeout
Content-Type: multipart/form-data; boundary=boundary
X-API-Token: d8a3e1ed-33ad-4e6c-b517-757b54d03833
--boundary
Content-Disposition: form-data; name="file"; filename="Records.json"
< /home/daniel/Downloads/takeout-20250422T152421Z-001/Takeout/Zeitachse/Records.json
###
# @name Upload Google Takeout Records.json
POST http://localhost:8080/api/v1/import/google-takeout
Content-Type: multipart/form-data; boundary=boundary
X-API-Token: d8a3e1ed-33ad-4e6c-b517-757b54d03833
--boundary
Content-Disposition: form-data; name="file"; filename="Records.json"
< src/test/resources/data/exports/google-takeout/Records-one-day.json
<> 2025-05-26T131205.202.json
<> 2025-05-26T130742.202.json
<> 2025-05-26T130708.202.json
<> 2025-05-26T130015.202.json
<> 2025-05-26T125856.202.json
<> 2025-05-26T123636.202.json
<> 2025-05-26T112900-2.202.json
<> 2025-05-26T112900-1.202.json
<> 2025-05-26T112900.202.json
<> 2025-05-26T112859-3.202.json
<> 2025-05-26T112859-2.202.json
<> 2025-05-26T112859-1.202.json
<> 2025-05-26T112859.202.json
<> 2025-05-26T112858-3.202.json
<> 2025-05-26T112858-2.202.json
<> 2025-05-26T112858-1.202.json
<> 2025-05-26T112858.202.json
<> 2025-05-26T112857-1.202.json
<> 2025-05-26T112857.202.json
<> 2025-05-26T112856-1.202.json
<> 2025-05-26T112856.202.json
<> 2025-05-26T112854.202.json
<> 2025-05-26T112841.202.json
<> 2025-05-26T112750.202.json
<> 2025-05-26T112750-1.202.json
<> 2025-05-26T112749-3.202.json
<> 2025-05-26T112749-2.202.json
<> 2025-05-26T112749-1.202.json
<> 2025-05-26T112749.202.json
<> 2025-05-26T112748-2.202.json
<> 2025-05-26T112748-1.202.json
<> 2025-05-26T112748.202.json
<> 2025-05-26T112747.202.json
<> 2025-05-26T112746-1.202.json
<> 2025-05-26T112746.202.json
<> 2025-05-26T112745-2.202.json
<> 2025-05-26T112745-1.202.json
<> 2025-05-26T112745.202.json
<> 2025-05-26T112744-4.202.json
<> 2025-05-26T112744-3.202.json
<> 2025-05-26T112744-2.202.json
<> 2025-05-26T112744-1.202.json
<> 2025-05-26T112744.202.json
<> 2025-05-26T112738.202.json
<> 2025-05-26T112657.202.json
<> 2025-05-26T112009.202.json
<> 2025-05-26T105346.200.json
<> 2025-05-26T105220.500.json
<> 2025-05-26T105116.400.json
<> 2025-05-26T105039.400.json
###
# @name Merge Trips
POST http://localhost:8080/api/v1/trips/merge/user/1

View File

@@ -1,9 +0,0 @@
-- Enable PostGIS extension
CREATE EXTENSION IF NOT EXISTS postgis;
-- Create schema
CREATE SCHEMA IF NOT EXISTS reitti;
-- Grant privileges
GRANT ALL PRIVILEGES ON DATABASE reittidb TO reitti;
ALTER USER reitti WITH SUPERUSER;

24
pom.xml
View File

@@ -126,6 +126,13 @@
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
@@ -146,21 +153,4 @@
</plugin>
</plugins>
</build>
<profiles>
<profile>
<id>docker</id>
<build>
<plugins>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<executable>true</executable>
</configuration>
</plugin>
</plugins>
</build>
</profile>
</profiles>
</project>

View File

@@ -27,6 +27,7 @@ public class SecurityConfig {
http
.authorizeHttpRequests(authorize -> authorize
.requestMatchers("/css/**", "/js/**", "/images/**").permitAll()
.requestMatchers("/actuator/health").permitAll()
.anyRequest().authenticated()
)
.addFilterBefore(bearerTokenAuthFilter, AuthorizationFilter.class)

View File

@@ -0,0 +1,12 @@
# PostgreSQL configuration (commented out for now, uncomment for production)
spring.datasource.url=jdbc:postgresql://${POSTGIS_HOST:postgis}:${POSTGIS_PORT:5432}/${POSTGIS_DB:reittidb}
spring.datasource.username=${POSTGIS_USER:reitti}
spring.datasource.password=${POSTGIS_PASSWORD:reitti}
spring.thymeleaf.cache=true
# RabbitMQ Configuration
spring.rabbitmq.host=${RABBITMQ_HOST:rabbitmq}
spring.rabbitmq.port=${RABBITMQ_PORT:5672}
spring.rabbitmq.username=${RABBITMQ_USER:reitti}
spring.rabbitmq.password=${RABBITMQ_PASSWORD:reitti}