@@ -3,7 +3,7 @@ tags: [development, container]
33executables:
44 - verb: build
55 name: container
6- description: Build the flow container image
6+ description: Build the flow container image (single-arch, local testing)
77 aliases: [docker, image]
88 exec:
99 dir: //
@@ -24,6 +24,140 @@ executables:
2424 $BUILDER build -t $IMAGE_REPO:$IMAGE_TAG .
2525 rm flow
2626
27+ - verb: build
28+ name: multiarch
29+ description: Build multi-arch container images (linux/amd64, linux/arm64) using docker buildx
30+ aliases: [buildx]
31+ exec:
32+ dir: //
33+ args:
34+ - envKey: IMAGE_REPO
35+ default: ghcr.io/flowexec/flow
36+ flag: repo
37+ - envKey: IMAGE_TAG
38+ default: latest
39+ flag: tag
40+ - envKey: DRY_RUN
41+ default: "false"
42+ flag: dry-run
43+ cmd: |
44+ set -euo pipefail
45+
46+ # Check docker buildx is available
47+ if ! docker buildx version &> /dev/null; then
48+ echo "docker buildx is not available. Please install Docker with buildx support."
49+ exit 1
50+ fi
51+
52+ # Get version info for build args
53+ GIT_COMMIT=$(git rev-parse HEAD)
54+ BUILD_DATE=$(date -u +%Y-%m-%dT%H:%M:%SZ)
55+ VERSION="${IMAGE_TAG}"
56+
57+ # Create/use buildx builder instance
58+ BUILDER_NAME="flow-builder"
59+ if ! docker buildx inspect "$BUILDER_NAME" &> /dev/null; then
60+ echo "Creating buildx builder instance: $BUILDER_NAME"
61+ docker buildx create --name "$BUILDER_NAME" --use
62+ else
63+ docker buildx use "$BUILDER_NAME"
64+ fi
65+
66+ if [ "$DRY_RUN" = "true" ]; then
67+ echo "DRY RUN: Building multi-arch images locally (not pushing)"
68+ echo " Platforms: linux/amd64, linux/arm64"
69+ echo " Image: ${IMAGE_REPO}:${IMAGE_TAG}"
70+ echo ""
71+
72+ # Build multi-arch and load to local docker (note: can only load one platform at a time)
73+ # For local testing, we'll build for the current platform only
74+ CURRENT_OS=linux
75+ CURRENT_ARCH=$(uname -m)
76+ if [ "$CURRENT_ARCH" = "x86_64" ]; then CURRENT_ARCH="amd64"; fi
77+ if [ "$CURRENT_ARCH" = "aarch64" ] || [ "$CURRENT_ARCH" = "arm64" ]; then CURRENT_ARCH="arm64"; fi
78+
79+ echo "Building for ${CURRENT_OS}/${CURRENT_ARCH} (local platform)..."
80+
81+ # First build the flow binary with version info
82+ GOOS=linux GOARCH=${CURRENT_ARCH} go build \
83+ -ldflags="-s -w -X github.com/flowexec/flow/cmd/internal/version.gitCommit=${GIT_COMMIT} -X github.com/flowexec/flow/cmd/internal/version.version=${VERSION} -X github.com/flowexec/flow/cmd/internal/version.buildDate=${BUILD_DATE}" \
84+ -o flow
85+
86+ # Build Docker image for local platform
87+ docker buildx build \
88+ --platform "${CURRENT_OS}/${CURRENT_ARCH}" \
89+ --tag "${IMAGE_REPO}:${IMAGE_TAG}" \
90+ --load \
91+ .
92+
93+ # Cleanup binary
94+ rm -f flow
95+
96+ echo ""
97+ echo "✓ Multi-arch image built for local platform"
98+ echo " Platform: ${CURRENT_OS}/${CURRENT_ARCH}"
99+ echo " Image: ${IMAGE_REPO}:${IMAGE_TAG}"
100+ echo " Test with: docker run --rm ${IMAGE_REPO}:${IMAGE_TAG} --version"
101+ else
102+ echo "Building and pushing multi-arch images..."
103+ echo " Platforms: linux/amd64, linux/arm64"
104+ echo " Image: ${IMAGE_REPO}:${IMAGE_TAG}"
105+ echo ""
106+
107+ # Build binaries for both architectures
108+ echo "Building binaries for multi-arch..."
109+
110+ # Build amd64
111+ GOOS=linux GOARCH=amd64 go build \
112+ -ldflags="-s -w -X github.com/flowexec/flow/cmd/internal/version.gitCommit=${GIT_COMMIT} -X github.com/flowexec/flow/cmd/internal/version.version=${VERSION} -X github.com/flowexec/flow/cmd/internal/version.buildDate=${BUILD_DATE}" \
113+ -o flow-amd64
114+
115+ # Build arm64
116+ GOOS=linux GOARCH=arm64 go build \
117+ -ldflags="-s -w -X github.com/flowexec/flow/cmd/internal/version.gitCommit=${GIT_COMMIT} -X github.com/flowexec/flow/cmd/internal/version.version=${VERSION} -X github.com/flowexec/flow/cmd/internal/version.buildDate=${BUILD_DATE}" \
118+ -o flow-arm64
119+
120+ # Create temporary Dockerfile that uses TARGETARCH for multi-arch builds
121+ TEMP_DOCKERFILE=/tmp/Dockerfile.multiarch.$$
122+
123+ echo "FROM --platform=\$TARGETPLATFORM golang:1.25.1-bookworm" > "$TEMP_DOCKERFILE"
124+ echo "" >> "$TEMP_DOCKERFILE"
125+ echo "ARG TARGETARCH" >> "$TEMP_DOCKERFILE"
126+ echo 'ENV DISABLE_FLOW_INTERACTIVE="true"' >> "$TEMP_DOCKERFILE"
127+ echo "" >> "$TEMP_DOCKERFILE"
128+ echo "# TODO: replace with examples repo" >> "$TEMP_DOCKERFILE"
129+ echo 'ENV WORKSPACE="flow"' >> "$TEMP_DOCKERFILE"
130+ echo 'ENV REPO="https://github.com/flowexec/flow.git"' >> "$TEMP_DOCKERFILE"
131+ echo 'ENV BRANCH=""' >> "$TEMP_DOCKERFILE"
132+ echo "" >> "$TEMP_DOCKERFILE"
133+ echo "WORKDIR /workspaces" >> "$TEMP_DOCKERFILE"
134+ echo "" >> "$TEMP_DOCKERFILE"
135+ echo "# Copy the appropriate binary based on architecture" >> "$TEMP_DOCKERFILE"
136+ echo 'COPY flow-${TARGETARCH} /usr/bin/flow' >> "$TEMP_DOCKERFILE"
137+ echo "" >> "$TEMP_DOCKERFILE"
138+ echo 'RUN if [ -z "$BRANCH" ]; then git clone $REPO .; else git clone -b $BRANCH $REPO .; fi' >> "$TEMP_DOCKERFILE"
139+ echo 'RUN flow workspace create $WORKSPACE . --set' >> "$TEMP_DOCKERFILE"
140+ echo "" >> "$TEMP_DOCKERFILE"
141+ echo 'ENTRYPOINT ["flow"]' >> "$TEMP_DOCKERFILE"
142+ echo 'CMD ["--version"]' >> "$TEMP_DOCKERFILE"
143+
144+ # Build and push multi-arch image
145+ docker buildx build \
146+ --platform linux/amd64,linux/arm64 \
147+ --tag "${IMAGE_REPO}:${IMAGE_TAG}" \
148+ --tag "${IMAGE_REPO}:latest" \
149+ --push \
150+ --file "$TEMP_DOCKERFILE" \
151+ .
152+
153+ # Cleanup
154+ rm -f flow-amd64 flow-arm64 "$TEMP_DOCKERFILE"
155+
156+ echo ""
157+ echo "✓ Multi-arch images pushed to ${IMAGE_REPO}"
158+ echo " Tags: ${IMAGE_TAG}, latest"
159+ fi
160+
27161 - verb: run
28162 name: container
29163 description: Run the flow container image
@@ -63,7 +197,7 @@ executables:
63197
64198 - verb: push
65199 name: container
66- description: Push the flow container image to the registry
200+ description: Push the flow container image to the registry (use with build multiarch for production)
67201 aliases: [image, docker]
68202 exec:
69203 dir: //
@@ -77,6 +211,15 @@ executables:
77211 - envKey: IMAGE_TAG
78212 default: latest
79213 flag: tag
214+ - envKey: DRY_RUN
215+ default: "false"
216+ flag: dry-run
80217 cmd: |
218+ if [ "$DRY_RUN" = "true" ]; then
219+ echo "DRY RUN: Would push ${IMAGE_REPO}:${IMAGE_TAG}"
220+ echo "Skipping actual push to registry"
221+ exit 0
222+ fi
223+
81224 echo "pushing container image..."
82225 $BUILDER push $IMAGE_REPO:$IMAGE_TAG
0 commit comments