Build Strategy
Dockflow supports different strategies for building and transferring Docker images to your servers.
Strategies Overview
| Strategy | Build Location | Transfer Method | Best For |
|---|---|---|---|
| Local (default) | CI/CD runner | SSH streaming | Single-node, small clusters |
| Local + Registry | CI/CD runner | Docker registry | Large multi-node clusters |
| Remote | Target server | None (built in place) | Large contexts, slow networks |
Local Build (Default)
Images are built in your CI/CD pipeline and transferred to the server via SSH. No additional configuration required.
How it works:
- Dockflow parses
docker-compose.ymlto extract build commands - Images are built locally (in parallel if multiple services)
- Images are streamed to all Swarm nodes via SSH:
docker save IMAGE | gzip -1 | ssh user@host "gunzip | docker load"
This is the simplest strategy and works for both single-node deployments and multi-node clusters. For larger clusters with many nodes or heavy images, consider using a registry instead.
Multiple images are built in parallel automatically. Build times are displayed per-service after completion.
Registry Build
For larger multi-node Swarm clusters, use a Docker registry so all nodes can pull images independently. This avoids streaming large images over SSH to each node individually.
How it works:
- Images are built locally (same as default)
- Images are pushed to your configured registry
- During
docker stack deploy, each Swarm node pulls the image from the registry
See Docker Registry for full configuration (GHCR, GitLab, Docker Hub, self-hosted).
When to use:
- Large multi-node clusters where SSH streaming becomes a bottleneck
- When you want image versioning in a registry
- CI/CD pipelines with native registry support
Remote Build
Build images directly on the server instead of transferring them:
# .dockflow/config.yml
options:
remote_build: trueHow it works:
- Dockflow clones your repository on the target server (supports Git token authentication)
- Images are built directly on the server
- No image transfer needed — images are already where they need to be
For private repositories, add a GIT_TOKEN secret to your CI/CD environment. Dockflow auto-constructs authenticated URLs for GitHub and GitLab.
When to use:
- Large build contexts that would be slow to transfer
- Slow network connections between CI/CD and server
- When the server has more build resources than your CI runner
Remote builds prune the Docker builder cache after each build to free disk space. Docker’s layer cache still works within a single build but is not preserved across deployments.
Trade-Offs
| Local | Local + Registry | Remote | |
|---|---|---|---|
| Setup complexity | None | Registry config needed | Git access on server |
| Network usage | SSH stream per node | Single push, nodes pull | Git clone only |
| Build cache | Full local cache | Full local cache | Pruned between deploys |
| Multi-node | Streaming to each node | Native Swarm pull | Streaming to workers |
| CI resources | Needs Docker on runner | Needs Docker on runner | Minimal CI resources |
| Private repos | N/A | N/A | Needs GIT_TOKEN |
Build-Only Mode
Use dockflow build to build images without deploying:
dockflow build production # Build all services
dockflow build production --services app # Build specific service
dockflow build production --push # Build and push to registryThis is useful for validating builds in CI before deploying, or for pre-building images.
Docker Cache
Docker caches image layers by default. When nothing changes in your source code or Dockerfile, subsequent builds reuse cached layers and complete in seconds.
To maximize cache efficiency:
- Order Dockerfile instructions from least to most frequently changing
- Copy dependency files (
package.json,requirements.txt) before source code - Use multi-stage builds to separate build and runtime dependencies
# Example: good cache utilization
FROM node:20-alpine AS build
WORKDIR /app
COPY package.json package-lock.json ./ # Changes rarely
RUN npm ci # Cached if lockfile unchanged
COPY . . # Changes often
RUN npm run build
FROM node:20-alpine
COPY --from=build /app/dist ./dist
COPY --from=build /app/node_modules ./node_modules
CMD ["node", "dist/index.js"]Next: Deployment — understand what happens when you deploy.