-
-
Notifications
You must be signed in to change notification settings - Fork 2k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #8254 from OpenMined/config-dockerfile
Build custom worker with config
- Loading branch information
Showing
12 changed files
with
286 additions
and
156 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
# Syft Worker | ||
# Build as-is to create a base worker image | ||
# Build with args to create a custom worker image | ||
|
||
# NOTE: This dockerfile will be built inside a grid-backend container in PROD | ||
# Hence COPY will not work the same way in DEV vs. PROD | ||
|
||
# FIXME: Due to dependency on grid-backend base, python can only be changed from 3.11 to 3.11-dev | ||
# Later we'd want to uninstall old python, and then install a new python runtime... | ||
# ... but pre-built syft deps may break! | ||
|
||
FROM openmined/grid-backend:0.8.3-beta.2 | ||
|
||
ARG PYTHON_VERSION="3.11" | ||
ARG SYSTEM_PACKAGES="" | ||
ARG PIP_PACKAGES="pip --dry-run" | ||
ARG CUSTOM_CMD='echo "No custom commands passed"' | ||
|
||
# Worker specific environment variables go here | ||
ENV SYFT_WORKER="true" | ||
|
||
RUN --mount=type=cache,target=/var/cache/apk,sharing=locked \ | ||
--mount=type=cache,target=$HOME/.cache/pip,sharing=locked \ | ||
apk update && \ | ||
apk add ${SYSTEM_PACKAGES} && \ | ||
pip install --user ${PIP_PACKAGES} && \ | ||
bash -c "$CUSTOM_CMD" |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
# stdlib | ||
import os.path | ||
from pathlib import Path | ||
from typing import Tuple | ||
|
||
# third party | ||
import docker | ||
|
||
# relative | ||
from .config import CustomWorkerConfig | ||
|
||
|
||
class CustomWorkerBuilder: | ||
TYPE_CPU = "cpu" | ||
TYPE_GPU = "gpu" | ||
|
||
DOCKERFILE_PROD_PATH = os.path.expandvars("$APPDIR/grid/") | ||
DOCKERFILE_DEV_PATH = "../../../../../grid/backend/" | ||
|
||
CUSTOM_IMAGE_PREFIX = "custom-worker" | ||
|
||
BUILD_MAX_WAIT = 30 * 60 | ||
|
||
def build_image(self, config: CustomWorkerConfig) -> None: | ||
""" | ||
Builds a Docker image for the custom worker based on the provided configuration. | ||
Args: | ||
config (CustomImageConfig): The configuration for building the Docker image. | ||
Returns: | ||
bool: True if the image was built successfully, raises Exception otherwise. | ||
""" | ||
|
||
# remove once GPU is supported | ||
if config.build.gpu: | ||
raise Exception("GPU custom worker is not supported yet") | ||
|
||
type = self.TYPE_GPU if config.build.gpu else self.TYPE_CPU | ||
|
||
contextdir, dockerfile = self.find_worker_ctx(type) | ||
|
||
imgtag = config.get_signature()[:8] | ||
|
||
build_args = { | ||
"PYTHON_VERSION": config.build.python_version, | ||
"SYSTEM_PACKAGES": config.build.merged_system_pkgs(), | ||
"PIP_PACKAGES": config.build.merged_python_pkgs(), | ||
"CUSTOM_CMD": config.build.merged_custom_cmds(), | ||
} | ||
|
||
print( | ||
f"Building dockerfile={dockerfile} " | ||
f"in context={contextdir} " | ||
f"with args={build_args}" | ||
) | ||
|
||
try: | ||
client = docker.from_env() | ||
|
||
# TODO: Push logs to mongo/seaweed? | ||
client.images.build( | ||
path=str(contextdir), | ||
dockerfile=dockerfile, | ||
pull=True, | ||
tag=f"{self.CUSTOM_IMAGE_PREFIX}-{type}:{imgtag}", | ||
timeout=self.BUILD_MAX_WAIT, | ||
buildargs=build_args, | ||
) | ||
|
||
return | ||
except docker.errors.BuildError as e: | ||
raise e | ||
except docker.errors.APIError as e: | ||
raise e | ||
except Exception as e: | ||
raise e | ||
|
||
def find_worker_ctx(self, type: str) -> Tuple[Path, str]: | ||
""" | ||
Find the Worker Dockerfile and it's context path | ||
- PROD will be in `$APPDIR/grid/` | ||
- DEV will be in `packages/grid/backend` | ||
- In both the cases context dir does not matter (unless we're calling COPY) | ||
Args: | ||
type (str): The type of worker. | ||
Returns: | ||
Path: The path to the Dockerfile. | ||
""" | ||
filename = f"worker_{type}.dockerfile" | ||
lookup_paths = [ | ||
Path(self.DOCKERFILE_PROD_PATH, filename).resolve(), | ||
Path(__file__, self.DOCKERFILE_DEV_PATH, filename).resolve(), | ||
] | ||
for path in lookup_paths: | ||
if path.exists(): | ||
return path.parent, filename | ||
|
||
raise FileNotFoundError(f"Cannot find the {filename}") |
Oops, something went wrong.