Lint scanner now flags `community.docker.docker_container_exec` — it has
a 1:1 `compose exec`/`container exec` replacement and pinning to Docker
defeats engine-swappability. Other `community.docker.*` modules (network
create, host_info, container start with image+args) have no clean wrapper
equivalent and stay legal.
Migrations:
- svc-db-mariadb (01_core, 02_init, 03_reset_root_password): replace
module calls with `container exec -i` via `ansible.builtin.command`,
pipe SQL via stdin. Health probes share a single SELECT 1 file.
- web-app-decidim (01_setup): same migration, preserving env vars as
`-e KEY=VAL` argv elements and stdin for rails-runner snippets.
Extract all SQL to `roles/svc-db-mariadb/files/sql/*.sql` as plain SQL
(no Jinja). Values flow as MariaDB user variables (`@db_name`, `@db_pwd`,
`@root_pwd`, …) via a `SET` prefix in the task stdin. Identifier
substitution (db/user/encoding names) uses `PREPARE` + `CONCAT(@var, …)`
since `@vars` cannot bind identifiers directly. Password values use
`QUOTE(@var)` inside SQL and Jinja `replace("'", "''")` on the task side.
Pin MariaDB to "11.8" (current LTS major). Required for `CREATE DATABASE`
in prepared statements, supported since 10.5.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>