diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml index d7265c07d..a0c47f60a 100644 --- a/.github/workflows/release.yml +++ b/.github/workflows/release.yml @@ -302,13 +302,17 @@ jobs: role-to-assume: ${{ secrets.ECR_PUBLIC_UPLOAD_ROLE }} aws-region: us-east-1 - - name: Generate tag + - name: Generate metadata run: | aws --version docker info TAG="$(cat ./VERSION)" echo "TAG: $TAG" echo "TAG=$TAG" >> $GITHUB_ENV + BUILD_DATE=`date -u +%Y-%m-%d` + echo "BUILD_DATE=$BUILD_DATE" >> $GITHUB_ENV + BUILD_VERSION=${{ github.sha }} + echo "BUILD_VERSION=$BUILD_VERSION" >> $GITHUB_ENV - name: Login to Public Registry run: | @@ -323,8 +327,13 @@ jobs: with: builder: ${{ steps.buildx.outputs.name }} context: . - file: ./Dockerfile.dev + file: Dockerfile platforms: linux/amd64 + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + BUILD_DATE=${{ env.BUILD_DATE }} + BUILD_VERSION=${{ env.BUILD_VERSION }} push: true tags: | public.ecr.aws/covalent/covalent:latest @@ -341,8 +350,13 @@ jobs: with: builder: ${{ steps.buildx.outputs.name }} context: . - file: ./Dockerfile.dev + file: Dockerfile platforms: linux/amd64 + cache-from: type=gha + cache-to: type=gha,mode=max + build-args: | + BUILD_DATE=${{ env.BUILD_DATE }} + BUILD_VERSION=${{ env.BUILD_VERSION }} push: true tags: | public.ecr.aws/covalent/covalent:${{ inputs.stable_version }} diff --git a/.gitignore b/.gitignore index 9635caada..bc406e096 100644 --- a/.gitignore +++ b/.gitignore @@ -55,7 +55,7 @@ !.secrets.baseline !alembic.ini !codecov.yml -!Dockerfile* +!Dockerfile !MANIFEST.in !Makefile !README.md diff --git a/CHANGELOG.md b/CHANGELOG.md index e55e921e1..bfbd3ea50 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [UNRELEASED] +### Changed + +- Enhanced the Dockerfile to include builds from various sources and a differentiation between SDK and Server builds + ## [0.217.0-rc.0] - 2023-02-12 ### Authors @@ -65,7 +69,6 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Faiyaz Hasan - Alejandro Esquivel - ### Docs - Added IBMQ tutorial diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index e1315c0fa..cc7ba7b70 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -513,6 +513,78 @@ Some important commands to know about: This module can be used to mock module variables, environment variables etc. Check out the official [monkeypatch documentation](https://docs.pytest.org/en/6.2.x/monkeypatch.html). +## Covalent with Docker + +This repository contains a Dockerfile that can be used in a variety of ways for development and deployment. Note that we use the Dockerfile 1.4 syntax which requires BuildKit. For most users, it is sufficient to set the environment variable `DOCKER_BUILDKIT=1` before attempting to build images. All of the examples below use build arguments and target stages referenced in the Dockerfile. For a full list of build arguments, run `grep ARG Dockerfile`. + +### Covalent Server + +The Covalent server can run inside a container. Build this container using the default options: + +```shell +docker build --tag covalent-server:latest . +``` + +It is recommended a date and version are included using build arguments whenever an image is build. This can be done by including these options: + +```shell +--build-arg COVALENT_BUILD_DATE=`date -u +%Y-%m-%d` --build-arg COVALENT_BUILD_VERSION=`cat ./VERSION` --tag covalent-server:`cat ./VERSION` +``` + +To run the server, use the command + +```shell +docker run -d -p 48008:48008 covalent-server:latest +``` + +### Covalent SDK + +The Covalent SDK can also run inside a container. This is useful in scenarios where containerized tasks use Covalent, e.g., in executor plugins. Build the container using these options: + +```shell +docker build --build-arg COVALENT_INSTALL_TYPE=sdk --tag covalent-sdk:latest . +``` + +To run the SDK interactively against a server running somewhere else accessible by the host network, start the container using + +```shell +docker run -it --rm --network=host covalent-sdk:latest +``` + +### Development Images + +By referencing an intermediate build target, we can also generate a build environment that can be used for developing Covalent: + +```shell +# Does not include Covalent source +docker build --tag covalent-build:latest --target build_server . + +# Includes Covalent source +docker build --tag covalent-dev:latest --target covalent_install . +``` + +### Selecting a Covalent Source + +Different circumstances will require Covalent coming from different sources. The build arguments can be leveraged to specify either a local source, a PyPI release, or a commit SHA checked into GitHub. The default source is local, i.e., it uses the Covalent source code next to the Dockerfile. + +```shell +# PyPI Release +--build-arg COVALENT_SOURCE=pypi --build-arg COVALENT_RELEASE=0.202.0.post1 + +# GitHub Commit +--build-arg COVALENT_SOURCE=sha --build-arg COVALENT_COMMIT_SHA=abcdef +``` + +### Custom Base Image + +Finally, users can specify a custom base image, which can be useful when users are trying to incorporate Covalent SDK or Server into their existing tech stack: + +```shell +--build-arg COVALENT_BASE_IMAGE=/: +``` + +Note that the base image must include a compatible version of Python and must be based on either Ubuntu or Debian. + Building Read the Docs (RTD) locally ==================================== diff --git a/Dockerfile b/Dockerfile index e57857f87..5f6ae5ade 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,3 +1,4 @@ +# syntax=docker/dockerfile:1.4 # Copyright 2021 Agnostiq Inc. # # This file is part of Covalent. @@ -18,49 +19,327 @@ # # Relief from the License may be granted by purchasing a commercial license. -# syntax=docker/dockerfile:1 -FROM python:3.8-slim-bullseye AS build +####################### +# Docker Build Options +####################### -RUN apt-get update \ - && apt-get install -y --no-install-recommends rsync wget \ - && rm -rf /var/lib/apt/lists/* +# Options are local,pypi,sha +ARG COVALENT_SOURCE=local +# Options are sdk,server +ARG COVALENT_INSTALL_TYPE=server +# Must include a compatible version of Python +ARG COVALENT_BASE_IMAGE=docker.io/python:3.8-slim-bullseye -RUN python -m venv --copies /covalent/.venv \ - && . /covalent/.venv/bin/activate \ - && pip install --upgrade pip \ - && pip install covalent==0.177.0 +################### +# Covalent Options +################### -FROM python:3.8-slim-bullseye AS prod -LABEL org.label-schema.name="Covalent Server" -LABEL org.label-schema.vendor="Agnostiq" -LABEL org.label-schema.url="https://covalent.xyz" -LABEL org.label-schema.vcs-url="https://github.com/AgnostiqHQ/covalent" -LABEL org.label-schema.vcs-ref="f2e85397ea4609df274a38b03e6e17dcbae6bc52" # pragma: allowlist secret -LABEL org.label-schema.version="0.177.0" -LABEL org.label-schema.docker.cmd="docker run -it -p 8080:8080 -d covalent:latest" -LABEL org.label-schema.schema-version=1.0 +# Installation path +ARG COVALENT_ROOT=/var/lib/covalent +# Configuration file path +ARG COVALENT_CONFIG_DIR=/etc/covalent +# Service port for dispatcher / UI +ARG COVALENT_SVC_PORT=48008 +# Local plugins path +ARG COVALENT_PLUGINS_DIR=/etc/covalent/plugins +# SQLite database path (do not use in production) +ARG COVALENT_DATABASE=/var/lib/covalent/dispatch.db +# Remote database path (overrides SQLite database if defined) +ARG COVALENT_DATABASE_URL="" +# Local object storage path +ARG COVALENT_DATA_DIR=/var/lib/covalent/data +# Log file path +ARG COVALENT_LOGDIR=/var/log/covalent +# Cache path +ARG COVALENT_CACHE_DIR=/var/cache/covalent +# Debug mode +ARG COVALENT_DEBUG_MODE=1 -COPY --from=build /usr/bin/rsync /usr/bin/rsync -COPY --from=build /usr/lib/x86_64-linux-gnu/libpopt.so.0 /usr/lib/x86_64-linux-gnu/libpopt.so.0 +######################## +# Covalent Dask Options +######################## -COPY --from=build /usr/bin/wget /usr/bin/wget -COPY --from=build /usr/lib/x86_64-linux-gnu/libpcre2-8.so.0 /usr/lib/x86_64-linux-gnu/libpcre2-8.so.0 -COPY --from=build /usr/lib/x86_64-linux-gnu/libpsl.so.5 /usr/lib/x86_64-linux-gnu/libpsl.so.5 +# Disable Dask inside the container +ARG COVALENT_DISABLE_DASK=1 +# Number of Dask workers used by dispatcher +ARG COVALENT_NUM_WORKERS=1 +# Number of threads per Dask worker +ARG COVALENT_THREADS_PER_WORKER=1 +# Memory per worker (in GB) +ARG COVALENT_MEM_PER_WORKER=1GB -COPY --from=build /covalent/.venv/ /covalent/.venv +################## +# Global Settings +################## -RUN useradd -ms /bin/bash ubuntu \ - && chown ubuntu:users /covalent +FROM ${COVALENT_BASE_IMAGE} as base -WORKDIR /covalent -USER ubuntu +ARG COVALENT_ROOT +ARG COVALENT_CONFIG_DIR +ARG COVALENT_PLUGINS_DIR +ARG COVALENT_LOGDIR +ARG COVALENT_CACHE_DIR -ENV COVALENT_SERVER_IFACE_ANY=1 -ENV PATH=/covalent/.venv/bin:$PATH -EXPOSE 8080 -HEALTHCHECK CMD wget --no-verbose --tries=1 --spider http://localhost:8080 || exit 1 +ENV PYTHONHASHSEED=random \ + PYTHONUNBUFFERED=1 \ + DEBIAN_FRONTEND=noninteractive \ + BUILDROOT=/build \ + INSTALLROOT=${COVALENT_ROOT} \ + USER=covalent \ + COVALENT_ROOT=${COVALENT_ROOT} \ + COVALENT_CONFIG_DIR=${COVALENT_CONFIG_DIR} \ + COVALENT_PLUGINS_DIR=${COVALENT_PLUGINS_DIR} \ + COVALENT_LOGDIR=${COVALENT_LOGDIR} \ + COVALENT_CACHE_DIR=${COVALENT_CACHE_DIR} -RUN covalent config \ - && sed -i 's|^results_dir.*$|results_dir = "/covalent/results"|' /home/ubuntu/.config/covalent/covalent.conf +USER root -CMD covalent start --ignore-migrations --port 8080 && bash +RUN < dict: """ from .config import get_config - return "local" if get_config("sdk.no_cluster") == "true" else "dask" + return ( + "local" + if os.environ.get("COVALENT_DISABLE_DASK") == "1" or get_config("sdk.no_cluster") == "true" + else "dask" + ) # Default configuration settings diff --git a/covalent_dispatcher/_cli/service.py b/covalent_dispatcher/_cli/service.py index 2e5d937d9..66ea4fb2a 100644 --- a/covalent_dispatcher/_cli/service.py +++ b/covalent_dispatcher/_cli/service.py @@ -315,6 +315,13 @@ def start( """ Start the Covalent server. """ + + if os.environ.get("COVALENT_DEBUG_MODE") == "1": + develop = True + + if os.environ.get("COVALENT_DISABLE_DASK") == "1": + no_cluster = True + if develop: set_config({"sdk.log_level": "debug"})