Docker Support
This document describes Structyl's Docker integration.
Overview
Structyl supports running builds inside Docker containers, providing:
- Reproducible builds across environments
- No need to install language toolchains locally
- Isolation between different language runtimes
- CI/local build parity
Enabling Docker Mode
Command Line Flag
structyl build cs --docker
structyl test --docker
structyl ci --dockerEnvironment Variable
export STRUCTYL_DOCKER=1
structyl build # Runs in DockerOr per-command:
STRUCTYL_DOCKER=1 structyl buildActivation Precedence
| Condition | Docker Mode |
|---|---|
--docker flag present | Enabled |
--no-docker flag present | Disabled (overrides env var) |
STRUCTYL_DOCKER = 1, true, yes (case-insensitive) | Enabled |
STRUCTYL_DOCKER = 0, false, no | Disabled |
STRUCTYL_DOCKER unset or empty | Disabled |
STRUCTYL_DOCKER = other value | Warning emitted; disabled |
Command-line flags take precedence over environment variables. The --no-docker flag explicitly disables Docker mode even if STRUCTYL_DOCKER is set.
Docker Compose Configuration
Structyl uses Docker Compose to manage containers. The compose file can be:
- Auto-generated by Structyl (default)
- User-provided for custom configuration
Auto-Generated Compose File
If no docker-compose.yml exists, Structyl generates one based on .structyl/config.json:
# Auto-generated by Structyl
services:
cs:
build:
context: .
dockerfile: cs/Dockerfile
volumes:
- ./cs:/workspace/cs
- ./tests:/workspace/tests:ro
working_dir: /workspace/cs
py:
build:
context: .
dockerfile: py/Dockerfile
volumes:
- ./py:/workspace/py
- ./tests:/workspace/tests:ro
working_dir: /workspace/pyUser-Provided Compose File
Place a docker-compose.yml at project root. Structyl will use it instead of generating one.
Dockerfile Templates
Each target needs a Dockerfile. Options:
1. Built-in Templates (Default)
Structyl provides default Dockerfiles for common languages:
| Language | Base Image |
|---|---|
| C# | mcr.microsoft.com/dotnet/sdk:8.0 |
| Go | golang:1.22 |
| Kotlin | gradle:8-jdk21 |
| Python | python:3.12-slim |
| R | rocker/verse:latest |
| Rust | rust:1.75 |
| TypeScript | node:20-slim |
2. Custom Dockerfile
Place a Dockerfile in the target directory:
cs/
├── Dockerfile # Custom Dockerfile
└── MyProject.csprojCustom Dockerfile takes precedence over built-in template.
3. Configuration Override
Specify in .structyl/config.json:
{
"docker": {
"services": {
"cs": {
"base_image": "mcr.microsoft.com/dotnet/sdk:9.0",
"dockerfile": "docker/cs.Dockerfile"
}
}
}
}Volume Mounts
Standard volume mounts:
| Mount | Purpose |
|---|---|
./<target>:/workspace/<target> | Target source code (read-write) |
./tests:/workspace/tests:ro | Test data (read-only) |
./.structyl/config.json:/workspace/.structyl/config.json:ro | Configuration (read-only) |
Cache Volumes
To avoid permission conflicts, use separate cache directories for Docker:
services:
cs:
volumes:
- ./cs/.nuget-docker:/tmp/.nuget
rs:
volumes:
- ./rs/.cargo-docker:/tmp/.cargoAdd to .gitignore:
**/.nuget-docker
**/.cargo-docker
**/.cache-dockerPlatform Considerations
ARM64 (Apple Silicon)
Some images don't support ARM64. Specify platform explicitly:
{
"docker": {
"services": {
"r": {"platform": "linux/amd64"},
"pdf": {"platform": "linux/amd64"}
}
}
}Docker Desktop uses Rosetta for emulation.
User Mapping
Structyl maps the container user to avoid root-owned files on the host.
| Platform | Behavior |
|---|---|
| Linux | Run as host user: --user "$(id -u):$(id -g)" |
| macOS | Run as host user: --user "$(id -u):$(id -g)" |
| Windows | Run as default container user (user mapping not supported) |
On Unix systems, the equivalent command is:
docker compose run --rm --user "$(id -u):$(id -g)" cs bash -c "dotnet build"On Windows, user mapping is omitted:
docker compose run --rm cs powershell -Command "dotnet build"Note: On Windows, files created in containers may be owned by root. Use separate cache directories (see "Cache Volumes" above) to mitigate permission issues.
Docker Commands
Build Images
structyl docker-build # Build all images
structyl docker-build cs py # Build specific imagesClean Docker Resources
structyl docker-clean # Remove containers, images, volumesExample Dockerfiles
C# (.NET)
FROM mcr.microsoft.com/dotnet/sdk:8.0
WORKDIR /workspace/cs
ENV DOTNET_CLI_TELEMETRY_OPTOUT=1
ENV NUGET_PACKAGES=/tmp/.nugetPython
FROM python:3.12-slim
WORKDIR /workspace/py
RUN pip install --upgrade pipRust
FROM rust:1.75
WORKDIR /workspace/rs
ENV CARGO_HOME=/tmp/.cargoGo
FROM golang:1.22
WORKDIR /workspace/go
ENV GOCACHE=/tmp/.cache
ENV GOPATH=/tmp/goConfiguration Reference
{
"docker": {
"compose_file": "docker-compose.yml",
"env_var": "STRUCTYL_DOCKER",
"services": {
"<target>": {
"base_image": "image:tag",
"dockerfile": "path/to/Dockerfile",
"platform": "linux/amd64",
"volumes": ["additional:/mounts"]
}
}
}
}| Field | Description | Default |
|---|---|---|
compose_file | Path to compose file | docker-compose.yml |
env_var | Env var to enable Docker mode | STRUCTYL_DOCKER |
services.<target>.base_image | Base Docker image | Language-specific |
services.<target>.dockerfile | Custom Dockerfile path | <target>/Dockerfile |
services.<target>.platform | Target platform | Host platform |
services.<target>.volumes | Additional volume mounts | [] |
Troubleshooting
Permission Denied
If files are owned by root after Docker build:
- Ensure user mapping is enabled
- Use separate cache directories (e.g.,
.nuget-docker)
Image Not Found
structyl docker-build # Rebuild all imagesSlow Builds on Apple Silicon
ARM64 emulation is slow. Options:
- Use native ARM64 images where available
- Accept slower builds for x64-only tools
- Use native builds for development, Docker for CI only