Skip to content

Latest commit

 

History

27 Commits

Folders and files

NameName
Last commit message
Last commit date
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Docker Compose Repository

English | 한국어

Docker Compose Elasticsearch PostgreSQL ChromaDB OpenTelemetry Terraform License

A collection of Docker Compose files for the backing services I run on my development machine: search, a relational database, a vector store, distributed tracing, a static-site dev server, and a containerized Terraform CLI.

There is no application code here. Each file is a self-contained stack that can be started on its own, and all of them attach to one shared Docker bridge network so containers from different stacks can reach each other by service name.


Contents

Stack Compose file Services Published ports
Elasticsearch 8 elasticsearch/elkstack-v1.2.yml Elasticsearch 8.17.2 (Nori analyzer, built locally), one-shot user bootstrap, Kibana 8.17.2 10041, 10042
Elasticsearch 7 elasticsearch/elasticsearch-7-14-1/elkstack-v1.2.yml Same shape on 7.14.1 10060, 10061
Kibana → remote elasticsearch/kibana-ifns.yml Kibana 8.17.2 only, pointed at a cluster elsewhere on the network 10040
ChromaDB chromadb/chromadb-v10.yml ChromaDB, OpenTelemetry Collector, Zipkin 10050, 10051
PostgreSQL postgresql/postgresql-v11.yml PostgreSQL 17, schema loaded from init.sql on first boot 10010
PostgreSQL + pgAdmin postgresql/postgresql-pgadmin-v10.yml PostgreSQL 17, pgAdmin 4 10010, 10011
Jekyll jekyll/jekyll.yml Jekyll dev server with --watch 10020
Terraform terraform/terraform.yml Terraform 1.9 CLI, run as a one-off command

The two PostgreSQL files are alternatives, not companions — both publish 10010, so only one runs at a time.


Requirements

  • Docker Engine with Compose v2 (docker compose, not docker-compose)

  • The shared network, created once per machine:

    docker network create avocado-network

    Every stack declares this network as external: true and will fail to start if it does not exist.

  • Enough RAM for the Elasticsearch stacks: ES_HEAP_SIZE defaults to 3g per node, plus container overhead.


Quick start

Each stack directory has its own .env.example. Copy it, fill in the values, then bring the stack up from inside that directory.

# Elasticsearch 8 + Kibana (builds a local image on first run)
cd elasticsearch
cp .env.example .env
docker compose -f elkstack-v1.2.yml up -d --build
# Elasticsearch → http://localhost:10041   (user: elastic)
# Kibana        → http://localhost:10042
# PostgreSQL
cd postgresql
cp .env.example .env
docker compose -f postgresql-v11.yml up -d
# ChromaDB + tracing
cd chromadb
cp .env.example .env
docker compose -f chromadb-v10.yml up -d
# ChromaDB → http://localhost:10050
# Zipkin   → http://localhost:10051
# Terraform (no long-running container)
cd terraform
cp .env.example .env          # TF_PROJECT must be an absolute host path
docker compose -f terraform.yml run --rm terraform init
docker compose -f terraform.yml run --rm terraform plan

Tear a stack down with docker compose -f <file> down, or down -v to drop its named volumes as well.


Conventions

Ports. Nothing binds a service's default port, so these stacks do not collide with a PostgreSQL or Elasticsearch already installed on the host. Each area owns a band:

Band Area
1001x Relational database and its admin UI
1002x Web / static site
1004x Elastic 8.x, and Kibana against a remote cluster
1005x Vector store and tracing
1006x Elastic 7.x

Configuration. Credentials and host paths come from a per-directory .env, which is gitignored. Required variables use the ${VAR:?message} form, so a missing value stops the stack at startup with a named error instead of falling back to a default. .env.example files are committed and document what each stack needs.

Image versions. Most images are pinned to explicit tags rather than latest. The exceptions are dpage/pgadmin4:latest, jekyll/jekyll:latest, and openzipkin/zipkin (untagged, so also latest) — all three are UI or tooling containers holding no data worth reproducing. The ChromaDB tag (1.5.8.dev23) is a pre-release build.

Locally built images. The Nori-enabled Elasticsearch images are tagged elasticsearch-nori:<version> — deliberately not the upstream tag, so Docker cannot resolve the official plugin-less image in their place. These stacks need --build on first run.

Startup order. Where order matters it is expressed with health checks rather than delays: the Kibana service waits for the bootstrap container's service_completed_successfully, which in turn waits for Elasticsearch's service_healthy. The pgAdmin service waits on PostgreSQL's pg_isready health check.

State. PostgreSQL, pgAdmin, and Elasticsearch persist to named Docker volumes. ChromaDB and Jekyll use bind mounts driven by CHROMA_DATA_DIR and JEKYLL_SITE_DIR, defaulting to a path relative to the compose file.

Line endings. .gitattributes normalizes text files to LF and marks certificate and image files binary, so checkouts on Windows do not show the tree as modified.


Stack notes

Elasticsearch + Kibana

Dockerfile.es-nori installs the analysis-nori Korean morphological analyzer into the official image at build time, skipping the install if the plugin is already present.

Both Elastic stacks run discovery.type=single-node with security enabled and TLS switched off on the HTTP and transport layers. The health check treats Elasticsearch's missing authentication credentials response as the success signal — an unauthenticated probe being rejected shows the node is both serving and enforcing security.

A one-shot elasticsearch_settings container sets the kibana_system password over the security API and exits; Kibana starts only after it completes successfully.

The 8.17.2 and 7.14.1 stacks use different ports, container names, and volumes, so they can run at the same time. The 7.x directory has no .env.example of its own — copy the parent one:

cd elasticsearch/elasticsearch-7-14-1
cp ../.env.example .env
docker compose -f elkstack-v1.2.yml up -d --build

kibana-ifns.yml starts Kibana alone against REMOTE_ES_HOST, for browsing a cluster this repo does not manage.

Two files in elasticsearch/ are reference material and are not used by any stack here:

  • config/elasticsearch.yml — a TLS-enabled node configuration, including the elasticsearch-certutil and keystore commands needed to produce it. Certificate material belongs in certs/, which is gitignored and generated locally.
  • logstash/config/logstash.yml — pipeline settings from an earlier Logstash setup. No compose file starts Logstash.

ChromaDB

ChromaDB is configured to persist to /data and to export OTLP traces to the OpenTelemetry Collector, which batches them under a memory limiter and exports to Zipkin at http://zipkin:9411/api/v2/spans. The collector reads otel-collector-config.yaml, mounted read-only relative to the compose file. ANONYMIZED_TELEMETRY is left on.

PostgreSQL

Both files set the user, password, and database from .env. Only postgresql-v11.yml mounts init.sql, and Postgres runs it only when the data directory is empty — so it applies on a first boot, or after down -v.

init.sql creates a rag_chatbot schema with a config key/value table and seeds it with retrieval settings, index names, and model paths for an application that reads its configuration from the database. Secret-looking values in it are placeholders (__SET_AT_DEPLOY__); real credentials are injected at application start.

Jekyll

Serves the directory named by JEKYLL_SITE_DIR (default ./jekyll-site, a minimal sample site) with jekyll serve --watch --drafts. On Windows and WSL bind mounts, inotify events are not always delivered — add --force_polling to the command if edits are not picked up.

Terraform

Runs the pinned CLI in a container instead of installing it on the host, with TF_PROJECT mounted at /workspace. Docker cannot resolve relative paths in bind mounts, so TF_PROJECT must be absolute. AWS credentials pass through if set and default to empty, which is fine for local-only providers; AWS_REGION defaults to ap-northeast-2.


Repository layout

.
├── chromadb/
│   ├── chromadb-v10.yml            # Chroma + OTel Collector + Zipkin
│   └── otel-collector-config.yaml  # OTLP receive → batch → Zipkin export
├── elasticsearch/
│   ├── elkstack-v1.2.yml           # ES 8.17.2 + Nori + Kibana
│   ├── Dockerfile.es-nori          # Nori installed at image build time
│   ├── kibana-ifns.yml             # Kibana → remote cluster
│   ├── config/elasticsearch.yml    # TLS reference config (unused by the stacks)
│   ├── logstash/config/            # Logstash settings (unused by the stacks)
│   └── elasticsearch-7-14-1/       # Parallel 7.14.1 stack
├── postgresql/
│   ├── postgresql-v11.yml          # Postgres 17 + init.sql
│   ├── postgresql-pgadmin-v10.yml  # Postgres 17 + pgAdmin
│   └── init.sql                    # Schema and config seed, first boot only
├── jekyll/
│   ├── jekyll.yml                  # Jekyll dev server
│   └── jekyll-site/                # Sample site to serve
├── terraform/terraform.yml         # Containerized Terraform CLI
├── .gitattributes                  # LF normalization, linguist hints
└── prompt-documentation.md         # Working notes on changes to this repo

Caveats

  • This is a local development setup. It is not hardened for production: HTTP-layer TLS is off in the compose stacks, containers run as their images' default users, there are no CPU or memory limits, and secrets live in .env rather than a secret manager.
  • Written and used on Windows with Docker Desktop. The compose files contain no OS-specific paths and should run unchanged on Linux and macOS.
  • bootstrap.memory_lock=true depends on the memlock ulimits already declared in the Elastic stacks; removing them will cause the node to fail at startup.
  • The two Elasticsearch stacks read the same variable names from separate .env files. Their ports, container names, and volumes differ, so running both is safe, but the passwords are whatever each .env says.

License

MIT

About

Local development infrastructure as Compose files: version-pinned images, health-gated startup order, per-stack .env contracts, a documented port scheme. Elasticsearch 8/7 with Korean Nori, ChromaDB → OTel → Zipkin, PostgreSQL 17 + pgAdmin, Jekyll, containerized Terraform.

Topics

Resources

Stars

0 stars

Watchers

1 watching

Forks

Releases

Packages

Contributors

Languages