Skip to content

Commit 1e1f5d9

Browse files
authored
feat: Support arm docker build (#6061)
* feat: support arm docker build Signed-off-by: aaronzuo <anarionzuo@outlook.com> * docker ci test Signed-off-by: aaronzuo <anarionzuo@outlook.com> * support dev Signed-off-by: aaronzuo <anarionzuo@outlook.com> * publish feature-server-dev Signed-off-by: aaronzuo <anarionzuo@outlook.com> * master_only trigger Signed-off-by: aaronzuo <anarionzuo@outlook.com> * master_only docker build use make Signed-off-by: aaronzuo <anarionzuo@outlook.com> --------- Signed-off-by: aaronzuo <anarionzuo@outlook.com>
1 parent 95b9af8 commit 1e1f5d9

File tree

5 files changed

+187
-16
lines changed

5 files changed

+187
-16
lines changed
Lines changed: 112 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,112 @@
1+
name: docker-smoke-tests
2+
3+
on:
4+
pull_request:
5+
paths:
6+
- "sdk/python/feast/infra/feature_servers/multicloud/**"
7+
- "sdk/python/feast/feature_server.py"
8+
- "infra/scripts/feature_server_docker_smoke.py"
9+
- "Makefile"
10+
- ".github/workflows/publish_images.yml"
11+
- ".github/workflows/docker_smoke_tests.yml"
12+
workflow_dispatch:
13+
14+
concurrency:
15+
group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref }}
16+
cancel-in-progress: true
17+
18+
jobs:
19+
feature-server-docker-smoke:
20+
runs-on: ubuntu-latest
21+
strategy:
22+
fail-fast: false
23+
matrix:
24+
arch: [amd64, arm64]
25+
steps:
26+
- uses: actions/checkout@v4
27+
- name: Set up QEMU
28+
uses: docker/setup-qemu-action@v3
29+
- name: Set up Docker Buildx
30+
uses: docker/setup-buildx-action@v3
31+
with:
32+
install: true
33+
- name: Build feature-server image
34+
env:
35+
ARCH: ${{ matrix.arch }}
36+
run: |
37+
make build-feature-server-docker REGISTRY=feastdev VERSION=smoke-${ARCH} DOCKER_PLATFORMS=linux/${ARCH}
38+
- name: Run container
39+
env:
40+
ARCH: ${{ matrix.arch }}
41+
run: |
42+
docker run -d --rm \
43+
--name feature-server-smoke-${ARCH} \
44+
--platform linux/${ARCH} \
45+
-p 6566:6566 \
46+
-v "${GITHUB_WORKSPACE}/infra/scripts/feature_server_docker_smoke.py:/smoke.py:ro" \
47+
feastdev/feature-server:smoke-${ARCH} \
48+
python /smoke.py
49+
- name: Wait for /health
50+
run: |
51+
for i in $(seq 1 60); do
52+
if curl -fsS http://localhost:6566/health >/dev/null; then
53+
exit 0
54+
fi
55+
sleep 2
56+
done
57+
echo "feature-server /health did not become ready"
58+
docker logs feature-server-smoke-${{ matrix.arch }} || true
59+
exit 1
60+
- name: Cleanup
61+
if: always()
62+
env:
63+
ARCH: ${{ matrix.arch }}
64+
run: |
65+
docker stop feature-server-smoke-${ARCH} || true
66+
feature-server-dev-docker-smoke:
67+
runs-on: ubuntu-latest
68+
strategy:
69+
fail-fast: false
70+
matrix:
71+
arch: [amd64, arm64]
72+
steps:
73+
- uses: actions/checkout@v4
74+
- name: Set up QEMU
75+
uses: docker/setup-qemu-action@v3
76+
- name: Set up Docker Buildx
77+
uses: docker/setup-buildx-action@v3
78+
with:
79+
install: true
80+
- name: Build feature-server-dev image
81+
env:
82+
ARCH: ${{ matrix.arch }}
83+
run: |
84+
make build-feature-server-dev-docker REGISTRY=feastdev VERSION=smoke-${ARCH} DOCKER_PLATFORMS=linux/${ARCH}
85+
- name: Run container
86+
env:
87+
ARCH: ${{ matrix.arch }}
88+
run: |
89+
docker run -d --rm \
90+
--name feature-server-dev-smoke-${ARCH} \
91+
--platform linux/${ARCH} \
92+
-p 6566:6566 \
93+
-v "${GITHUB_WORKSPACE}/infra/scripts/feature_server_docker_smoke.py:/smoke.py:ro" \
94+
feastdev/feature-server:smoke-${ARCH} \
95+
python /smoke.py
96+
- name: Wait for /health
97+
run: |
98+
for i in $(seq 1 60); do
99+
if curl -fsS http://localhost:6566/health >/dev/null; then
100+
exit 0
101+
fi
102+
sleep 2
103+
done
104+
echo "feature-server /health did not become ready"
105+
docker logs feature-server-dev-smoke-${{ matrix.arch }} || true
106+
exit 1
107+
- name: Cleanup
108+
if: always()
109+
env:
110+
ARCH: ${{ matrix.arch }}
111+
run: |
112+
docker stop feature-server-dev-smoke-${ARCH} || true

.github/workflows/master_only.yml

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -89,7 +89,19 @@ jobs:
8989
runs-on: ubuntu-latest
9090
strategy:
9191
matrix:
92-
component: [ feature-server-dev, feature-transformation-server, feast-operator ]
92+
include:
93+
- component: feature-server-dev
94+
target: feature-server-dev
95+
build_args: DOCKER_PUSH=true DOCKER_PLATFORMS=linux/amd64,linux/arm64
96+
push_mode: imagetools
97+
- component: feature-transformation-server
98+
target: feature-transformation-server
99+
build_args: ""
100+
push_mode: all_tags
101+
- component: feast-operator
102+
target: feast-operator
103+
build_args: ""
104+
push_mode: all_tags
93105
env:
94106
REGISTRY: quay.io/feastdev-ci
95107
steps:
@@ -117,14 +129,11 @@ jobs:
117129
username: ${{ secrets.QUAYIO_CI_USERNAME }}
118130
password: ${{ secrets.QUAYIO_CI_TOKEN }}
119131
- name: Build image
120-
run: |
121-
make build-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${GITHUB_SHA}
132+
run: make build-${{ matrix.target }}-docker REGISTRY=${REGISTRY} VERSION=${GITHUB_SHA} ${{ matrix.build_args }}
122133
- name: Push image
123134
run: |
124-
if [[ "${{ matrix.component }}" == "feature-server-dev" ]]; then
125-
docker tag ${REGISTRY}/feature-server:${GITHUB_SHA} ${REGISTRY}/feature-server:develop
126-
docker push ${REGISTRY}/feature-server --all-tags
135+
if [[ "${{ matrix.push_mode }}" == "imagetools" ]]; then
136+
docker buildx imagetools create -t ${REGISTRY}/feature-server:develop ${REGISTRY}/feature-server:${GITHUB_SHA}
127137
else
128-
docker tag ${REGISTRY}/${{ matrix.component }}:${GITHUB_SHA} ${REGISTRY}/${{ matrix.component }}:develop
129-
docker push ${REGISTRY}/${{ matrix.component }} --all-tags
138+
docker tag ${REGISTRY}/${{ matrix.target }}:${GITHUB_SHA} ${REGISTRY}/${{ matrix.target }}:develop && docker push ${REGISTRY}/${{ matrix.target }} --all-tags
130139
fi

.github/workflows/publish_images.yml

Lines changed: 16 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -69,17 +69,29 @@ jobs:
6969
env:
7070
VERSION_WITHOUT_PREFIX: ${{ steps.get-version.outputs.version_without_prefix }}
7171
run: |
72-
make build-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${VERSION_WITHOUT_PREFIX}
72+
if [ "${{ matrix.component }}" = "feature-server" ]; then
73+
make build-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${VERSION_WITHOUT_PREFIX} DOCKER_PUSH=true DOCKER_PLATFORMS=linux/amd64,linux/arm64
74+
else
75+
make build-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${VERSION_WITHOUT_PREFIX}
76+
fi
7377
- name: Push versioned images
7478
env:
7579
VERSION_WITHOUT_PREFIX: ${{ steps.get-version.outputs.version_without_prefix }}
7680
HIGHEST_SEMVER_TAG: ${{ steps.get-version.outputs.highest_semver_tag }}
7781
run: |
78-
make push-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${VERSION_WITHOUT_PREFIX}
82+
if [ "${{ matrix.component }}" = "feature-server" ]; then
83+
echo "feature-server image pushed via buildx during build step"
84+
else
85+
make push-${{ matrix.component }}-docker REGISTRY=${REGISTRY} VERSION=${VERSION_WITHOUT_PREFIX}
86+
fi
7987
8088
echo "Only push to latest tag if tag is the highest semver version $HIGHEST_SEMVER_TAG"
8189
if [ "${VERSION_WITHOUT_PREFIX}" = "${HIGHEST_SEMVER_TAG:1}" ]
8290
then
83-
docker tag ${REGISTRY}/${{ matrix.component }}:${VERSION_WITHOUT_PREFIX} ${REGISTRY}/${{ matrix.component }}:latest
84-
docker push ${REGISTRY}/${{ matrix.component }}:latest
91+
if [ "${{ matrix.component }}" = "feature-server" ]; then
92+
docker buildx imagetools create -t ${REGISTRY}/feature-server:latest ${REGISTRY}/feature-server:${VERSION_WITHOUT_PREFIX}
93+
else
94+
docker tag ${REGISTRY}/${{ matrix.component }}:${VERSION_WITHOUT_PREFIX} ${REGISTRY}/${{ matrix.component }}:latest
95+
docker push ${REGISTRY}/${{ matrix.component }}:latest
96+
fi
8597
fi

Makefile

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -659,10 +659,10 @@ push-feature-server-docker: ## Push Feature Server Docker image
659659
docker push $(REGISTRY)/feature-server:$(VERSION)
660660

661661
build-feature-server-docker: ## Build Feature Server Docker image
662-
docker buildx build \
662+
docker buildx build $(if $(DOCKER_PLATFORMS),--platform $(DOCKER_PLATFORMS),) \
663663
-t $(REGISTRY)/feature-server:$(VERSION) \
664664
-f sdk/python/feast/infra/feature_servers/multicloud/Dockerfile \
665-
--load sdk/python/feast/infra/feature_servers/multicloud
665+
$(if $(filter true,$(DOCKER_PUSH)),--push,--load) sdk/python/feast/infra/feature_servers/multicloud
666666

667667
push-feature-transformation-server-docker: ## Push Feature Transformation Server Docker image
668668
docker push $(REGISTRY)/feature-transformation-server:$(VERSION)
@@ -715,9 +715,9 @@ build-feature-server-dev: ## Build Feature Server Dev Docker image
715715
-f sdk/python/feast/infra/feature_servers/multicloud/Dockerfile.dev --load .
716716

717717
build-feature-server-dev-docker: ## Build Feature Server Dev Docker image
718-
docker buildx build \
718+
docker buildx build $(if $(DOCKER_PLATFORMS),--platform $(DOCKER_PLATFORMS),) \
719719
-t $(REGISTRY)/feature-server:$(VERSION) \
720-
-f sdk/python/feast/infra/feature_servers/multicloud/Dockerfile.dev --load .
720+
-f sdk/python/feast/infra/feature_servers/multicloud/Dockerfile.dev $(if $(filter true,$(DOCKER_PUSH)),--push,--load) .
721721

722722
build-feature-server-dev-docker_on_mac: ## Build Feature Server Dev Docker image on Mac
723723
docker buildx build --platform linux/amd64 \
Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
from types import SimpleNamespace
2+
3+
import uvicorn
4+
5+
from feast.feature_server import get_app
6+
7+
8+
class _FakeRegistry:
9+
def proto(self):
10+
return object()
11+
12+
13+
class _FakeStore:
14+
def __init__(self):
15+
self.config = SimpleNamespace()
16+
self.registry = _FakeRegistry()
17+
self._provider = SimpleNamespace(
18+
async_supported=SimpleNamespace(
19+
online=SimpleNamespace(read=False, write=False)
20+
)
21+
)
22+
23+
def _get_provider(self):
24+
return self._provider
25+
26+
async def initialize(self):
27+
return None
28+
29+
def refresh_registry(self):
30+
return None
31+
32+
async def close(self):
33+
return None
34+
35+
36+
if __name__ == "__main__":
37+
app = get_app(_FakeStore())
38+
uvicorn.run(app, host="0.0.0.0", port=6566, log_level="error")

0 commit comments

Comments
 (0)