Skip to content

Commit cb47f53

Browse files
committed
Building docker images for both architectures
1 parent 6a05054 commit cb47f53

5 files changed

Lines changed: 206 additions & 22 deletions

File tree

docker/README.md

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -14,21 +14,58 @@ docker pull ghcr.io/openmined/bioscript:0.1.0
1414

1515
Images are automatically built and pushed on every commit to main and on releases.
1616

17-
## Building Locally
17+
## Building
18+
19+
### Local (single architecture)
1820

1921
From the repository root:
2022

2123
```bash
2224
docker build -f docker/Dockerfile -t bioscript:0.1.0 .
2325
```
2426

25-
Or use the build script:
27+
### Multi-architecture (amd64 + arm64)
28+
29+
The build script runs Docker Buildx once to generate a multi-architecture manifest for both `linux/amd64` and `linux/arm64`.
30+
31+
```bash
32+
./docker/build.sh 0.1.0
33+
```
34+
35+
By default the manifest is pushed to GitHub Container Registry. Switch to a local OCI archive by setting `OUTPUT_MODE=oci` (the archive is written to `docker/dist/bioscript-<version>.oci.tar` unless `OUTPUT_DEST` is provided):
36+
37+
```bash
38+
OUTPUT_MODE=oci ./docker/build.sh 0.1.0
39+
```
40+
41+
After building you can inspect the manifest to confirm both platforms are present:
2642

2743
```bash
28-
cd docker
29-
./build.sh
44+
docker buildx imagetools inspect ghcr.io/openmined/bioscript:0.1.0
3045
```
3146

47+
Environment knobs:
48+
49+
- `OUTPUT_MODE=push|oci` (default `push`)
50+
- `OUTPUT_DEST=path/to/archive.tar` when `OUTPUT_MODE=oci`
51+
- `LOAD_PLATFORM=linux/amd64|linux/arm64|none` (default `auto`, meaning match the host). The script always executes the multi-arch build first, then optionally loads one platform locally for quick testing.
52+
53+
> **Note:** Run `docker login ghcr.io` before using `OUTPUT_MODE=push`.
54+
55+
### Local architecture-specific tests
56+
57+
To build and exercise the container for a single architecture without pushing to GHCR, use the helper scripts in the repository root:
58+
59+
```bash
60+
# On x86_64 hosts
61+
./test_docker_amd64.sh
62+
63+
# On arm64 hosts (including Apple Silicon)
64+
./test_docker_arm64.sh
65+
```
66+
67+
These scripts perform the multi-arch build, load the host architecture locally, and exercise the classifier with `docker run --platform=<arch> ...`.
68+
3269
## Usage
3370

3471
### Run a classifier

docker/build.sh

Lines changed: 124 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
#!/bin/bash
2-
set -e
2+
set -euo pipefail
33

44
# Build BioScript Docker image
55
#
@@ -10,27 +10,136 @@ set -e
1010
SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
1111
cd "$SCRIPT_DIR/.."
1212

13+
PLATFORMS=${PLATFORMS:-linux/amd64,linux/arm64}
14+
BUILDER_NAME=${BUILDER_NAME:-bioscript-builder}
15+
REMOTE_IMAGE=${REMOTE_IMAGE:-ghcr.io/openmined/bioscript}
16+
OUTPUT_MODE=${OUTPUT_MODE:-push} # push|oci
17+
OUTPUT_DEST="${OUTPUT_DEST:-}"
18+
LOAD_PLATFORM=${LOAD_PLATFORM:-auto} # auto|none|<platform>
19+
VERIFY_MANIFEST=${VERIFY_MANIFEST:-0}
20+
1321
# Get version from argument or __init__.py
14-
if [ -n "$1" ]; then
22+
if [ -n "${1:-}" ]; then
1523
VERSION="$1"
1624
else
1725
VERSION=$(grep '^__version__ = ' python/src/bioscript/__init__.py | cut -d'"' -f2)
1826
fi
1927

20-
echo "Building bioscript:${VERSION}..."
28+
if [ -z "$OUTPUT_DEST" ]; then
29+
OUTPUT_DEST="docker/dist/bioscript-${VERSION}.oci.tar"
30+
fi
31+
32+
if ! docker buildx inspect "$BUILDER_NAME" >/dev/null 2>&1; then
33+
echo "Creating docker buildx builder '$BUILDER_NAME'..."
34+
docker buildx create --name "$BUILDER_NAME" --driver docker-container >/dev/null
35+
fi
36+
37+
docker buildx use "$BUILDER_NAME" >/dev/null
38+
docker buildx inspect "$BUILDER_NAME" --bootstrap >/dev/null
39+
40+
echo "Building bioscript:${VERSION} for ${PLATFORMS}..."
41+
42+
REMOTE_TAGS=( )
43+
if [ -n "$REMOTE_IMAGE" ]; then
44+
REMOTE_TAGS=("${REMOTE_IMAGE}:${VERSION}" "${REMOTE_IMAGE}:latest")
45+
fi
46+
47+
BUILD_CMD=(docker buildx build
48+
--builder "$BUILDER_NAME"
49+
--platform "$PLATFORMS"
50+
-f docker/Dockerfile
51+
)
52+
for tag in "${REMOTE_TAGS[@]}"; do
53+
BUILD_CMD+=( -t "$tag" )
54+
done
55+
56+
case "$OUTPUT_MODE" in
57+
push)
58+
if [ "${#REMOTE_TAGS[@]}" -eq 0 ]; then
59+
echo "REMOTE_IMAGE must be set when OUTPUT_MODE=push" >&2
60+
exit 1
61+
fi
62+
BUILD_CMD+=( --push )
63+
;;
64+
oci)
65+
mkdir -p "$(dirname "$OUTPUT_DEST")"
66+
BUILD_CMD+=( --output "type=oci,dest=${OUTPUT_DEST}" )
67+
;;
68+
*)
69+
echo "Unsupported OUTPUT_MODE: $OUTPUT_MODE" >&2
70+
exit 1
71+
;;
72+
esac
73+
74+
BUILD_CMD+=( . )
75+
76+
"${BUILD_CMD[@]}"
2177

22-
docker build \
23-
-f docker/Dockerfile \
24-
-t "bioscript:${VERSION}" \
25-
-t "bioscript:latest" \
26-
-t "ghcr.io/openmined/bioscript:${VERSION}" \
27-
-t "ghcr.io/openmined/bioscript:latest" \
28-
.
78+
LOAD_PLATFORM_RESOLVED=""
79+
if [ "$LOAD_PLATFORM" = "auto" ]; then
80+
case "$(uname -m)" in
81+
x86_64)
82+
LOAD_PLATFORM_RESOLVED="linux/amd64"
83+
;;
84+
arm64|aarch64)
85+
LOAD_PLATFORM_RESOLVED="linux/arm64"
86+
;;
87+
*)
88+
echo "Skipping local load: unsupported host architecture '$(uname -m)'" >&2
89+
LOAD_PLATFORM_RESOLVED=""
90+
;;
91+
esac
92+
elif [ "$LOAD_PLATFORM" = "none" ]; then
93+
LOAD_PLATFORM_RESOLVED=""
94+
else
95+
LOAD_PLATFORM_RESOLVED="$LOAD_PLATFORM"
96+
fi
97+
98+
LOCAL_TAGS=("bioscript:${VERSION}" "bioscript:latest")
99+
LOCAL_LOADED=0
100+
if [ -n "$LOAD_PLATFORM_RESOLVED" ]; then
101+
LOAD_CMD=(docker buildx build
102+
--builder "$BUILDER_NAME"
103+
--platform "$LOAD_PLATFORM_RESOLVED"
104+
-f docker/Dockerfile
105+
)
106+
for tag in "${LOCAL_TAGS[@]}"; do
107+
LOAD_CMD+=( -t "$tag" )
108+
done
109+
LOAD_CMD+=( --load . )
110+
"${LOAD_CMD[@]}"
111+
LOCAL_LOADED=1
112+
fi
29113

30114
echo "✓ Built bioscript:${VERSION}"
31-
echo " Tagged: bioscript:${VERSION}, bioscript:latest"
32-
echo " Tagged: ghcr.io/openmined/bioscript:${VERSION}, ghcr.io/openmined/bioscript:latest"
115+
case "$OUTPUT_MODE" in
116+
push)
117+
echo " Multi-arch pushed: ${REMOTE_TAGS[*]}"
118+
;;
119+
oci)
120+
echo " Multi-arch OCI archive: ${OUTPUT_DEST}"
121+
;;
122+
esac
123+
124+
if [ "$LOCAL_LOADED" = "1" ]; then
125+
echo " Loaded local image for ${LOAD_PLATFORM_RESOLVED}: bioscript:${VERSION}, bioscript:latest"
126+
else
127+
echo " Local image not loaded"
128+
fi
129+
130+
if [ "$VERIFY_MANIFEST" = "1" ]; then
131+
if [ "$OUTPUT_MODE" = "push" ]; then
132+
docker buildx imagetools inspect "${REMOTE_IMAGE}:${VERSION}"
133+
else
134+
echo "(Skipping manifest inspect: only available for pushed images)"
135+
fi
136+
fi
137+
33138
echo ""
34-
echo "Test with:"
35-
echo " docker run --rm bioscript:${VERSION}"
36-
echo " docker run --rm ghcr.io/openmined/bioscript:latest"
139+
echo "Suggested next steps:"
140+
if [ "$OUTPUT_MODE" = "push" ]; then
141+
echo " docker buildx imagetools inspect ${REMOTE_IMAGE}:${VERSION}"
142+
fi
143+
if [ "$LOCAL_LOADED" = "1" ]; then
144+
echo " docker run --platform=${LOAD_PLATFORM_RESOLVED} --rm bioscript:${VERSION}"
145+
fi

test_docker.sh

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,43 @@
11
#!/bin/bash
2-
set -e
2+
set -euo pipefail
33

44
# Test bioscript using Docker
55
# Rebuilds the container and runs the classifier
66

77
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
88

9+
HOST_ARCH=$(uname -m)
10+
case "$HOST_ARCH" in
11+
x86_64)
12+
DEFAULT_PLATFORM="linux/amd64"
13+
;;
14+
arm64|aarch64)
15+
DEFAULT_PLATFORM="linux/arm64"
16+
;;
17+
*)
18+
echo "Unsupported host architecture: $HOST_ARCH" >&2
19+
exit 1
20+
;;
21+
esac
22+
23+
PLATFORM=${PLATFORM:-$DEFAULT_PLATFORM}
24+
OUTPUT_MODE=${OUTPUT_MODE:-oci}
25+
LOAD_PLATFORM=${LOAD_PLATFORM:-$PLATFORM}
26+
BUILD_PLATFORMS=${BUILD_PLATFORMS:-linux/amd64,linux/arm64}
27+
928
echo "Building Docker image..." >&2
10-
cd "$REPO_ROOT/docker"
11-
bash build.sh >&2
29+
PLATFORMS="$BUILD_PLATFORMS" \
30+
OUTPUT_MODE="$OUTPUT_MODE" \
31+
LOAD_PLATFORM="$LOAD_PLATFORM" \
32+
"$REPO_ROOT/docker/build.sh" >&2
1233

1334
echo "" >&2
1435
echo "Running classification in Docker..." >&2
1536
echo "" >&2
1637

1738
# Run with Docker
1839
docker run --rm \
40+
--platform="$PLATFORM" \
1941
-v "$REPO_ROOT/examples/apol1:/data" \
2042
-w /data \
2143
bioscript:latest \

test_docker_amd64.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
PLATFORM=linux/amd64 \
6+
OUTPUT_MODE="${OUTPUT_MODE:-oci}" \
7+
LOAD_PLATFORM=linux/amd64 \
8+
"$REPO_ROOT/test_docker.sh"

test_docker_arm64.sh

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
#!/bin/bash
2+
set -euo pipefail
3+
4+
REPO_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5+
PLATFORM=linux/arm64 \
6+
OUTPUT_MODE="${OUTPUT_MODE:-oci}" \
7+
LOAD_PLATFORM=linux/arm64 \
8+
"$REPO_ROOT/test_docker.sh"

0 commit comments

Comments
 (0)