Docker & Network
Network topology#
Three network layers exist at runtime:
| Network | Scope | Containers | Purpose |
|---|---|---|---|
| glci-net-{pipelineID} | Per pipeline | glci-mock, glci-runner, glci-runner-<project> (if any) | Runners poll mock for jobs via Docker DNS (glci-mock:39741) |
| Per-build network | Per job | Job container, service sidecars | Service DNS aliases (postgres, redis, etc.) |
| glci-net-{pipelineID}-job-{jobID} | Per DinD job | DinD job, docker:dind, glci-mock (attached) | Isolates DinD docker alias; gives DinD access to the embedded registry |
How each component reaches the mock server:
- Runners → Docker DNS on the pipeline network (
glci-mock:39741). The sharedglci-runnerholds N[[runners]]blocks from aconfig_template— each polls independently with its own HMAC-derived token. Per-project runners (glci-runner-<project>) are separate containers on the same network. - Job containers →
extra_hostsmappinghost.docker.internalto the Docker host gateway, then the published host port (default39741) - DinD daemons →
glci-mockis attached to the per-job DinD network, configured viainsecure-registriesindaemon.json - Daemon →
docker exec -iwith muxproto binary framing over stdin/stdout (works with local and remote Docker)
Docker host configuration#
Configure the Docker daemon endpoint in ~/.glci/config.toml:
# ~/.glci/config.toml
[docker]
host = "tcp://remote-host:2375" # or "ssh://remote-host"
container_socket = "/var/run/docker.sock"
privileged = true # default; set false to disable --privileged
Supported schemes for host:
unix:///var/run/docker.sock– local Docker socket (default)tcp://remote-host:2375– TCP connection to a remote Docker daemonssh://remote-host– SSH tunnel to a remote Docker daemon
The container_socket setting controls the Docker socket path mounted inside runner containers. This is auto-detected by default but may need manual configuration when the Docker daemon uses a non-standard socket path.
Set privileged = false to disable the --privileged flag on runner containers. This may be required on some security-hardened systems, but will break Docker-in-Docker pipelines.
Docker-in-Docker#
For CI pipelines that use Docker-in-Docker services (docker:dind), glci automatically:
- Mounts the Docker socket for DinD service containers
- Injects a
buildkitd.tomlmarking the mock registry as insecure (HTTP) - Fixes wrong-architecture buildx plugins (e.g. CI downloads amd64 binary but container is arm64)
- Registers QEMU binfmt handlers for cross-platform builds
- Configures every pipeline’s DinD as a pull-through mirror of the embedded registry
- Wraps
docker buildx createto inject--config(registry trust) and--driver-opt network=(pipeline DNS)
Build layer cache#
glci does not inject BuildKit cache flags automatically. Use --cache-from / --cache-to in your .gitlab-ci.yml as you would on GitLab CI. Since the embedded registry persists across runs, type=registry cache references work without extra setup.
Network configuration#
Fine-tune how containers reach the mock server, registry, and host services:
# ~/.glci/config.toml
[network]
mock_server_bind = "0.0.0.0:0" # mock server listen address (default)
mock_server_port = 39741 # host port for mock server (default); change requires daemon restart
container_host = "host.docker.internal" # hostname containers use for host (default)
host_gateway = "auto" # extra_hosts value for container_host (default)
registry_bind = "127.0.0.1:0" # registry HTTPS listener (default)
registry_http_bind = "0.0.0.0:0" # registry HTTP listener (default)
daemon_socket = "~/.glci/daemon.sock" # Unix socket path (default)
[network.extra_hosts]
entries = ["internal-registry.corp:10.0.0.50"] # additional /etc/hosts entries for containers
The container_host defaults to host.docker.internal, which resolves natively on Docker Desktop (macOS/Windows) and on Linux Docker 20.10+. On older Linux, glci adds an extra_hosts entry mapping it to the Docker bridge IP.
The mock_server_port is the host port that CI job containers use to reach the mock server via Docker’s host-gateway. This port must be available on every Docker host where glci runs. Changing it requires a full daemon restart (glci daemon stop && glci daemon start).
Use glci config --network to see all resolved network settings:
glci config --network
CI cache#
GitLab CI cache: keywords work the same as production, including key: files: (MD5-based), prefix:, and fallback_keys:. Entries persist across pipeline runs via daemon-managed disk storage on the glci-cache Docker volume.
[cache]
persistent = true # default; set false to disable
max_size = "500MB" # reject uploads when exceeded (default: 500MB)
ttl = "24h" # entry expiry (default: 24h)
glci system cache clean # wipe all CI cache entries
Setting persistent = false disables cross-pipeline caching entirely; each pipeline starts with cold caches.
System management#
# Disk usage of all glci resources
glci system df
# Remove unused containers, networks, volumes, and CI cache
glci system prune
# Remove everything including registry data and pipeline history
glci system prune --all
# Skip the confirmation prompt
glci system prune --force
# Manage daemon logs
glci system logs info # show log file path and size
glci system logs clean # remove the log file
# Inspect Docker resources
glci system docker containers
glci system docker networks
glci system docker volumes
glci system prune (without --all) removes stopped containers, unused networks, orphaned volumes, the bare repo cache, and the daemon log. Persistent daemon volumes (CI cache, registry storage, registry CA) are preserved.
glci system prune --all additionally removes registry data, pipeline history, and all persistent volumes. The daemon is automatically stopped and restarted if it was running.
Daemon#
The daemon runs automatically — you rarely need these commands:
glci daemon status # show PID, uptime, active pipelines, commit
glci daemon stop # graceful shutdown (waits for running jobs)
glci daemon start # manually start
glci daemon logs # show last 50 lines
glci daemon logs -F # follow in real time
glci daemon logs -n 100 # show last 100 lines
The daemon auto-stops after 30 minutes of idle (configurable via [daemon] idle_timeout). After make install, the next CLI invocation automatically restarts the daemon if built from a different commit.
Configure daemon settings in ~/.glci/config.toml:
[daemon]
idle_timeout = "1h" # default: 30m
socket = "~/.glci/daemon.sock"
log_file = "~/.glci/daemon.log"
max_log_size = "50MB" # rotate when log exceeds this size (default: 50MB, "0" to disable)
max_log_files = 3 # rotated backups to keep (default: 3)
Log rotation happens at daemon startup. When daemon.log exceeds max_log_size, it is renamed to daemon.log.1 (shifting older backups up to .N), and a fresh log is started. Set max_log_size = "0" to disable rotation.
Crash recovery#
On startup the daemon checks for pipelines whose Docker containers survived the crash. If both the mock server and runner containers are still alive, the daemon resumes execution — re-attaching to running jobs and dispatching pending ones. Pipelines whose containers died are marked as failed. Orphaned containers are cleaned up automatically.
Version#
glci version
# glci commit abc123def456...
# daemon commit abc123def456... (pid 12345, up 2h15m)