{"owner":"opf","repo":"openproject","hasDocker":true,"hasCompose":true,"hasDockerfile":false,"composePath":"docker-compose.yml","servicesCount":14,"services":[{"name":"backend","image":"openproject/dev:latest","build":{"context":".","dockerfile":"./docker/dev/backend/Dockerfile"},"restart":"unless-stopped","command":"run-app","ports":["${PORT:-3000}:3000"],"environment":["DATABASE_URL=postgresql://${DB_USERNAME:-postgres}:${DB_PASSWORD:-postgres}@${DB_HOST:-db}:${DB_PORT:-5432}/${DB_DATABASE:-openproject}?pool=100","LOCAL_DEV_CHECK=${LOCAL_DEV_CHECK:?The docker-compose file for OpenProject has moved to https://github.com/opf/openproject-docker-compose}","OPENPROJECT_CACHE__MEMCACHE__SERVER=cache:11211","OPENPROJECT_EDITION=${OPENPROJECT_EDITION:-standard}","OPENPROJECT_RAILS__CACHE__STORE=file_store","OPENPROJECT_RAILS__RELATIVE__URL__ROOT=${OPENPROJECT_RAILS__RELATIVE__URL__ROOT:-}","OPENPROJECT_SSRF_PROTECTION_IP_ALLOWLIST=0.0.0.0/0,::0/0","OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__URL=${OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__URL:-wss://hocuspocus.local}","OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__SECRET=${OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__SECRET:-secret12345}","OPENPROJECT_WEB_MAX__THREADS=1","OPENPROJECT_WEB_MIN__THREADS=1","OPENPROJECT_WEB_WORKERS=0","PIDFILE=/home/dev/openproject/tmpfs/pids/server.pid","RAILS_ENV=development"],"volumes":[".:/home/dev/openproject","opdata:/var/openproject/assets","bundle:/usr/local/bundle","tmp:/home/dev/openproject/tmp"],"depends_on":["db","cache","frontend","hocuspocus"]},{"name":"worker","image":"openproject/dev:latest","build":{"context":".","dockerfile":"./docker/dev/backend/Dockerfile"},"restart":"unless-stopped","command":"bundle exec good_job start","environment":["DATABASE_URL=postgresql://${DB_USERNAME:-postgres}:${DB_PASSWORD:-postgres}@${DB_HOST:-db}:${DB_PORT:-5432}/${DB_DATABASE:-openproject}?pool=100","LOCAL_DEV_CHECK=${LOCAL_DEV_CHECK:?The docker-compose file for OpenProject has moved to https://github.com/opf/openproject-docker-compose}","OPENPROJECT_CACHE__MEMCACHE__SERVER=cache:11211","OPENPROJECT_EDITION=${OPENPROJECT_EDITION:-standard}","OPENPROJECT_RAILS__CACHE__STORE=file_store","OPENPROJECT_RAILS__RELATIVE__URL__ROOT=${OPENPROJECT_RAILS__RELATIVE__URL__ROOT:-}","OPENPROJECT_SSRF_PROTECTION_IP_ALLOWLIST=0.0.0.0/0,::0/0","OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__URL=${OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__URL:-wss://hocuspocus.local}","OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__SECRET=${OPENPROJECT_COLLABORATIVE__EDITING__HOCUSPOCUS__SECRET:-secret12345}","OPENPROJECT_WEB_MAX__THREADS=1","OPENPROJECT_WEB_MIN__THREADS=1","OPENPROJECT_WEB_WORKERS=0","PIDFILE=/home/dev/openproject/tmpfs/pids/server.pid","RAILS_ENV=development"],"volumes":[".:/home/dev/openproject","opdata:/var/openproject/assets","bundle:/usr/local/bundle","tmp:/home/dev/openproject/tmp"],"depends_on":["db","cache"]},{"name":"frontend","build":{"context":".","dockerfile":"./docker/dev/frontend/Dockerfile"},"command":"node --max_old_space_size=8096 ./node_modules/@angular/cli/bin/ng serve --host 0.0.0.0","ports":["${FE_PORT:-4200}:4200"],"environment":["__VITE_ADDITIONAL_SERVER_ALLOWED_HOSTS=openproject-assets.${OPENPROJECT_DOCKER_DEV_TLD:-local}"],"volumes":[".:/home/dev/openproject","${CKEDITOR_BUILD_DIR:-./frontend/src/vendor/ckeditor/}:/home/dev/openproject/frontend/src/vendor/ckeditor/"]},{"name":"db","image":"postgres:17","restart":"unless-stopped","environment":["POSTGRES_USER=${DB_USERNAME:-postgres}","POSTGRES_PASSWORD=${DB_PASSWORD:-postgres}","POSTGRES_DB=${DB_DATABASE:-openproject}"],"volumes":["pgdata:/var/lib/postgresql/data"]},{"name":"hocuspocus","image":"node:24-alpine","restart":"unless-stopped","command":"sh -c \"npm run dev\"","environment":["SECRET=secret12345","NODE_TLS_REJECT_UNAUTHORIZED=0"],"volumes":["./extensions/op-blocknote-hocuspocus:/app"]},{"name":"cache","image":"memcached","restart":"unless-stopped"},{"name":"db-test","image":"postgres:17","environment":["POSTGRES_DB=openproject","POSTGRES_USER=openproject","POSTGRES_PASSWORD=openproject"],"volumes":["pgdata-test:/var/lib/postgresql/data"]},{"name":"hocuspocus-test","image":"node:24-alpine","restart":"unless-stopped","command":"sh -c \"npm run dev\"","environment":["SECRET=secret12345","NODE_TLS_REJECT_UNAUTHORIZED=0"],"volumes":["./extensions/op-blocknote-hocuspocus:/app"]},{"name":"frontend-test","build":{"context":".","dockerfile":"./docker/dev/frontend/Dockerfile"},"command":"npm run serve","environment":["PROXY_HOSTNAME=backend-test","CHROME_BIN=chromium","FE_PORT=4200","FE_HOST=frontend-test"],"volumes":[".:/home/dev/openproject","fedata-test:/home/dev/openproject/public/assets/frontend"]},{"name":"backend-test","build":{"context":".","dockerfile":"./docker/dev/backend/Dockerfile"},"command":"setup-tests","environment":["RAILS_ENV=test","OPENPROJECT_TESTING_WITH_DOCKER=true","OPENPROJECT_RAILS__RELATIVE__URL__ROOT=${OPENPROJECT_RAILS__RELATIVE__URL__ROOT:-}","DATABASE_URL=postgresql://openproject:openproject@db-test/openproject","DATABASE_CLEANER_ALLOW_REMOTE_DATABASE_URL=true","SELENIUM_GRID_URL=http://selenium-hub:4444/wd/hub","CHROME_WS_URL=ws://cuprite-chrome:3000/chrome","CAPYBARA_SERVER_PORT=3000","CAPYBARA_BIND_ADDRESS=0.0.0.0","CAPYBARA_APP_HOSTNAME=backend-test","OPENPROJECT_EMAIL__DELIVERY__METHOD=test","OPENPROJECT_CLI_PROXY=http://frontend-test:4200","OPENPROJECT_TESTING_NO_HEADLESS=true","OPENPROJECT_TESTING_AUTO_DEVTOOLS=true"],"volumes":[".:/home/dev/openproject","fedata-test:/home/dev/openproject/public/assets/frontend","opdata:/var/openproject/assets","bundle:/usr/local/bundle","tmp-test:/home/dev/openproject/tmp","./tmp/capybara:/home/dev/openproject/tmp/capybara"],"depends_on":["db-test","selenium-hub","frontend-test","cuprite-chrome","hocuspocus-test"]},{"name":"selenium-hub","image":"selenium/hub:4","environment":["GRID_MAX_SESSION=${CI_JOBS:-4}"],"depends_on":["chrome","firefox"]},{"name":"chrome","image":"selenium/node-chrome:4","environment":["SE_EVENT_BUS_HOST=selenium-hub","SE_EVENT_BUS_PUBLISH_PORT=4442","SE_EVENT_BUS_SUBSCRIBE_PORT=4443","SCREEN_WIDTH=1920","SCREEN_HEIGHT=1080","NODE_MAX_INSTANCES=${CI_JOBS:-4}","NODE_MAX_SESSION=${CI_JOBS:-4}"],"volumes":["/dev/shm:/dev/shm","downloads-test:/home/seluser/Downloads"]},{"name":"firefox","image":"selenium/node-firefox:4","environment":["SE_EVENT_BUS_HOST=selenium-hub","SE_EVENT_BUS_PUBLISH_PORT=4442","SE_EVENT_BUS_SUBSCRIBE_PORT=4443","SCREEN_WIDTH=1920","SCREEN_HEIGHT=1080","NODE_MAX_INSTANCES=${CI_JOBS:-4}","NODE_MAX_SESSION=${CI_JOBS:-4}"],"volumes":["/dev/shm:/dev/shm","downloads-test:/home/seluser/Downloads"]},{"name":"cuprite-chrome","image":"ghcr.io/browserless/chrome:latest","environment":["HOST=cuprite-chrome","CONNECTION_TIMEOUT=600000"]}],"exposedPorts":["3000","4200"],"dockerRunCommand":"docker run -d --name openproject -p 3000:3000 --restart always openproject/dev:latest","podmanRunCommand":"podman run -d --name openproject -p 3000:3000 --restart always openproject/dev:latest","skopeoInspectCommand":"skopeo inspect docker://docker.io/openproject/dev:latest","orasPullCommand":"oras pull openproject/dev:latest","registryMeta":{"provider":"dockerhub","image":"openproject/dev","canonicalImage":"docker.io/openproject/dev:latest","latestTag":"latest","cliCommands":{"dockerRun":"docker run -d --name openproject -p 3000:3000 --restart always openproject/dev:latest","dockerPull":"docker pull openproject/dev:latest","podmanRun":"podman run -d --name openproject -p 3000:3000 --restart always openproject/dev:latest","skopeoInspect":"skopeo inspect docker://docker.io/openproject/dev:latest","orasPull":"oras pull openproject/dev:latest","composeYaml":"services:\n  openproject:\n    image: openproject/dev:latest\n    restart: unless-stopped\n    ports:\n      - \"3000:3000\""}}}