Deployment
Building images
Build Docker images locally or on remote hosts.
Build strategies
Odysseus supports two build strategies:
- Local: Build on the machine running Odysseus
- Remote: Build on a dedicated build server via SSH
Local builds
Build images on your local machine:
builder:
strategy: local
arch: amd64
Run the build:
odysseus build --image v1.0.0
Configuration options
builder:
strategy: local
arch: amd64
dockerfile: Dockerfile
context: .
build_args:
RUBY_VERSION: "3.2"
NODE_VERSION: "20"
cache: true
arch
Target architecture: amd64 or arm64.
dockerfile
Path to Dockerfile (default: Dockerfile).
context
Build context directory (default: .).
build_args
Build-time arguments:
builder:
build_args:
RUBY_VERSION: "3.2"
BUNDLER_VERSION: "2.4.0"
cache
Enable Docker build cache (default: true).
Remote builds
Build on a dedicated server for faster builds or specific architectures:
builder:
strategy: remote
host: build-server.example.com
arch: amd64
Why remote builds?
- Faster CI: CI runners often have limited resources
- Architecture matching: Build for the target architecture
- Consistent environment: Same build environment every time
- Preserve cache: Build cache persists between runs
Remote build process
- Source files are synced to the build server
- Docker build runs on the remote host
- Image is tagged and ready for distribution
odysseus build --image v1.0.0
# Syncs files to build-server.example.com
# Runs docker build remotely
# Image available on build server
Push to registry
Push the built image to a Docker registry:
odysseus build --image v1.0.0 --push
Requires registry configuration:
registry:
server: ghcr.io
username: myuser
password: ${GITHUB_TOKEN}
Build and deploy
Combine building and deployment:
odysseus deploy --build --image v1.0.0
This:
- Builds the image
- Distributes to servers (push to registry or direct transfer)
- Deploys with zero-downtime
Direct transfer (pussh)
Transfer images directly to servers without a registry:
odysseus pussh --image v1.0.0
Or build and transfer:
odysseus pussh --build --image v1.0.0
How pussh works
- Image is saved as a tarball
- Tarball is streamed over SSH to each server
- Server loads the image into Docker
This is useful when:
- You don't have a Docker registry
- You want to avoid registry latency
- You're deploying to a single server
Multi-architecture builds
Build for multiple architectures:
builder:
strategy: local
multiarch: true
platforms:
- linux/amd64
- linux/arm64
Docker Buildx
Multi-architecture builds require Docker Buildx. It's included in Docker Desktop and can be installed separately on Linux.
Build context
.dockerignore
Create a .dockerignore file to exclude files from the build context:
.git
node_modules
tmp
log
.env*
*.md
This speeds up builds and reduces image size.
Custom context
Specify a custom build context:
builder:
context: ./app
dockerfile: ./docker/Dockerfile.production
Dockerfile tips
Multi-stage builds
Use multi-stage builds for smaller images:
# Build stage
FROM ruby:3.2 AS builder
WORKDIR /app
COPY Gemfile* ./
RUN bundle install
# Production stage
FROM ruby:3.2-slim
WORKDIR /app
COPY --from=builder /usr/local/bundle /usr/local/bundle
COPY . .
CMD ["rails", "server", "-b", "0.0.0.0"]
Health checks
Add a health check to your Dockerfile:
HEALTHCHECK --interval=10s --timeout=5s --start-period=30s \
CMD curl -f http://localhost:3000/health || exit 1
Odysseus uses this to verify containers are ready before routing traffic.
CLI reference
odysseus build
odysseus build [options]
Options:
--config FILE: Configuration file (default:deploy.yml)--image TAG: Image tag--push: Push to registry after build--context PATH: Build context path--verbose: Show detailed output
odysseus pussh
odysseus pussh [options]
Options:
--config FILE: Configuration file--image TAG: Image tag--build: Build before pushing--verbose: Show detailed output