Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .docker/.cli-version
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
v1.5.0
5 changes: 5 additions & 0 deletions .docker/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# Build artifacts
dist/

# Docker compose logs
docker-compose.log
100 changes: 100 additions & 0 deletions .docker/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
CLI_VERSION := $(shell cat .cli-version)
TEMPORAL_SHA := $(shell cd .. && git rev-parse HEAD)
IMAGE_SHA_TAG := sha-$(shell cd .. && git rev-parse --short HEAD)
IMAGE_BRANCH_TAG := branch-$(shell cd .. && git rev-parse --abbrev-ref HEAD)
IMAGE_REPO ?= ghcr.io/chaptersix

DOCKER := docker buildx
BAKE := cd .. && IMAGE_SHA_TAG=$(IMAGE_SHA_TAG) \
IMAGE_BRANCH_TAG=$(IMAGE_BRANCH_TAG) \
TEMPORAL_SHA=$(TEMPORAL_SHA) \
IMAGE_REPO=$(IMAGE_REPO) \
$(DOCKER) bake -f .docker/docker-bake.hcl
NATIVE_ARCH := $(shell go env GOARCH)
BAKE_OUTPUT ?= docker

.PHONY: all
all: prepare-bins build-native

.PHONY: prepare-bins
prepare-bins: goreleaser-bins download-cli organize-bins

.PHONY: goreleaser-bins
goreleaser-bins:
@echo "Building binaries with goreleaser..."
@cd .. && goreleaser build --snapshot --clean \
--id temporal-server \
--id temporal-cassandra-tool \
--id temporal-sql-tool \
--id temporal-elasticsearch-tool \
--id tdbg

.PHONY: download-cli
download-cli:
@echo "Downloading temporal CLI ${CLI_VERSION}..."
@mkdir -p dist/tmp
@for arch in amd64 arm64; do \
echo "Downloading for linux/$$arch..."; \
VERSION=$$(echo ${CLI_VERSION} | sed 's/^v//'); \
curl -fsSL "https://github.com/temporalio/cli/releases/download/${CLI_VERSION}/temporal_cli_$${VERSION}_linux_$$arch.tar.gz" | \
tar -xzf - -C dist/tmp && \
mkdir -p dist/$$arch && \
mv dist/tmp/temporal dist/$$arch/temporal; \
done
@rm -rf dist/tmp

.PHONY: organize-bins
organize-bins:
@echo "Organizing binaries for Docker..."
@mkdir -p dist/amd64 dist/arm64
@echo "Copying amd64 binaries..."
@for binary in temporal-server temporal-cassandra-tool temporal-sql-tool temporal-elasticsearch-tool tdbg; do \
find ../dist -type f -name "$$binary" | grep linux_amd64 | xargs -I {} cp -v {} dist/amd64/ ; \
done
@echo "Copying arm64 binaries..."
@for binary in temporal-server temporal-cassandra-tool temporal-sql-tool temporal-elasticsearch-tool tdbg; do \
find ../dist -type f -name "$$binary" | grep linux_arm64 | xargs -I {} cp -v {} dist/arm64/ ; \
done
@echo "Verifying binaries..."
@ls -lh dist/amd64/ || echo "Warning: No amd64 binaries found"
@ls -lh dist/arm64/ || echo "Warning: No arm64 binaries found"

.PHONY: build-native
build-native: prepare-bins
@echo "Building native Docker images..."
$(BAKE) --set "*.platform=linux/$(NATIVE_ARCH)" --load

.PHONY: build
build: prepare-bins
@echo "Building multi-arch Docker images..."
$(BAKE) --set="*.output=type=$(BAKE_OUTPUT)"

.PHONY: test
test:
@echo "Testing Docker images..."
IMAGE_SHA_TAG=$(IMAGE_SHA_TAG) IMAGE_REPO=$(IMAGE_REPO) ./scripts/test.sh

.PHONY: clean
clean:
@echo "Cleaning build artifacts..."
rm -rf dist/
rm -rf ../dist/

.PHONY: help
help:
@echo "Temporal Docker Build Makefile"
@echo ""
@echo "Targets:"
@echo " all - Build binaries and native Docker images (default)"
@echo " prepare-bins - Build binaries with goreleaser and download CLI"
@echo " goreleaser-bins - Build Temporal binaries with goreleaser"
@echo " download-cli - Download Temporal CLI from GitHub releases"
@echo " organize-bins - Organize binaries for Docker build"
@echo " build-native - Build Docker images for native architecture"
@echo " build - Build multi-arch Docker images"
@echo " test - Test Docker images"
@echo " clean - Clean build artifacts"
@echo ""
@echo "Environment Variables:"
@echo " IMAGE_REPO - Docker image repository (default: ghcr.io/chaptersix)"
@echo " BAKE_OUTPUT - Docker output type: docker or registry (default: docker)"
218 changes: 218 additions & 0 deletions .docker/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
# Temporal Docker Build System

This directory contains everything needed to build Temporal's Docker images using goreleaser and GHCR.

## Overview

The build system creates two main Docker images:
- **server**: Contains temporal-server and temporal CLI
- **admin-tools**: Contains temporal CLI, tdbg, and database tools (cassandra-tool, sql-tool, elasticsearch-tool)

## Local Development

### Prerequisites
- Docker with buildx support
- Go 1.21+
- goreleaser (`brew install --cask goreleaser`)
- make

### Building Images Locally

```bash
cd .docker

# Build native architecture images (fast)
make build-native

# Build multi-arch images (amd64 + arm64)
make build

# Test images
make test

# Clean build artifacts
make clean
```

### Manual Build Steps

```bash
# 1. Build binaries with goreleaser
make goreleaser-bins

# 2. Download temporal CLI from GitHub releases
make download-cli

# 3. Organize binaries for Docker
make organize-bins

# 4. Build Docker images
make build-native
```

## CI/CD Workflows

### Automatic Builds

The `.github/workflows/docker-build.yml` workflow automatically builds and pushes images to GHCR on:
- Push to `main` branch
- Push to `test/*`, `cloud/*`, `feature/*`, `release/*` branches
- Pull requests (build only, no push)

**Images are tagged with:**
- `sha-<commit>` (e.g., `sha-abc1234`)
- `branch-<branch-name>` (e.g., `branch-main`)
- `latest` (only for main branch)

### Manual Releases

Use `.github/workflows/release-docker-images.yml` to promote images to production:

```bash
# Promote a pre-built image to release registry
# Input: commit SHA (first 7 chars), version tag, flags for latest/major
```

### Base Image Updates

Use `.github/workflows/release-base-images.yml` to build new base images when dependencies change.

## Directory Structure

```
.docker/
├── base-images/ # Base image Dockerfiles
│ ├── base-server.Dockerfile
│ └── base-admin-tools.Dockerfile
├── server.Dockerfile # Server image
├── admin-tools.Dockerfile # Admin tools image
├── docker-bake.hcl # Docker buildx bake configuration
├── scripts/ # Runtime scripts
│ ├── entrypoint.sh
│ ├── start-temporal.sh
│ └── test.sh
├── dist/ # Build output (gitignored)
│ ├── amd64/ # Linux amd64 binaries
│ └── arm64/ # Linux arm64 binaries
├── .cli-version # Temporal CLI version to download
├── docker-compose.yml # Testing compose file
├── Makefile # Build automation
└── README.md # This file
```

## Configuration

### Temporal CLI Version

Update `.cli-version` to change which temporal CLI version is downloaded:

```bash
echo "v1.6.0" > .cli-version
```

### Image Registry

The default registry is `ghcr.io/chaptersix` for testing. To change:

**In docker-bake.hcl:**
```hcl
variable "IMAGE_REPO" {
default = "ghcr.io/your-org" # or "dockerhub-username"
}
```

**In workflows:**
Update the `IMAGE_REPO` environment variable or registry login steps.

## Testing

### Local Testing

```bash
# Build and test
make build-native test

# Run specific tests
docker run --rm ghcr.io/chaptersix/server:sha-test temporal-server --version
docker run --rm ghcr.io/chaptersix/admin-tools:sha-test temporal --version
```

### Integration Testing

Use docker-compose for integration tests:

```bash
IMAGE_SHA_TAG=sha-test docker compose up -d
docker compose exec admin-tools temporal operator cluster health
docker compose down
```

## Goreleaser Configuration

The build uses `../.goreleaser.yml` to build temporal binaries:
- temporal-server
- temporal-cassandra-tool
- temporal-sql-tool
- temporal-elasticsearch-tool
- tdbg

**Note:** The goreleaser config was updated to v2 format. Key changes:
- Added `version: 2` at the top
- Changed `changelog.skip` to `changelog.disable`

## Troubleshooting

### Goreleaser build fails
```bash
# Check goreleaser version
goreleaser --version

# Validate config
goreleaser check
```

### Binaries not found in Docker build
```bash
# Check organized binaries
ls -la dist/amd64/ dist/arm64/

# Manually run organize-bins
make organize-bins
```

### CLI download fails
```bash
# Check version in .cli-version
cat .cli-version

# Verify release exists
curl -I https://github.com/temporalio/cli/releases/download/$(cat .cli-version)/temporal_cli_$(cat .cli-version | sed 's/^v//')_linux_amd64.tar.gz
```

### Docker build context errors
The Dockerfiles expect to be run from the temporal repo root, not from `.docker/`.
The Makefile handles this automatically with `cd ..`.

## Migration Notes

This docker build system replaces the docker-builds repository approach:

**Old approach:**
- Separate docker-builds repo with submodules
- Built CLI and tctl from source
- Cross-repo workflow triggers

**New approach:**
- Everything in temporal repo
- Downloads CLI from releases
- No tctl (deprecated)
- Uses goreleaser for all temporal binaries
- Simpler, single-repo workflow

## Contributing

When making changes:
1. Test locally with `make build-native test`
2. Verify goreleaser config still works
3. Update this README if adding new features
4. Check that both amd64 and arm64 builds work
23 changes: 23 additions & 0 deletions .docker/admin-tools.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
ARG BASE_ADMIN_TOOLS_IMAGE=temporalio/base-admin-tools:1.12.12

FROM ${BASE_ADMIN_TOOLS_IMAGE} as temporal-admin-tools
ARG TARGETARCH

# Essential binaries only
COPY ./.docker/dist/${TARGETARCH}/temporal /usr/local/bin/
COPY ./.docker/dist/${TARGETARCH}/tdbg /usr/local/bin/
COPY ./.docker/dist/${TARGETARCH}/temporal-cassandra-tool /usr/local/bin/
COPY ./.docker/dist/${TARGETARCH}/temporal-sql-tool /usr/local/bin/
COPY ./.docker/dist/${TARGETARCH}/temporal-elasticsearch-tool /usr/local/bin/
COPY ./schema /etc/temporal/schema

# Setup bash completion
RUN apk add bash-completion && \
temporal completion bash > /etc/bash/temporal-completion.sh && \
addgroup -g 1000 temporal && \
adduser -u 1000 -G temporal -D temporal

USER temporal
WORKDIR /etc/temporal

ENTRYPOINT ["tini", "--", "sleep", "infinity"]
38 changes: 38 additions & 0 deletions .docker/base-images/base-admin-tools.Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
ARG BASE_IMAGE=alpine:3.22

FROM ${BASE_IMAGE} AS builder

# These are necessary to install cqlsh
RUN apk add --update --no-cache \
python3-dev \
musl-dev \
libev-dev \
gcc \
pipx

RUN pipx install --global cqlsh

FROM ${BASE_IMAGE} AS base-admin-tools

RUN apk upgrade --no-cache
RUN apk add --no-cache \
python3 \
libev \
ca-certificates \
tzdata \
bash \
curl \
jq \
yq \
mysql-client \
postgresql-client \
expat \
tini

COPY --from=builder /opt/pipx/venvs/cqlsh /opt/pipx/venvs/cqlsh
RUN ln -s /opt/pipx/venvs/cqlsh/bin/cqlsh /usr/local/bin/cqlsh

# validate cqlsh installation
RUN cqlsh --version

SHELL ["/bin/bash", "-c"]
Loading
Loading