Docker debugger
Skill lubochka/xiigen-mvp-engine/.agents/skills/docker-debugger
Docker debugging skill for the xiigen-dynamic-forms WordPress plugin test stack. Covers: WordPress 6.7 + MySQL 8 + wp-cli + Playwright + xiigen-mock containers. Includes known issues from Phases 1-3, structured failure patterns with Symptoms → Diagnostic → Fixes, and a complete quick reference.From its SKILL.md
npx -y skills add lubochka/xiigen-mvp-engine --skill docker-debuggerAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
12.7 KB, ~3.2k tokens by cl100k_base, as published. Nobody here has run it
Docker Debugger v2.0
xiigen-dynamic-forms test stack — merged knowledge from Phases 1-3
OUR DOCKER STACK (docker-compose.test.yml)
| Service | Image | Host Port | Health Check |
|---|---|---|---|
| wordpress | wordpress:6.7-php8.2-apache | 18080 | curl -f http://localhost:80/wp-login.php |
| mysql | mysql:8.0 | 13306 | mysqladmin ping -h localhost |
| wp-cli | wordpress:cli-php8.2 | — | One-shot: runs setup-wordpress.sh then exits |
| playwright | mcr.microsoft.com/playwright | — | Runs e2e tests then exits |
| xiigen-mock | node:20-slim | 19090 | curl -f http://localhost:3000/health |
| wordpress-tenant-b | wordpress:6.7-php8.2-apache | 18081 | Phase 9 only |
| mysql-b | mysql:8.0 | — | Phase 9 only |
Zero cloud credentials. Everything runs locally.
STEP 0 — Always Start Here
Before debugging anything, gather state:
# 1. What's running and what exited?
docker compose -f docker-compose.test.yml ps -a
docker compose -f docker-compose.test.yml ps --format "table {{.Name}}\t{{.Status}}\t{{.Ports}}"
# 2. Check health status
docker compose -f docker-compose.test.yml ps --format "table {{.Name}}\t{{.Health}}"
# 3. Recent logs (last 50 lines per service)
docker compose -f docker-compose.test.yml logs --tail 50
# 4. Disk space (Docker can fill up)
docker system df
KNOWN ISSUES FROM PHASES 1-3
These are confirmed issues discovered during execution. Codex MUST know these.
Issue 1: WordPress container has NO wp-cli
Root cause: The official wordpress:6.7-php8.2-apache image doesn't include wp-cli.
Fix: Never run wp inside the wordpress container. Use the wp-cli service:
docker compose -f docker-compose.test.yml run --rm wp-cli wp post create --post_title="Test" --post_status=publish
Caveat: docker compose run creates a NEW container. The wp-cli service must connect to the same MySQL.
Issue 2: mysqli only — NO pdo_mysql
Root cause: WordPress container has mysqli but NOT pdo_mysql by default.
Fix: All database access must use $wpdb (mysqli internally). Never use PDO.
docker compose -f docker-compose.test.yml exec wordpress php -m | grep -i mysql
# Expected: mysqli (NOT pdo_mysql)
Issue 3: SHORTINIT integration tests
Root cause: SHORTINIT loads only bare minimum (wpdb, NOT options API, NOT plugin API).
Fix: Integration tests needing $wpdb use SHORTINIT. Tests needing full WP API use bootstrap-wp.php.
// SHORTINIT: Only $wpdb available. No get_option(), no add_action().
// Full WP: Everything available, but slower.
Issue 4: WP_SITEURL not set
Root cause: WordPress stores site URL in DB. If wp-cli sets it before port mapping is active, it uses internal port (80) not mapped port (18080).
Fix: In setup-wordpress.sh:
wp option update siteurl "http://localhost:18080" --allow-root
wp option update home "http://localhost:18080" --allow-root
Issue 5: E2E posts must be pre-seeded
Root cause: Can't use wp-cli inside wordpress container (Issue 1). wp-cli service exits after setup.
Fix: Pre-seed posts in scripts/setup-wordpress.sh:
wp post create --post_title="Test Form Page" --post_name="test-form-page" \
--post_content='[xiigen_form id="contact"]' --post_status=publish --allow-root
E2E tests navigate to ?name=test-form-page (follows 301 to pretty permalink).
Issue 6: REST API basic auth not available
Root cause: WordPress requires Application Passwords plugin for REST basic auth. Not installed. Fix: E2E tests use cookie-based auth (login via wp-login.php, use session cookie). Unit/integration tests mock the REST request + use CapabilityChecker injection from Phase 3.
Issue 7: PHPUnit 10 compatibility
Root cause: PHPUnit 10 removed legacy features. WP_Mock may not be compatible.
Fix: Use manual stubs in tests/php/stubs/wp-functions.php instead of WP_Mock:
if (!function_exists('wp_nonce_field')) {
function wp_nonce_field($action = -1, $name = '_wpnonce', $referer = true, $echo = true) {
$field = '<input type="hidden" name="' . $name . '" value="test-nonce" />';
if ($echo) echo $field;
return $field;
}
}
FAILURE PATTERNS — Symptoms → Diagnostic → Fixes
PATTERN 1 — MySQL Won't Start / Connection Refused
Symptoms:
SQLSTATE[HY000] [2002] Connection refusedERROR 2003 (HY000): Can't connect to MySQL server- WordPress container restarts repeatedly
mysqlservice shows "Exited (1)"
Diagnostic:
docker compose -f docker-compose.test.yml logs mysql --tail 100
docker compose -f docker-compose.test.yml exec mysql mysqladmin ping -h localhost -u root -ptestpass
Fixes:
Cause A: Corrupted data volume
docker compose -f docker-compose.test.yml down -v
docker volume prune -f
docker compose -f docker-compose.test.yml up -d mysql
sleep 30 # MySQL init takes 30-60 seconds on first run
docker compose -f docker-compose.test.yml logs mysql --tail 20
Cause B: WordPress starts before MySQL is ready
Ensure depends_on with condition: service_healthy in compose file.
Cause C: "InnoDB: Table flags are 0" — stale volume
docker volume rm xiigen-dynamic-forms_mysql-data
docker compose -f docker-compose.test.yml up -d
PATTERN 2 — WordPress Health Check Fails
Symptoms:
wordpressshows "unhealthy"- curl to
http://localhost:18080returns 500 or connection refused - E2E tests can't load any page
Diagnostic:
curl -s -o /dev/null -w "%{http_code}" http://localhost:18080/wp-login.php
docker compose -f docker-compose.test.yml exec wordpress cat /var/log/apache2/error.log | tail -50
docker compose -f docker-compose.test.yml exec wordpress cat /var/www/html/wp-content/debug.log 2>/dev/null | tail -50
Fixes:
Cause A: wp-config.php not generated
docker compose -f docker-compose.test.yml exec wordpress ls -la /var/www/html/wp-config.php
docker compose -f docker-compose.test.yml exec wordpress env | grep -E "WORDPRESS_|WP_"
Cause B: Plugin PHP fatal error
docker compose -f docker-compose.test.yml exec wordpress php -l /var/www/html/wp-content/plugins/xiigen-dynamic-forms/xiigen-dynamic-forms.php
Cause C: WP_SITEURL mismatch — See Known Issue 4 above.
PATTERN 3 — wp-cli Container Fails
Symptoms:
wp-cliservice shows "Exited (1)"- Setup script didn't run (no test posts, no plugin activated)
- "Error: This does not appear to be a WordPress installation"
Diagnostic:
docker compose -f docker-compose.test.yml logs wp-cli --tail 100
docker compose -f docker-compose.test.yml run --rm wp-cli wp db check --allow-root
Fixes:
- wp-cli must
depends_onwordpress withcondition: service_healthy - wp-cli needs SAME database credentials as wordpress
- Working directory must be
/var/www/html
PATTERN 4 — Playwright E2E Tests Fail
Symptoms:
net::ERR_CONNECTION_REFUSEDin E2E logsTimeout 30000ms exceededonpage.goto()- Tests pass locally but fail in Docker
Diagnostic:
docker compose -f docker-compose.test.yml exec playwright curl -s http://wordpress:80/
docker compose -f docker-compose.test.yml exec playwright ping -c 3 wordpress
Fixes:
Cause A: Using localhost instead of service name
// WRONG — localhost means the Playwright container itself
const BASE_URL = 'http://localhost:18080';
// RIGHT — use Docker service name
const BASE_URL = 'http://wordpress:80';
Cause B: WordPress not ready when tests start Add retry/wait logic in test globalSetup.
Cause C: Containers not on the same network All services must share the same Docker network in compose file.
PATTERN 5 — Plugin Mount Not Working
Symptoms:
- Plugin doesn't appear in WordPress admin
- PHP changes not reflected after edit
Diagnostic:
docker compose -f docker-compose.test.yml exec wordpress ls -la /var/www/html/wp-content/plugins/xiigen-dynamic-forms/
docker compose -f docker-compose.test.yml exec wordpress php -l /var/www/html/wp-content/plugins/xiigen-dynamic-forms/xiigen-dynamic-forms.php
Fix: Volume mount must map project root to plugin directory:
volumes:
- .:/var/www/html/wp-content/plugins/xiigen-dynamic-forms
PATTERN 6 — Container Exits Immediately
Diagnostic:
docker inspect <container> --format='{{.State.ExitCode}}'
# 0 = normal exit, 1 = error, 137 = OOM killed, 143 = SIGTERM
docker compose -f docker-compose.test.yml logs <service> --tail 50
docker compose -f docker-compose.test.yml run --rm --entrypoint /bin/bash <service>
PATTERN 7 — Port Already in Use
lsof -i :18080 # or :13306, :19090
kill -9 <PID>
PATTERN 8 — Disk Space / Resource Issues
docker system df
docker system prune -a --volumes # WARNING: removes ALL unused data
# Less aggressive:
docker image prune -a
docker volume prune
docker builder prune
PATTERN 9 — Volume Permission Issues
docker compose -f docker-compose.test.yml exec wordpress ls -la /var/www/html/wp-content/plugins/
docker compose -f docker-compose.test.yml exec wordpress chown -R www-data:www-data /var/www/html/wp-content/plugins/xiigen-dynamic-forms/
PATTERN 10 — Docker Compose File Syntax Errors
docker compose -f docker-compose.test.yml config --quiet && echo "VALID" || echo "INVALID"
docker compose -f docker-compose.test.yml config # show resolved config
FULL RESET (nuclear option)
When nothing else works:
docker compose -f docker-compose.test.yml down --volumes --remove-orphans
docker system prune -f
docker compose -f docker-compose.test.yml up -d --build --force-recreate
sleep 30 # Wait for health checks
docker compose -f docker-compose.test.yml ps
QUICK REFERENCE: Test Commands
# Start stack
docker compose -f docker-compose.test.yml up -d
# Wait for healthy
docker compose -f docker-compose.test.yml ps --format "table {{.Name}}\t{{.Health}}"
# Run all 5 test levels
composer test # PHPUnit unit (mocked, no Docker needed)
composer test:integration # PHPUnit integration (SHORTINIT + Docker MySQL)
npm test # Jest React tests (no Docker needed)
cd e2e && npx playwright test # Playwright E2E (needs full Docker stack)
docker compose -f docker-compose.test.yml exec wordpress \
wp plugin check xiigen-dynamic-forms # PCP compliance
# Shell into containers for debugging
docker compose -f docker-compose.test.yml exec wordpress bash
docker compose -f docker-compose.test.yml exec mysql mysql -uroot -ptestpass wordpress
docker compose -f docker-compose.test.yml exec wordpress php -r "phpinfo();" | grep -i mysqli
# Stop stack
docker compose -f docker-compose.test.yml down
RULES FOR Codex
- Always check container state FIRST. Before guessing at fixes, run
docker compose ps -a. - Read logs before changing code. The error message tells you what's wrong 90% of the time.
- Health checks are your friend. If a service is "unhealthy", the health check command tells you exactly what failed.
- Service names, not localhost. Inside Docker, containers talk via service names (
mysql,wordpress), neverlocalhost. Port 13306 is HOST mapping; 3306 is container port. - Volume mounts are immediate. If you edit a PHP file and it's not reflected, the mount is wrong — not a caching issue.
- MySQL needs time. First-run initialization takes 30-60 seconds. Don't declare failure before then.
- One problem at a time. If MySQL is down AND WordPress is unhealthy, fix MySQL FIRST. WordPress depends on it.
- Nuclear option is okay. If you've spent more than 10 minutes debugging, do a full
down -v+up --build. It's faster than finding a subtle state issue. - Never use PDO. WordPress uses mysqli. See Known Issue 2.
- wp-cli is a separate container. Never run
wpinside the wordpress container. See Known Issue 1.
END OF SKILL
What ships with it: 5 files
22.6 KB alongside SKILL.md
references/
- docker-basics.md5.7 KB
- docker-compose.md4.7 KB
- systematic-debugging.md9.5 KB
- AGENTS.md1.9 KB
- skill.yaml733 B