This is a top-level Docker Compose environment for a Freegle development system. You should be able to start up a local development environment and make changes to each of the client/server components.
π¦ Installation
This top-level repository has a number of git submodules (see .gitmodules
in project root).
To clone this repository and all submodules:
git clone --recurse-submodules https://github.com/freegle/FreegleDocker
If you cloned without the --recurse-submodules
flag, you can initialize them with:
git submodule update --init --recursive
On Windows, using Docker Desktop works but is unusably slow. So we won't document that. Instead we use WSL2, with some jiggery-pokery to get round issues with file syncing and WSL2. Here are instructions on the assumption that you have a JetBrains IDE (e.g. PhpStorm):
- Install a WSL2 distribution (Ubuntu recommended). If you already have a WSL installation, you may benefit from installing a dedicated freegle one
wsl --install --name freegle
- Clone this repository from JetBrains and give it a WSL2 path (e.g.,
\\wsl$\Ubuntu\home\edward\FreegleDockerWSL
). - Install docker
- Use
wsl
to open a WSL2 terminal in the repository directory. - Start the docker service:
sudo service docker start
This will clone the required Freegle repositories:
iznik-nuxt3
(User website aka FD - runs as both dev and prod containers)iznik-nuxt3-modtools
(Moderator website aka ModTools)iznik-server
(legacy PHP API)iznik-server-go
(modern Go API)
Since these are git submodules, you can navigate into each subdirectory and work with them as independent git repositories - checking out different branches, making commits, etc.
Add these to your hosts file:
127.0.0.1 freegle.localhost
127.0.0.1 freegle-dev.localhost
127.0.0.1 freegle-prod.localhost
127.0.0.1 modtools.localhost
127.0.0.1 phpmyadmin.localhost
127.0.0.1 mailhog.localhost
127.0.0.1 tusd.localhost
127.0.0.1 status.localhost
127.0.0.1 apiv1.localhost
127.0.0.1 apiv2.localhost
127.0.0.1 delivery.localhost
(not sure if this is necessary)
Feel free to write this.
The system can be customized through environment variables in a .env
file. Copy .env.example
to .env
and modify as needed. The basic system will work without any configuration, but some features require API keys.
Branch Selection (Optional):
IZNIK_SERVER_BRANCH
- Branch for the PHP API server (default: master)IZNIK_SERVER_GO_BRANCH
- Branch for the Go API server (default: master)IZNIK_NUXT3_BRANCH
- Branch for the user website (default: master)IZNIK_NUXT3_MODTOOLS_BRANCH
- Branch for ModTools (default: master)
External Service API Keys (Optional but Recommended):
These keys enable full functionality and are used for both application features and PHPUnit testing:
GOOGLE_CLIENT_ID
- Google OAuth client ID for user authenticationGOOGLE_CLIENT_SECRET
- Google OAuth client secret for user authenticationGOOGLE_PUSH_KEY
- Google API key for push notificationsGOOGLE_VISION_KEY
- Google Vision API key for image analysisGOOGLE_PERSPECTIVE_KEY
- Google Perspective API key for content moderationGOOGLE_GEMINI_API_KEY
- Google Gemini API key for AI servicesGOOGLE_PROJECT
- Google Cloud project IDGOOGLE_APP_NAME
- Application name for Google services (usually "Freegle")MAPBOX_KEY
- Mapbox API key for map tiles and routingMAXMIND_ACCOUNT
- MaxMind account ID for GeoIP servicesMAXMIND_KEY
- MaxMind license key for GeoIP services
Example .env
file:
# Branch configuration (optional)
IZNIK_SERVER_BRANCH=better-phpunit
IZNIK_SERVER_GO_BRANCH=master
IZNIK_NUXT3_BRANCH=master
IZNIK_NUXT3_MODTOOLS_BRANCH=master
# API Keys (optional but recommended)
GOOGLE_CLIENT_ID=your_google_client_id_here.apps.googleusercontent.com
GOOGLE_CLIENT_SECRET=your_google_client_secret_here
GOOGLE_PUSH_KEY=your_google_push_key_here
GOOGLE_VISION_KEY=your_google_vision_api_key_here
GOOGLE_PERSPECTIVE_KEY=your_google_perspective_api_key_here
GOOGLE_GEMINI_API_KEY=your_google_gemini_api_key_here
GOOGLE_PROJECT=your_google_project_id_here
GOOGLE_APP_NAME=Freegle
MAPBOX_KEY=your_mapbox_api_key_here
MAXMIND_ACCOUNT=your_maxmind_account_here
MAXMIND_KEY=your_maxmind_key_here
After Configuration Changes:
If you modify branch settings or API keys, probably best to do a complete rebuild.
docker-compose build --no-cache
π Running
On Windows:
- Run
docker-compose up -d
from within the WSL2 environment to start the system. - File syncing to Docker containers happens automatically via the host-scripts container (this works around a inotifywait issue).
Monitor the startup progress at Status Monitor to see when all services are ready.
The system builds in stages:
- Infrastructure (databases, queues, reverse proxy) - ~2-3 minutes
- Development Tools (PhpMyAdmin, MailHog) - ~1 minute
- Freegle Components (websites, APIs) - ~10-15 minutes
Container Status Indicators:
- π’ Running - Service is ready
- π‘ Starting... - Service is building/starting up
- π΄ Offline - Service has failed
If the localhost domains above don't work, check that Windows hasn't blocked access: curl -I freegle.localhost
should give a 200 response.
If this is the case, you can open a proxy port: sudo netsh interface portproxy add v4tov4 listenport=80 listenaddress=0.0.0.0 connectport=80 connectaddress=<wsl IP address>
(see SO post for more info)
If you need to wipe everything and rebuild:
docker compose down
docker system prune -a # Warning: removes all unused Docker data
docker compose up -d
All containers use consistent freegle-*
naming:
# View logs
docker logs freegle-freegle-dev # Development Freegle site
docker logs freegle-freegle-prod # Production Freegle site
docker logs freegle-modtools # ModTools site
docker logs freegle-apiv1 # PHP API
docker logs freegle-apiv2 # Go API
docker logs freegle-status # Status monitor
docker logs freegle-delivery # Image delivery service
docker logs freegle-playwright # Test runner
# Execute commands in containers
docker exec -it freegle-freegle-dev bash
docker exec -it freegle-percona mysql -u root -piznik
# Restart specific services
docker restart freegle-modtools
docker restart freegle-status
Once all services show as Running in the status monitor, you can access:
-
Status Monitor - Real-time service health with CPU monitoring, visit buttons, and container management
- Restart Button - Available for all containers to quickly restart services
- Rebuild Button - Available for containers with build context (freegle, modtools, apiv1, apiv2, status) to rebuild and restart
- Playwright Test Runner - Run end-to-end tests with real-time progress tracking and HTML reports
β οΈ Development Tool Notice: The status monitor and test runner functionality was created by Claude Code and is intended for development use only. It is not production-quality code and should not be used in production environments.
- Freegle Dev - User site development version (Login:
[email protected]
/freegle
) - Freegle Prod - User site production build (Login:
[email protected]
/freegle
) - ModTools - Moderator site (Login:
[email protected]
/freegle
)
Note: It's normal for Freegle Dev and ModTools pages to reload a few times on first view -
this is expected Nuxt.js development mode behavior. The Freegle Prod container runs a production
build for testing production-like behavior. Also, nuxt dev
uses HTTP/1.1 which
serializes asset loading, making it slower than the live system which uses HTTP/2.
This means the page load can be quite slow until the browser has cached the code.
You can see this via 'Pending' calls in the Network tab.
- PhpMyAdmin - Database management (Login:
root
/iznik
) - MailHog - Email testing interface
- TusD - Image upload service
- Image Delivery - Image processing service (weserv/images)
- Traefik Dashboard - Reverse proxy dashboard
π§ͺ Test Configuration
The system contains one test group, FreeglePlayground, centered around Edinburgh.
The only recognised postcode is EH3 6SS.
π§ͺ Running Tests
We have the following tests, which can be run from the status page:
- PHPUnit tests for iznik-server (v1 API and background processing)
- Go tests for iznik-server-go (v2 API)
- Playwright end-to-end tests for the user-facing site only.
π CircleCI Continuous Integration
This repository includes CircleCI configuration that automatically monitors submodules and runs integration tests when changes are detected.
The system automatically:
- Monitors submodules every 6 hours for updates
- Updates submodules to latest commits on their default branches
- Runs full integration tests using the complete Docker Compose stack
- Commits successful updates back to the repository
- Responds to webhooks from submodule repositories for immediate testing
- Schedule: Every 6 hours (
0 */6 * * *
) - Branch: Only runs on
master
- Process:
- Updates all submodules to latest commits
- Starts complete Docker Compose environment (if changes detected)
- Waits for all services to be ready
- Runs Go API unit tests with coverage reporting
- Runs Playwright end-to-end tests via status container
- Collects test artifacts and logs
- Commits updates if tests pass
- Purpose: Immediate testing when submodule repositories push changes
- Trigger: API calls from submodule repository webhooks
- Behavior: Forces testing regardless of detected changes
- Process: Same as scheduled check but runs immediately on submodule changes
- Trigger: Push to
master
branch or manual pipeline trigger - Purpose: On-demand testing and validation
The following submodules are pre-configured with GitHub Actions workflows that automatically trigger CircleCI builds in this repository when changes are pushed:
- iznik-nuxt3 - User website repository
- iznik-nuxt3-modtools - ModTools repository
- iznik-server - Legacy PHP API repository
- iznik-server-go - Modern Go API repository
Each submodule contains .github/workflows/trigger-parent-ci.yml
that triggers the FreegleDocker CircleCI pipeline on push to master/main branches.
To activate webhook integration, add a CIRCLECI_TOKEN
secret to each submodule repository:
- Get CircleCI API Token from CircleCI β Personal API Tokens
- Add secret to each submodule: Settings β Secrets and Variables β Actions
- Secret name:
CIRCLECI_TOKEN
- Secret value: Your CircleCI API token
Once configured, any push to master/main in the submodules will automatically trigger integration testing in this repository.
- Build Artifacts: Docker logs, test reports, and debugging info automatically collected
- Timeout Protection: Builds timeout after appropriate intervals to prevent resource waste
- Resource Cleanup: Docker resources are always cleaned up after completion
- Smart Testing: Only runs tests when submodule changes are detected
For detailed setup instructions, see .circleci/README.md
.
β οΈ Limitations
- This doesn't run most of the various background jobs, so it won't be sending out emails in the way the live system would.
- We don't yet have a development container for ModTools - only production build is available.
- We're sharing the live tiles server - we've not added this to the Docker Compose setup yet.