feat: add Docker Compose setup for local development#1
Closed
aberoham wants to merge 15 commits into
Closed
Conversation
the .test/, dist/docker/debian/, and .dist configs were three copies of roughly the same thing with different hardcoded passwords. now there's one set of env-var-aware .dist configs and a shared setup script that Docker and CI both call. what changed: - nictoolserver.conf.dist and nictoolclient.conf.dist read credentials, hosts, ports, protocol from env vars (safe defaults for non-sensitive stuff, die() for passwords so you know what to set) - new dist/setup/ with install-nictool.sh, apache.conf.in template, tls-setup.sh, and setup-test-env.pl for generating test users - dist/docker/ flattened -- new Dockerfile with layer caching so code changes rebuild in ~2s, docker-compose.yml, entrypoint, and a generate-env.sh that creates random passwords - healthcheck on the web container so --wait actually waits for Apache - ci.yml generates random creds per run instead of sed-ing hardcoded passwords into config copies - new docker.yml workflow that builds the image and runs server, client, and all 120 E2E tests against it - deleted 7 redundant .test/ files and the old dist/docker/debian/ tree - `git grep -i lootcin` returns zero matches now - test.cfg files gitignored, generated at runtime by setup-test-env.pl - perltidy on all modified perl files Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
fda24ac to
9805233
Compare
Pre-build the image with docker/build-push-action using GitHub Actions cache (type=gha, mode=max) so the expensive apt/cpanm layers persist across runs. Code-only changes should skip straight to the final COPY layer. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
the GitHub Actions MySQL runner uses caching_sha2_password which requires SSL. the old .test/create_tables.pl hardcoded mysql_ssl => 1, but we need it parameterized so it works everywhere. DB_SSL=1 enables mysql_ssl=1 in the DSN and DBI connect options for nictoolserver.conf.dist, create_tables.pl, and setup-test-env.pl. unset or empty means no SSL (Docker's MariaDB doesn't need it). CI sets DB_SSL=1, Docker doesn't. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
brought back .test/apache-matt.conf with: - PerlPassEnv directives so the env-var-aware .dist configs work - Apache 2.4 Require all granted (was 2.2 Order/Allow) - quoted paths for spaces safety - added Directory block on the server vhost - header comment showing how to use it (or just run install-nictool.sh) Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
create_tables.pl grants to nictool@$DB_HOSTNAME. with 127.0.0.1, MySQL's reverse lookup sees the connection as 'localhost' which doesn't match the grant for '127.0.0.1'. the old .test/create_tables.pl used localhost and granted to localhost/127.0.0.1/::1 — matching the runner's MySQL behavior. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
MySQL 8.0 removed GRANT ... IDENTIFIED BY for user creation. the old syntax silently failed to create the nictool user, so setup-test-env.pl couldn't connect. now uses CREATE USER (with mysql_native_password, falling back to default plugin) followed by a separate GRANT — same pattern the old .test/create_tables.pl used. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
mod_perl requires mpm_prefork — Ubuntu defaults to mpm_event which causes 500 errors on mod_perl handler requests. the Dockerfile already did this but the shared install script didn't. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI: sudo cpanm leaves root-owned build artifacts that Apache (www-data)
can't read, causing "Permission denied" on URI/_generic.pm. Add chmod
before Apache restart.
Docker: $dbh->do() doesn't throw exceptions by default (no RaiseError),
so the eval { do(); 1 } pattern always returned 1. The mysql_native_password
syntax fails on MariaDB but the fallback never ran. Use return value check
instead.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI: The 500 error was AppArmor, not Unix permissions. Ubuntu 22.04's Apache profile blocks reads from /home/runner/work/ — EACCES even for nonexistent files, which is why URI/_generic.pm showed "Permission denied" despite not existing. Disable the profile in CI. Docker: cache npm packages (setup-node) and Playwright browsers (actions/cache) so E2E dependency installs are fast on repeat runs. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Docker workflow is now three jobs: build (populates GHA layer cache), docker-tests (server + client), and e2e-tests (Playwright). The test jobs run in parallel after the build, each loading the image from cache. Node bumped from EOL 18 to LTS 22. CI: the 500 error was Ubuntu's AppArmor profile for Apache blocking reads from /home/runner/work/ — returning EACCES even for nonexistent files (which is why URI/_generic.pm showed "Permission denied" despite not existing in client/lib/). Disable the profile in CI. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
CI: Instead of disabling AppArmor, symlink the workspace to /var/www/nictool and use that as NT_DIR. Apache's AppArmor profile allows /var/www/ reads. Docker E2E: add a curl-based login verification step before Playwright to diagnose why login returns no session cookie. Also fix password extraction to handle base64 = chars (sed instead of cut -d=). Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
c4305ab to
d0070a0
Compare
Symlinks don't work — AppArmor resolves to the real path. Instead, add a local rule allowing Apache to read $GITHUB_WORKSPACE/** and reload the profile. This is the standard AppArmor mechanism for site-specific additions. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Not AppArmor (no profile exists on the runner). Ubuntu 21.04+ defaults home directories to 750, so www-data can't traverse /home/runner/. Add o+x to each parent dir in the workspace path. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
dist/docker/debian/web/layout with a flatteneddist/docker/structuredocker-compose.ymlwith MariaDB 11 + web service, health checks, volume persistencenictoolserver.confandtest.cfgUsage
Test plan
docker compose buildsucceedsdocker compose up -dstarts both containers healthy🤖 Generated with Claude Code