docker-compose.test.yml
Rama main · réplica de lectura del repositorio original.
# Databases the test suite talks to.
#
# Several tests are only meaningful against a real server: what a string
# literal means, how a driver converts a value, whether a collation orders the
# way Go does. Those are exactly the questions a fake would define away, so
# they skip unless the matching environment variable is set — which meant, for
# a long time, that they only ever ran on one developer's machine.
#
# docker compose -f docker-compose.test.yml up -d
# export BROKOLI_TEST_POSTGRES_URL='postgres://brokoli:brokoli@localhost:55532/brokoli_test?sslmode=disable'
# export BROKOLI_TEST_MYSQL_URL='mysql://brokoli:br@k:li/pw#1@tcp(localhost:55533)/brokoli_test'
# export BROKOLI_TEST_MYSQL_ROOT_URL='mysql://root:rootpw@tcp(localhost:55533)/brokoli_test'
# export BROKOLI_TEST_CLICKHOUSE_URL='clickhouse://brokoli:brokoli@localhost:55534/brokoli_test'
# export BROKOLI_TEST_SQLSERVER_URL='sqlserver://sa:Brokoli%2112345@localhost:55535?database=master&encrypt=disable'
# export BROKOLI_TEST_S3_ENDPOINT='http://localhost:55536'
# export BROKOLI_TEST_S3_ACCESS_KEY='brokoli-test'
# export BROKOLI_TEST_S3_SECRET_KEY='brokoli-test-secret'
# export BROKOLI_BIGQUERY_ENDPOINT='http://localhost:55538'
# export BROKOLI_OUTBOUND_ALLOW_LOOPBACK='true' # MinIO is bound to localhost
# go test ./...
#
# Ports are in an unusual range so this does not collide with a database
# someone already has running — 5543x is taken on at least one machine here,
# which is how that lesson was learned. The data is tmpfs — these are scratch
# servers, and a test that depends on state surviving a restart is a test
# that will fail mysteriously in CI.
services:
gcs:
# fake-gcs-server (MIT), pinned like every other service here. The public
# host and external URL keep resumable uploads on this address: without
# them the emulator hands back a session URL on storage.googleapis.com.
image: fsouza/fake-gcs-server:1.56.1
command: ["-scheme", "http", "-port", "4443", "-backend", "memory",
"-public-host", "127.0.0.1:55543", "-external-url", "http://127.0.0.1:55543"]
ports:
- "55543:4443"
openbao:
# OpenBao (MPL-2.0) speaks Vault's HTTP API, so the vault secret-store
# provider is tested against it. Dev mode: in-memory, unsealed, a KV v2
# mount at secret/, and a fixed root token the tests use to configure
# policies and auth methods.
image: openbao/openbao:2.4.1
command: ["server", "-dev", "-dev-root-token-id=brokoli-test-root", "-dev-listen-address=0.0.0.0:8200"]
cap_add: ["IPC_LOCK"]
ports:
- "55547:8200"
bigquery:
# Pinned, like every other service here. goccy/bigquery-emulator is a
# community project (MIT); 0.8.1 is its release of 2026-06-13.
image: ghcr.io/goccy/bigquery-emulator:0.8.1
command: ["--project=test", "--dataset=brokoli_test"]
ports:
- "55538:9050"
postgres:
image: postgres:16-alpine
environment:
POSTGRES_USER: brokoli
POSTGRES_PASSWORD: brokoli
POSTGRES_DB: brokoli_test
ports:
- "55532:5432"
tmpfs:
- /var/lib/postgresql/data
healthcheck:
test: ["CMD-SHELL", "pg_isready -U brokoli -d brokoli_test"]
interval: 2s
timeout: 3s
retries: 30
mysql:
image: mysql:8.4
environment:
MYSQL_ROOT_PASSWORD: rootpw
MYSQL_USER: brokoli
MYSQL_PASSWORD: br@k:li/pw#1
MYSQL_DATABASE: brokoli_test
ports:
- "55533:3306"
tmpfs:
- /var/lib/mysql
command:
# local_infile is off by default in MySQL 8 and is what a bulk-load
# path would need; enabling it here means the capability can be tested
# rather than assumed available.
- --local-infile=1
healthcheck:
test: ["CMD", "mysqladmin", "ping", "-h", "127.0.0.1", "-uroot", "-prootpw"]
interval: 3s
timeout: 5s
retries: 30
clickhouse:
# 25.3 is an LTS release, pinned per ADR-027 phase 0. The exposed port
# is the NATIVE protocol (9000) -- clickhouse-go's decision path; the
# HTTP port stays unexposed because the ADR defers the HTTP fallback.
#
# The password is deliberately plain for now: hostile-credential
# coverage belongs to phase 1, when the URI builder that has to carry
# it exists (the MySQL password above is hostile because #338's DSN
# builder is what it proves).
image: clickhouse/clickhouse-server:25.3-alpine
environment:
CLICKHOUSE_USER: brokoli
CLICKHOUSE_PASSWORD: brokoli
CLICKHOUSE_DB: brokoli_test
# Lets the test user CREATE USER, which the hostile-credential
# round-trip test needs. Scratch server, tmpfs data.
CLICKHOUSE_DEFAULT_ACCESS_MANAGEMENT: "1"
ports:
- "55534:9000"
tmpfs:
- /var/lib/clickhouse
ulimits:
# The server refuses to start under the default container nofile
# limit on some hosts; this is the value its own docs use.
nofile:
soft: 262144
hard: 262144
healthcheck:
# /ping answers unauthenticated on the HTTP port inside the
# container, so the check needs no credentials.
test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8123/ping"]
interval: 3s
timeout: 5s
retries: 30
# Oracle Database Free, from gvenzl/oracle-free (Apache-2.0 image build of
# Oracle's free edition), pinned by digest: the 23-slim tag moves with
# each Oracle release. It is a 2 GB image, so it sits behind a profile and
# a plain `up -d` does not pull it; naming it starts it:
#
# docker compose -f docker-compose.test.yml up -d --wait oracle
# export BROKOLI_TEST_ORACLE_URL='oracle://brokoli:p%40ss%2Fw%3Ard%231@127.0.0.1:55544/FREEPDB1'
#
# The application user's password carries @, /, : and # on purpose, so
# the tests prove a connection's URI survives URL syntax in a credential.
oracle:
image: gvenzl/oracle-free:23-slim@sha256:6d61d267a3b978c24c5ac1790e62e927416a0aec446bd86e4b3a1527562757bd
profiles: ["oracle"]
environment:
ORACLE_PASSWORD: "Brokoli_sys1"
APP_USER: brokoli
APP_USER_PASSWORD: "p@ss/w:rd#1"
ports:
- "55544:1521"
tmpfs:
- /opt/oracle/oradata
healthcheck:
# The image's own check: the database is open and the PDB is up.
test: ["CMD", "healthcheck.sh"]
interval: 5s
timeout: 5s
retries: 60
start_period: 10s
sqlserver:
image: mcr.microsoft.com/mssql/server:2022-latest
environment:
ACCEPT_EULA: "Y"
MSSQL_SA_PASSWORD: "Brokoli!12345"
MSSQL_PID: Developer
ports:
- "55535:1433"
tmpfs:
# The 2022 image runs as the non-root mssql user. Docker creates a
# tmpfs mount as root unless its ownership is explicit, which prevents
# the image from creating /.system during startup.
- /var/opt/mssql:rw,uid=10001,gid=0,mode=1770
healthcheck:
test: ["CMD-SHELL", "timeout 1 bash -c '</dev/tcp/127.0.0.1/1433'"]
interval: 5s
timeout: 3s
retries: 30
# S3-compatible object store for the file-node and artifact-store tests.
#
# This was MinIO until 2026-09-25, when MinIO withdrew public access to
# its container images: the pinned tag, every other tag, Docker Hub,
# quay.io, ghcr.io and public.ecr.aws all answer "unauthorized" or
# "repository does not exist" to an anonymous pull. Nothing in this repo
# changed; the dependency did, and CI began failing in 8 seconds at the
# pull, before a single test ran.
#
# SeaweedFS rather than an S3 mock deliberately: it is a real object
# store and it ENFORCES the credentials below (an unauthenticated
# request gets 403). A mock that ignores auth would let these tests pass
# while the credential path went unexercised, which is the kind of
# quietly hollow gate this repo keeps finding and removing.
#
# The service keeps the name, port and credentials the old one had, so
# the workflow, the env vars and the tests are untouched.
azurite:
# Microsoft's own Azure Storage emulator, for the azure_blob file
# transport (#687): blob service only, data in tmpfs, pinned like the
# S3 service so an image change is a deliberate edit.
# --skipApiVersionCheck: the SDK may speak a newer API version than a
# pinned emulator knows, and the operations used here are old ones.
image: mcr.microsoft.com/azure-storage/azurite:3.37.0
command: azurite-blob --blobHost 0.0.0.0 --blobPort 10000 --location /data --skipApiVersionCheck
ports:
- "55537:10000"
tmpfs:
- /data
healthcheck:
# Any HTTP status line means the blob API is serving; an anonymous
# list is refused, which is fine. busybox wget, as the image has no
# curl.
test:
- CMD-SHELL
- 'wget -q -S -O /dev/null "http://127.0.0.1:10000/devstoreaccount1?comp=list" 2>&1 | grep -qE "HTTP/1.1 [0-9]{3}"'
interval: 2s
timeout: 5s
retries: 30
minio:
image: chrislusf/seaweedfs:3.80
command: server -s3 -s3.port=8333 -s3.config=/etc/seaweedfs/s3.json -dir=/data
volumes:
- ./testdata/seaweedfs-s3.json:/etc/seaweedfs/s3.json:ro
ports:
- "55536:8333"
tmpfs:
- /data
healthcheck:
# 403 is the correct answer from an S3 endpoint to an unauthenticated
# GET, and it is the first moment the API is actually serving, so it
# is the readiness signal. `curl -f` would treat it as failure.
# wget, not curl: this image is minimal and has no curl, which the
# first version of this healthcheck discovered the slow way.
test:
- CMD-SHELL
- 'wget -q -S -O /dev/null http://127.0.0.1:8333/ 2>&1 | grep -qE "HTTP/1.1 (200|403)"'
# The master, volume and S3 components converge in about 35s on a
# cold runner, so the window is wider than MinIO's single process
# needed.
interval: 3s
timeout: 5s
retries: 40
start_period: 10s
localstack:
# The aws_secrets_manager and aws_ssm secret-store providers (ADR-041)
# are tested against LocalStack's Secrets Manager, SSM and STS. 4.4 is
# the community edition and runs without an auth token; pinned by digest
# so a later image that requires one cannot arrive silently.
image: localstack/localstack:4.4@sha256:b52c16663c70b7234f217cb993a339b46686e30a1a5d9279cb5feeb2202f837c
environment:
SERVICES: secretsmanager,ssm,sts
ports:
- "55545:4566"
healthcheck:
test:
- CMD-SHELL
- 'curl -s http://127.0.0.1:4566/_localstack/health | grep -q "\"secretsmanager\": \"available\""'
interval: 2s
timeout: 5s
retries: 60