Drupal + Next.js test stack
Usage
- Ensure Docker and Docker Compose are installed.
- Create a .env file at the project root with database variables required by docker-compose.yml, for example:
# .env
MYSQL_ROOT_PASSWORD=supersecret
MYSQL_USER=drupal
MYSQL_PASSWORD=drupal
MYSQL_DATABASE=drupal
# Optional if you use a non-standard port inside the network
MYSQL_PORT=3306- Or create it automatically with the helper script:
chmod +x ./create_env.sh && ./create_env.sh
# To overwrite an existing .env:
FORCE=1 ./create_env.sh- Map test.local to localhost in /etc/hosts if you want to use the virtual host: 127.0.0.1 test.local
Install Drupal (empty database)
- From the project root run:
# Start/ensure DB is up, then (re)create containers so PHP gets DB env vars
docker compose up -d test_db
# If you changed docker-compose.yml, rebuild/recreate:
docker compose up -d --build
# Run the installer helper
chmod +x ./install_drupal.sh && ./install_drupal.sh- To enable extra debugging during install, run:
DEBUG=1 ./install_drupal.sh- The script will:
- Start the database, PHP-FPM (Drupal) and Nginx containers
- Wait for the database to be ready (with detailed diagnostics on failure; supports MYSQL_PORT and works even if mysqladmin isn't present)
- Install Composer dependencies inside the PHP container
- Ensure Drush is available
- Prepare permissions for web/sites/default
- Run a non-interactive Drupal install using the DB defined in .env
- Enables the custom 'test' module automatically
- Clear caches
- Print drush status and basic connectivity checks
Access
- http://localhost (via Nginx)
- http://test.local (requires hosts entry above)
- Search page:
Diagnostics
- You can gather useful logs and connectivity checks with:
chmod +x ./diagnose_access.sh && ./diagnose_access.sh- Increase the log tail if needed:
TAIL=500 ./diagnose_access.shNotes
- You don't need to run
docker compose buildfirst; the install script usesdocker compose up --buildand will build images as needed. If you changed Dockerfiles and want a full rebuild, rundocker compose build --no-cacheonce. - You can override defaults when running the install script, for example: DRUPAL_SITE_NAME="My Site" DRUPAL_ACCOUNT_NAME=admin DRUPAL_ACCOUNT_PASS=admin ./install_drupal.sh
- The Drupal code and data are stored under the ./drupal directory, as mounted in the containers.
To access the drupal container:
docker exec -it test_drupal bashPart 1: Drupal (Producer)
- Custom module lives at drupal/web/modules/custom/test
- It creates the Dictionary Entry content type with:
- field_word (plain text, required, unique)
- field_definitions (long text)
- It exposes entries via JSON:API and supports filter by field_word.
Import a word via Drush
docker exec -it test_drupal bash -lc "drush import-word hello"- If the word exists at https://dictionaryapi.dev/ it will be created/updated.
- If not found, a simple error is shown.
Example JSON:API request
- http://test.local/jsonapi/node/dictionary_entry?filter[field_word]=hello
- http://localhost/jsonapi/node/dictionary_entry?filter[field_word]=hello
Part 2: Next.js (Consumer) The Next.js app is under ./nextjs and uses the App Router (TypeScript) with Tailwind CSS.
Run locally
- Ensure Drupal is running and reachable at http://localhost or http://test.local
- Create ./nextjs/.env with:
NEXT_API_URL=http://localhost
# or
# NEXT_API_URL=http://test.local
- Install and start the app:
cd nextjs
npm install
npm run devBehavior
- On the homepage, search a word. If not found, an inline error is shown and the page does not navigate.
- If found, the app navigates to /word/[word] and renders field_word and field_definitions.
Example fetch URL used by the app
- ${NEXT_API_URL}/jsonapi/node/dictionary_entry?filter[field_word]=hello
Troubleshooting
- Access denied (SQLSTATE[HY000] [1045]) when installing Drupal usually means the MariaDB volume was initialized earlier with different credentials. Changing .env later does not recreate users in an existing data directory, so the drupal user may be missing or have the wrong password.
Option A: Repair/create the DB user and grants (non-destructive)
# Ensure DB is running
docker compose up -d test_db
# Run the helper to (re)create the user and grants using root creds from .env
chmod +x ./fix_db_user.sh && ./fix_db_user.sh
# Then re-run the installer
./install_drupal.shOption B: Reset the database volume (DELETES ALL DATA)
chmod +x ./reset_db.sh && ./reset_db.sh
# This stops containers and removes the DB volume, then starts a fresh DB.
# After it is up, run the installer again:
./install_drupal.shNotes
- Ensure your .env has the intended values before (re)creating containers.
- The PHP container receives MYSQL_* via docker-compose.yml; if you changed them, recreate the container:
docker compose up -d --build.