# MySQL for the Jorge Cuadros platform on galactus — the PROD source of truth. # # galactus is STANDALONE Docker (Portainer endpoint 3, `swarm: inactive`), not # the 3-node Swarm on cubex. deploy/jorgecuadros-db.stack.yml is the Swarm # version of this file; the deltas are called out below because plain compose # SILENTLY IGNORES the Swarm keys rather than erroring on them: # # 1. `deploy.restart_policy` is ignored -> `restart: unless-stopped` instead. # Without this MySQL does not come back after a host reboot. This is the # single highest-risk difference. # 2. `deploy.placement.constraints` is meaningless on one host — dropped, # along with its `docker node update --label-add jorgecuadros_db=true` # prerequisite. # 3. `deploy.replicas` / `update_config` are ignored — dropped. # 4. `ports: {mode: ingress}` long syntax is Swarm-only -> short syntax. # 5. Named volumes stay exactly as they were: the node-pinning hazard that # motivated them was purely a Swarm problem, and Portainer still namespaces # the volume by stack name. # # This node is the REPLICATION MASTER for the whole topology. Every other MySQL # is a replica of it. server-id must be unique across the topology (prod=1, # cubex dev=11); a duplicate silently breaks replication. binlog + GTID are on # from first boot so a replica can attach with SOURCE_AUTO_POSITION=1 and no # file/position bookkeeping. # # Keep in sync with deploy/jorgecuadros-db.stack.yml when either changes. services: mysql: image: mysql:8.4 restart: unless-stopped command: # (caching_sha2_password is already the default in 8.4; the old # --default-authentication-plugin flag was REMOVED in 8.4 and aborts boot.) - --server-id=${MYSQL_SERVER_ID:-1} - --log-bin=mysql-bin - --binlog-format=ROW - --gtid-mode=ON - --enforce-gtid-consistency=ON # A replica offline longer than this needs a full re-seed, because the # binlogs it still needs are gone. The 8.4 default is 30 days; raise it # here rather than discovering the gap during an outage. - --binlog-expire-logs-seconds=${MYSQL_BINLOG_EXPIRE_SECONDS:-5184000} environment: MYSQL_DATABASE: ${MYSQL_DATABASE:-jorgecuadros} MYSQL_USER: ${MYSQL_USER:-jorgecuadros} MYSQL_PASSWORD: ${MYSQL_PASSWORD:?MYSQL_PASSWORD must be set} MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD:?MYSQL_ROOT_PASSWORD must be set} ports: # Standalone: binds directly on the host. Reachable at # :${MYSQL_PORT}. Replicas connect here — see # docs/DEPLOY_AND_MIGRATIONS.md on NOT exposing raw 3306 to the internet. - "${MYSQL_PORT:-3306}:3306" volumes: - mysql_data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost", "-u", "root", "-p$$MYSQL_ROOT_PASSWORD"] interval: 10s timeout: 5s retries: 12 start_period: 40s volumes: mysql_data: