Skip to content

Latest commit

 

History

History
139 lines (107 loc) · 6.73 KB

File metadata and controls

139 lines (107 loc) · 6.73 KB

GitLab dev stacks (CE + EE) via Docker Compose

Local docker-compose stacks that build and run GitLab from source for development — one for CE (FOSS) and one for EE. Each stack builds the Rails app + Workhorse from a local source checkout and runs Postgres, Redis, and Gitaly (prebuilt images) alongside. The headline feature is a hot-reload frontend mode (webpack dev server behind an nginx proxy) so you can edit JS/Vue and see the change on refresh — plus faster unminified asset builds.

The two stacks are independent (separate compose projects, volumes, and host ports) and can run at the same time.

Layout

gitlab-ee-dev/            # this repo (tooling only — no GitLab source)
├── ce/                   # CE (FOSS) stack
│   ├── docker-compose.dev.yml
│   ├── dev.sh  Makefile             # wrappers (same targets)
│   ├── Dockerfile                   # app image (Rails + Workhorse)
│   ├── Dockerfile.assets-build      # assets image (deps + compile stages)
│   ├── build-assets-fast.sh         # host-native full asset build (populates public/assets)
│   ├── .env  env.example
│   └── docker/docker-entrypoint.sh  docker/nginx-dev-proxy.conf  docker/gitaly-config.toml
└── ee/                   # EE stack (same shape, EE naming/ports)

../gitlab-foss            # CE source tree        (ce/ default GITLAB_SRC)
../gitlab-v18.11.4-ee     # EE source tree        (ee/ default GITLAB_SRC)

Gitaly always runs from the official CNG prebuilt image, so no Gitaly source checkout is needed.

Prerequisites

  • Docker with Buildx (Compose v2).
  • The GitLab source checkout for your edition (path configurable — see GITLAB_SRC).
  • For hotreload mode (and build-assets-fast.sh), a one-time host toolchain for compiling assets natively — see the header of ce/build-assets-fast.sh for the apt-get list. The Docker asset builds install their own build deps inside the image.
  • Assets/webpack builds are memory-hungry (~6–8 GB). Free RAM before a cold build.

Quick start

cd ce            # or: cd ee
cp env.example .env             # then set GITLAB_SRC + secrets (GITLAB_HOST defaults to localhost)
./dev.sh up                     # or: make up

Then browse:

Log in with GITLAB_ROOT_EMAIL / GITLAB_ROOT_PASSWORD from .env.

ASSETS_MODE — the single frontend switch (.env)

Mode What runs Use for
prebuilt app built FROM the official registry assets image; nothing compiled locally fastest bring-up; no frontend work
full local assets image, production/minified shippable-like static assets
fast local assets image, unminified (skips terser, webpack's ~90% cost) quick static assets for UI testing
hotreload webpack dev server + nginx proxy (compose hotreload profile); Rails fetches the manifest live live iteration — edit JS/Vue → browser auto-reloads

ASSETS_MODE also selects how the app image sources assets (it derives the ASSETS_SOURCE build-arg internally), so it's the only assets knob you set.

Hot reload

With ASSETS_MODE=hotreload, ./dev.sh up starts two extra services:

  • assets-watch — runs webpack-dev-server against the mounted source (in-memory bundles + HMR).
  • proxy — nginx on the host port, routing /assets/webpack/* + /ws to the dev server and everything else to Workhorse (so the browser stays same-origin).

Edit any .js/.vue under <source>/app/assets/javascripts/ → webpack rebuilds in-container → the page auto-reloads. (GitLab wires live-reload — a full page refresh — rather than state-preserving HMR for most components.)

Prerequisite: the source tree's public/assets must already hold CSS/images/sprockets output (the dev server only rebuilds the JS). Populate it once with:

./build-assets-fast.sh          # full unminified compile on the host, writes <source>/public/assets

Adding a brand-new chunk (new entry point / dynamic import) changes the manifest; restart web to pick it up: docker compose -f docker-compose.dev.yml restart web.

Environment variables (.env)

Var Meaning
GITLAB_HOST / GITLAB_PORT / GITLAB_HTTPS external URL the browser uses (CE 8182, EE 8181). GITLAB_HOST is optional — defaults to localhost; don't use 0.0.0.0 (it's a bind address, not a reachable host).
GITLAB_SRC GitLab source tree (absolute, or relative to the stack dir) — set this
GITLAB_VERSION bare version tag (e.g. 18.11.4); image/registry tags add a leading v
ASSETS_MODE prebuilt | full | fast | hotreload (see above)
WORKHORSE_SOURCE source (compile) or prebuilt (official CNG image). Gitaly is always prebuilt.
POSTGRES_*, GITALY_AUTH_TOKEN, GITLAB_SHELL_SECRET, GITLAB_WORKHORSE_SECRET infra + shared secrets
GITLAB_ROOT_EMAIL / GITLAB_ROOT_PASSWORD initial admin, seeded on first boot

To target another release: set GITLAB_VERSION and point GITLAB_SRC at a matching checkout, then rebuild.

Commands (./dev.sh <cmd> or make <cmd>)

Command Action
up build as needed, then start the stack (applies ASSETS_MODE)
build build the images only
assets build the local assets image if missing
assets-rebuild force-rebuild the local assets image (honors ASSETS_MODE)
restart recreate web/workhorse/sidekiq
stop / down stop / remove containers (volumes kept)
logs tail web logs
ps stack status

Watch webpack rebuilds in hotreload mode: docker compose -f docker-compose.dev.yml logs -f assets-watch

Ports (CE and EE coexist)

CE EE
Browser / proxy 8182 8181
Workhorse (hotreload alt) 8183 8184
Dev server (internal only) 3808 3808

Notes / gotchas

  • The GitLab source trees are not modified. The stacks bind-mount source read-only where needed; the webpack-dev-server overlay tweak is applied via a CLI flag (--no-client-overlay-warnings), not by editing config/webpack.config.js. Generated config (config/gitlab.yml, etc.) is rendered by docker/docker-entrypoint.sh at container boot.
  • CSP is disabled in hotreload mode (dev-only) so the browser can load bundles same-origin.
  • First hotreload boot: give assets-watch ~1 min for its initial compile (assets 502 until done), then hard-refresh once so the browser picks up the current HMR client.
  • Switching modes with ./dev.sh up / make up cleans up the hotreload-only services so the host port is handed back to Workhorse.

See CLAUDE.md for an internals-oriented map of how the pieces fit together.