Subscription Tracker backend (Laravel) Docker image for the API server.
846
This Docker image delivers the production-ready backend API for the Subscription Tracker application, built with Laravel 11. The backend provides a secure, high-performance RESTful API for managing and tracking user subscriptions. Core features include JWT-based authentication, secure user registration and email verification, full CRUD for subscriptions, and automated email notifications for expiring or reminder-set subscriptions. This image is designed for deployment as part of a multi-container stack, always paired with the official Subscription Tracker frontend Docker image.
Important:
The Subscription Tracker backend container must be used together with the official frontend container and is designed to work as part of a five-service stack:
- Backend API (this image)
- Frontend
- Nginx
- MySQL database
- Redis
For a full, production-ready setup and seamless experience, it is strongly recommended to use the provided
docker-compose.production.yml,.env, andnginx/nginx.conffiles. These are available in the main GitHub repository root directory.
Download the required files from the GitHub repo:
.env.example → Rename to .env and update with your own values/secrets.docker-compose.production.ymlnginx/nginx.conf (must be placed in an nginx directory next to your compose file)Customize your .env file:
Below is the full list of environment variables needed for all components.
Copy and adjust as needed:
# MySQL
DB_HOST=subs-tracker-database
DB_PORT=3306
DB_USERNAME=root
MYSQL_DATABASE=subscription_tracker
MYSQL_ROOT_PASSWORD=your_db_root_password_here
# Redis
REDIS_HOST=subs-tracker-redis
REDIS_PORT=6379
REDIS_PASSWORD=redis_password_here
# Backend
APP_KEY=your_app_key_here
APP_ENV=production
APP_DEBUG=false
FRONT_END_URL=your_public_frontend_url_here
FRONTEND_SECRET=your_frontend_secret_here
MAIL_HOST=your_mail_host_here
MAIL_PORT=port_here
MAIL_USERNAME=your_mail_username_here
MAIL_PASSWORD=your_mail_password_here
MAIL_ENCRYPTION=tls
MAIL_FROM_ADDRESS=mail_from_address_here
JWT_SECRET=your_jwt_secret_here
# Frontend
NODE_ENV=production
COOKIE_SECURE=false
BACKEND_URL=http://subs-tracker-nginx:8000/api
SERVER_SECRET=${FRONTEND_SECRET}
NEXT_PUBLIC_APP_URL=${FRONT_END_URL}
IP_LOOKUP=https://api.ipify.org?format=json
| Variable | Description | Example Value |
|---|---|---|
| DB_HOST | Hostname for MySQL database (Docker service name) | subs-tracker-database |
| DB_PORT | MySQL port | 3306 |
| DB_USERNAME | MySQL username | root |
| MYSQL_DATABASE | MySQL database name | subscription_tracker |
| MYSQL_ROOT_PASSWORD | MySQL root password | your_db_root_password_here |
| REDIS_HOST | Redis hostname (Docker service name) | subs-tracker-redis |
| REDIS_PORT | Redis port | 6379 |
| REDIS_PASSWORD | Redis access password | redis_password_here |
| APP_KEY | Laravel app key (backend secret) | base64:... |
| APP_ENV | Laravel environment | production |
| APP_DEBUG | Laravel debug mode (should be false in production) | false |
| FRONT_END_URL | The public URL where the frontend is accessible | https://yourdomain.com or http://192.168.10.2 (your local IP for testing) |
| FRONTEND_SECRET | Shared secret for frontend-backend communication | zgGbB28m5Mn77U... (min 128 chars, avoid special chars: $,&,@,%) |
| MAIL_HOST | SMTP server host | smtp.mailtrap.io |
| MAIL_PORT | SMTP server port | 2525 |
| MAIL_USERNAME | SMTP username | 2ddfd45fda851 |
| MAIL_PASSWORD | SMTP password | o5sddsfddf54d9 |
| MAIL_ENCRYPTION | Mail encryption type | tls |
| MAIL_FROM_ADDRESS | Default sender email address | [email protected] |
| JWT_SECRET | Secret for backend JWT authentication | btM0rQ9vhL... |
| NODE_ENV | Node.js environment for frontend | production |
| COOKIE_SECURE | Should cookies be sent only over HTTPS? (true/false) | false (local), true (production) |
| BACKEND_URL | Internal URL for the backend API (through Nginx; change only if needed) | http://subs-tracker-nginx:8000/api |
| SERVER_SECRET | Frontend server secret (should match FRONTEND_SECRET) | ${FRONTEND_SECRET} |
| NEXT_PUBLIC_APP_URL | The public URL where the frontend is accessible (same as FRONT_END_URL) | ${FRONT_END_URL} |
| IP_LOOKUP | Public IP lookup endpoint (for IP-based features; no need to change) | https://api.ipify.org?format=json |
You can find the latest docker-compose.production.yml file here, but for convenience, the recommended configuration is shown below:
services:
subs-tracker-backend:
image: shahriar001/subscription-tracker-backend
container_name: subs-tracker-backend
restart: unless-stopped
volumes:
- backend_data:/var/www/storage
depends_on:
- subs-tracker-database
- subs-tracker-redis
networks:
- app-network
environment:
APP_KEY: "${APP_KEY}"
APP_ENV: "${APP_ENV}"
APP_DEBUG: "${APP_DEBUG}"
FRONT_END_URL: "${FRONT_END_URL}"
FRONTEND_SECRET: "${FRONTEND_SECRET}"
DB_HOST: "${DB_HOST}"
DB_PORT: "${DB_PORT}"
DB_DATABASE: "${MYSQL_DATABASE}"
DB_USERNAME: "${DB_USERNAME}"
DB_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
REDIS_HOST: "${REDIS_HOST}"
REDIS_PORT: "${REDIS_PORT}"
REDIS_PASSWORD: "${REDIS_PASSWORD}"
MAIL_HOST: "${MAIL_HOST}"
MAIL_PORT: "${MAIL_PORT}"
MAIL_USERNAME: "${MAIL_USERNAME}"
MAIL_PASSWORD: "${MAIL_PASSWORD}"
MAIL_ENCRYPTION: "${MAIL_ENCRYPTION}"
MAIL_FROM_ADDRESS: "${MAIL_FROM_ADDRESS}"
JWT_SECRET: "${JWT_SECRET}"
subs-tracker-nginx:
image: nginx:stable
container_name: subs-tracker-nginx
restart: unless-stopped
ports:
- "3000:3000"
volumes:
- ./nginx/nginx.conf:/etc/nginx/conf.d/custom.conf
depends_on:
- subs-tracker-backend
- subs-tracker-frontend
networks:
- app-network
subs-tracker-frontend:
image: shahriar001/subscription-tracker-frontend
container_name: subs-tracker-frontend
restart: unless-stopped
depends_on:
- subs-tracker-backend
networks:
- app-network
environment:
NODE_ENV: "${NODE_ENV}"
COOKIE_SECURE: "${COOKIE_SECURE}"
BACKEND_URL: "${BACKEND_URL}"
SERVER_SECRET: "${SERVER_SECRET}"
NEXT_PUBLIC_APP_URL: "${NEXT_PUBLIC_APP_URL}"
IP_LOOKUP: "${IP_LOOKUP}"
subs-tracker-database:
image: mysql:8.0.42
container_name: subs-tracker-database
restart: unless-stopped
volumes:
- db_data:/var/lib/mysql
environment:
MYSQL_DATABASE: "${MYSQL_DATABASE}"
MYSQL_ROOT_PASSWORD: "${MYSQL_ROOT_PASSWORD}"
ports:
- "127.0.0.1:3306:3306" # Bind to localhost for security
networks:
- app-network
subs-tracker-redis:
image: redis:8.0.2
container_name: subs-tracker-redis
restart: unless-stopped
volumes:
- redis_data:/data
command: ["redis-server", "--requirepass", "${REDIS_PASSWORD}", "--appendonly", "yes"]
networks:
- app-network
volumes:
backend_data:
db_data:
redis_data:
networks:
app-network:
driver: bridge
You must include the following Nginx config file as nginx/nginx.conf in your project root (same level as your compose file):
server {
listen 3000;
server_name frontend.local;
location / {
proxy_pass http://subs-tracker-frontend:3000;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
}
}
server {
listen 8000;
server_name backend.local;
root /var/www/public;
index index.php index.html index.htm;
location / {
try_files $uri $uri/ /index.php?$query_string;
}
location ~ \.php$ {
include fastcgi_params;
fastcgi_pass subs-tracker-backend:9000;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
location ~ /\.ht {
deny all;
}
}
Summary of Nginx Configuration:
server block listens on port 3000 inside the Docker network and proxies all frontend requests to the subs-tracker-frontend container (Next.js app).server block listens on port 8000 and serves the Laravel backend via FPM at port 9000 (subs-tracker-backend:9000).docker-compose.production.yml), so you can access the frontend via http://localhost/, and Nginx will route requests internally.Start the full stack:
In the directory containing your compose, .env, and nginx/nginx.conf files, run:
docker compose -f docker-compose.production.yml up -d
This will automatically pull all required images (backend, frontend, Nginx, MySQL, Redis) and launch the application with correct networking and environment variables.
Tip:
If you want to run the stack without downloading the compose file, you can use:curl -O https://raw.githubusercontent.com/Shahriar-Mahmud-Toha/SubscriptionTracker/master/docker-compose.production.yml mkdir -p nginx && curl -o nginx/nginx.conf https://raw.githubusercontent.com/Shahriar-Mahmud-Toha/SubscriptionTracker/master/nginx/nginx.conf curl -O https://raw.githubusercontent.com/Shahriar-Mahmud-Toha/SubscriptionTracker/master/.env.example && mv .env.example .env # Edit .env as needed, then: docker compose -f docker-compose.production.yml up -d
.env file as needed.app-network) to allow internal, secure communication.This project is licensed under the Creative Commons Attribution-NonCommercial 4.0 International License.
You are free to view, share, and adapt the code for non-commercial purposes with proper attribution.
Commercial use, redistribution, or republishing is not allowed without explicit permission from the author.
For permission requests, please contact via mdshahriar.me
or reach out on GitHub: Shahriar-Mahmud-Toha.
Content type
Image
Digest
sha256:5518b5b17…
Size
309.8 MB
Last updated
9 months ago
docker pull shahriar001/subscription-tracker-backend