diff --git a/src/jetbrain-space/docker-compose.yml b/src/jetbrain-space/docker-compose.yml
new file mode 100644
index 0000000..f0bd2d3
--- /dev/null
+++ b/src/jetbrain-space/docker-compose.yml
@@ -0,0 +1,164 @@
+version: '3.8'
+
+services:
+ init-configs:
+ image: "public.registry.jetbrains.space/p/space-on-premises/docker/init-configs:2023.3.1"
+ volumes:
+ - config:/home/init-config/config
+ environment:
+ AUTOMATION_TAG: "2023.3.1.87"
+ SPACE_VERSION: "2023.3.1"
+ space:
+ image: "public.registry.jetbrains.space/p/space-on-premises/docker/space:2023.3.1"
+ volumes:
+ - config:/home/space/circlet-server-onprem/config
+ environment:
+ JAVA_OPTS: "-Dconfig.file=/home/space/circlet-server-onprem/config/space.on-premises.conf -Dconfig.override_with_env_vars=true"
+ depends_on:
+ init-configs:
+ condition: service_completed_successfully
+ vcs:
+ condition: service_started
+ redis:
+ condition: service_started
+ postgres:
+ condition: service_started
+ minio:
+ condition: service_started
+ elasticsearch:
+ condition: service_healthy
+ ports:
+ - "8084:8084"
+ networks:
+ - "frontend"
+ - "backend-apps"
+ - "backend-data"
+
+ vcs:
+ image: "public.registry.jetbrains.space/p/space-on-premises/docker/vcs-hosting:2023.3.1"
+ volumes:
+ - config:/home/space/git/vcs-hosting/config
+ environment:
+ JAVA_OPTS: '-Dproperties.file=config/vcs.on-premises.properties'
+ depends_on:
+ init-configs:
+ condition: service_completed_successfully
+ redis:
+ condition: service_started
+ postgres:
+ condition: service_started
+ minio:
+ condition: service_started
+ elasticsearch:
+ condition: service_healthy
+ ports:
+ - "2222:2222"
+ - "8080:8080"
+ networks:
+ - "frontend"
+ - "backend-apps"
+ - "backend-data"
+
+ packages:
+ image: "public.registry.jetbrains.space/p/space-on-premises/docker/packages:2023.3.1"
+ volumes:
+ - config:/home/space/packages-server/config
+ environment:
+ JAVA_OPTS: '-Dconfig.file=/home/space/packages-server/config/packages.on-premises.conf -Dconfig.override_with_env_vars=true'
+ depends_on:
+ init-configs:
+ condition: service_completed_successfully
+ redis:
+ condition: service_started
+ postgres:
+ condition: service_started
+ minio:
+ condition: service_started
+ elasticsearch:
+ condition: service_healthy
+ ports:
+ - "8390:8390"
+ - "9390:9390"
+ networks:
+ - "frontend"
+ - "backend-apps"
+ - "backend-data"
+
+ langservice:
+ image: "public.registry.jetbrains.space/p/space-on-premises/docker/langservice:2023.3.1"
+ volumes:
+ - config:/home/space/langservice-server/config
+ environment:
+ JAVA_OPTS: "-Dconfig.file=/home/space/langservice-server/config/langservice.on-premises.conf -Dconfig.override_with_env_vars=true"
+ depends_on:
+ init-configs:
+ condition: service_completed_successfully
+ ports:
+ - "8095"
+ networks:
+ - "backend-apps"
+
+ postgres:
+ image: "postgres:12.2"
+ volumes:
+ - db_data:/var/lib/postgresql/data
+ environment:
+ POSTGRES_USER: space
+ POSTGRES_PASSWORD: spacepassword
+ POSTGRES_DB: spacedb
+ ports:
+ - "5432"
+ networks:
+ - "backend-data"
+
+ elasticsearch:
+ image: "elasticsearch:7.17.7"
+ volumes:
+ - elasticsearch_data:/usr/share/elasticsearch/data
+ environment:
+ ES_JAVA_OPTS: -Xms512m -Xmx1024m
+ discovery.type: single-node
+ xpack.security.enabled: "false"
+ ports:
+ - "9200"
+ - "9300"
+ healthcheck:
+ test: [ "CMD", "curl", "-f", "http://localhost:9200/_cat/health" ]
+ interval: 5s
+ timeout: 5s
+ retries: 10
+ start_period: 20s
+ networks:
+ - "backend-data"
+
+ redis:
+ image: "redis:7.0.2-alpine"
+ ports:
+ - "6379"
+ networks:
+ - "backend-data"
+
+ minio:
+ image: minio/minio:RELEASE.2021-09-09T21-37-07Z
+ volumes:
+ - minio_data:/data
+ environment:
+ MINIO_ROOT_USER: space-access-key
+ MINIO_ROOT_PASSWORD: space-secret-key
+ command: server --address :9000 --console-address :9001 --compat /data
+ ports:
+ - "9000:9000"
+ - "9001"
+ networks:
+ - "backend-data"
+volumes:
+ elasticsearch_data: {}
+ db_data: {}
+ minio_data: {}
+ config: {}
+
+networks:
+ frontend: {}
+ backend-apps: {}
+ backend-data: {}
+
diff --git a/src/prefect-docker-compose-main/README.md b/src/prefect-docker-compose-main/README.md
new file mode 100644
index 0000000..58507f5
--- /dev/null
+++ b/src/prefect-docker-compose-main/README.md
@@ -0,0 +1,195 @@
+# Prefect - Docker Compose
+
+A simple guide to understand and make Prefect **2.x** work with your own docker-compose configuration.
+
+Interested in examples for Prefect **1.x** ? Switch to the [last 1.x branch of this repo](https://github.com/flavienbwk/prefect-docker-compose/tree/e758a498d5819550a9b926b0bf9bb4e9c85574d1).
+
+This allows you to package your Prefect instance for fully-containerized environments (e.g: docker-compose, Kubernetes) or offline use.
+
+![Operating principle of Prefect](./prefect_schema_principle.jpg)
+
+- [Prefect - Docker Compose](#prefect---docker-compose)
+ - [Run the server](#run-the-server)
+ - [Run one or multiple agents](#run-one-or-multiple-agents)
+ - [Run your first flow via the Prefect API](#run-your-first-flow-via-the-prefect-api)
+ - [Principles to understand](#principles-to-understand)
+ - [Flow with Local storage (easiest)](#flow-with-local-storage-easiest)
+ - [Flow with S3 Storage (recommended)](#flow-with-s3-storage-recommended)
+ - [Flow with Docker storage](#flow-with-docker-storage)
+ - [Preparing the Registry](#preparing-the-registry)
+ - [Start the Docker in Docker agent](#start-the-docker-in-docker-agent)
+ - [Registering the flow](#registering-the-flow)
+
+## Run the server
+
+1. Optionally open and edit the [`server/.env`](./server/.env) file
+
+ :information_source: All `PREFECT_*` env variables can be [found in the Prefect settings.py file](https://github.com/PrefectHQ/prefect/blob/main/src/prefect/settings.py#L238).
+
+2. Start the server :
+
+ ```bash
+ cd server && docker-compose up --build -d && cd -
+ ```
+
+3. Access the Orion UI at [localhost:4200](http://localhost:4200)
+
+## Run one or multiple agents
+
+Agents are services that run your scheduled flows.
+
+1. Optionally open and edit the [`agent/docker-compose.yml`](./agent/docker-compose.yml) file.
+
+ > :information_source: In each `docker-compose.yml`, you will find the `PREFECT_API_URL` env variable including the `172.17.0.1` IP address. This is the IP of the Docker daemon on which are exposed all exposed ports of your containers. This allows containers launched from different docker-compose networks to communicate. Change it if yours is different (check your daemon IP by typing `ip a | grep docker0`).
+ >
+ > ![Docker interface IP](./docker_interface.png)
+ >
+ > Here, mine is `192.168.254.1` but the default is generally to `172.17.0.1`.
+
+2. Start the agent :
+
+ ```bash
+ docker-compose -f agent/docker-compose.yml up -d
+ ```
+
+ > :information_source: You can run the agent on another machine than the one with the Prefect server. Edit the `PREFECT_API_URL` env variable for that.
+
+ Maybe you want to instanciate multiple agents ?
+
+ ```bash
+ docker-compose -f agent/docker-compose.yml up -d --scale agent=3 agent
+ ```
+
+3. Our agents are now starting listening the Orion server on the `flows-example-queue` queue ([see the `--work-queue` option](./agent/docker-compose.yml#L7)).
+
+## Run your first flow via the Prefect API
+
+### Principles to understand
+
+> :speech_balloon: [Execution in your cloud; orchestration in ours](https://medium.com/the-prefect-blog/the-prefect-hybrid-model-1b70c7fd296)
+
+This means the Prefect server never stores your code. It just orchestrates the running (optionally the scheduling) of it.
+
+1. After developing your flow, Prefect will register it to the Orion server [through a Deployment](./client/app/weather.py#L49). In that script, you may ask the server to run your flow 3 times a day, for example.
+2. Your code never lies on the Prefect server : this means the code has to be stored somewhere accessible to the agents in order to be executed.
+
+ Prefect has [a lot of storage options](https://docs.prefect.io/tutorials/storage) but the most famous are : Local, S3, Docker and git.
+ - Local : saves the flows to be run on disk. So the volume where you save the flows must be [shared among your client and your agent(s)](./client/docker-compose.yml#L9). Requires your agent to have the same environment than your client (Python modules, packages installed etc... (the same Dockerfile if your agent and client are containers))
+ - S3 : similar to local, but saves the flows to be run in S3 objects.
+ - Docker : saves the flows to be run as Docker images to your Docker Registry so your agents can easily run the code.
+
+### Flow with Local storage (easiest)
+
+:information_source: If your agents are installed among multiple machines, I recommend you to mount a shared directory with SSHFS.
+
+1. Run the following command to register your deployment and run the flow :
+
+ ```bash
+ docker-compose -f client/docker-compose.yml up # Executes weather.py
+ ```
+
+2. Access the UI to see your flow correctly run
+
+### Flow with S3 Storage (recommended)
+
+
+Tutorial for S3 Storage
+
+
+We will use [MinIO](https://www.github.com/minio/minio) as our S3 server.
+
+1. Optionally open and edit the [`client_s3/.env`](./client_s3/.env) file and start MinIO
+
+ ```bash
+ docker-compose -f client_s3/docker-compose.yml up -d minio # Starts MinIO
+ ```
+
+2. Register the flow :
+
+ ```bash
+ docker-compose -f client_s3/docker-compose.yml up weather # Executes weather.py
+ ```
+
+Now your flow is registered. You can access the UI to run it.
+
+
+
+### Flow with Docker storage
+
+This method requires our client AND agent containers to have access to Docker so they can package or load the image in which the flow will be executed. We use _Docker in Docker_ for that.
+
+
+Tutorial for (secure) Docker Storage
+
+#### Preparing the Registry
+
+A Docker Registry is needed in order to save images that are going to be used by our agents.
+
+1. Generate the authentication credentials for our registry
+
+ ```bash
+ sudo apt install apache2-utils # required to generate basic_auth credentials
+ cd client_docker/registry/auth && htpasswd -B -c .htpasswd myusername && cd -
+ ```
+
+ > To add more users, re-run the previous command **without** the -c option
+
+2. Start the registry
+
+ ```bash
+ docker-compose -f client_docker/docker-compose.yml up -d registry
+ ```
+
+3. Login to the registry
+
+ You need to allow your Docker daemon to push to this registry. Insert this in your `/etc/docker/daemon.json` (create if needed) :
+
+ ```json
+ {
+ "insecure-registries": ["172.17.0.1:5000"]
+ }
+ ```
+
+4. Start the registry
+
+ ```bash
+ docker login http://172.17.0.1:5000 # with myusername and the password you typed
+ ```
+
+ You should see : _Login Succeeded_
+
+#### Start the Docker in Docker agent
+
+Optionally edit registry credentials in [`./agent_docker/docker-compose.yml`](./agent_docker/docker-compose.yml) and run :
+
+```bash
+docker-compose -f agent_docker/docker-compose.yml up --build -d
+```
+
+#### Registering the flow
+
+We're going to push our Docker image with Python dependencies and register our flow.
+
+1. Build, tag and push the image
+
+ ```bash
+ docker build . -f ./client_docker/execution.Dockerfile -t 172.17.0.1:5000/weather/base_image:latest
+ ```
+
+ > You **must** prefix your image with the registry URI `172.17.0.1:5000` to push it
+
+ ```bash
+ docker push 172.17.0.1:5000/weather/base_image:latest
+ ```
+
+2. Register the flow
+
+ Optionally edit registry credentials in `./client_docker/docker-compose.yml` and run :
+
+ ```bash
+ docker-compose -f ./client_docker/docker-compose.yml up --build weather
+ ```
+
+Now your flow is registered. You can access the UI to run it.
+
+
diff --git a/src/prefect-docker-compose-main/agent/Dockerfile b/src/prefect-docker-compose-main/agent/Dockerfile
new file mode 100644
index 0000000..5cbbfd0
--- /dev/null
+++ b/src/prefect-docker-compose-main/agent/Dockerfile
@@ -0,0 +1,4 @@
+FROM python:3.10
+
+RUN apt update && apt install uuid -y
+RUN pip install prefect==2.4.2 psycopg2-binary==2.9.3 s3fs==2022.8.2 minio==7.1.11
diff --git a/src/prefect-docker-compose-main/agent/docker-compose.yml b/src/prefect-docker-compose-main/agent/docker-compose.yml
new file mode 100644
index 0000000..b4e5155
--- /dev/null
+++ b/src/prefect-docker-compose-main/agent/docker-compose.yml
@@ -0,0 +1,12 @@
+version: "3.7"
+
+services:
+
+ agent:
+ build: .
+ command: bash -c "prefect agent start --work-queue flows-example-queue"
+ environment:
+ PREFECT_API_URL: "http://172.17.0.1:4200/api"
+ volumes:
+ - /srv/docker/prefect/flows:/root/.prefect/flows
+ - /srv/docker/prefect/flows:/flows
diff --git a/src/prefect-docker-compose-main/agent_docker/Dockerfile b/src/prefect-docker-compose-main/agent_docker/Dockerfile
new file mode 100644
index 0000000..8cc2dce
--- /dev/null
+++ b/src/prefect-docker-compose-main/agent_docker/Dockerfile
@@ -0,0 +1,7 @@
+FROM docker:20.10-dind-rootless
+ENV TZ="Europe/Paris"
+
+USER root
+RUN apk update && apk add build-base libffi-dev python3 python3-dev py3-pip gcc linux-headers musl-dev util-linux
+
+RUN pip3 install --upgrade pip && pip3 install prefect==2.4.2
diff --git a/src/prefect-docker-compose-main/agent_docker/docker-compose.yml b/src/prefect-docker-compose-main/agent_docker/docker-compose.yml
new file mode 100644
index 0000000..5f373bb
--- /dev/null
+++ b/src/prefect-docker-compose-main/agent_docker/docker-compose.yml
@@ -0,0 +1,20 @@
+version: "3.7"
+
+services:
+
+ agent:
+ build: .
+ privileged: true # forced for Docker DinD
+ entrypoint: ["/bin/sh", "-c"]
+ command:
+ - |
+ docker login -u=myusername -p=test http://172.17.0.1:5000
+ mkdir -p /opt/prefect/flows
+ prefect agent start --work-queue flows-example-queue-docker
+ environment:
+ PREFECT_API_URL: "http://172.17.0.1:4200/api"
+ volumes:
+ - type: bind
+ source: /var/run/docker.sock
+ target: /var/run/docker.sock
+ read_only: true
diff --git a/src/prefect-docker-compose-main/client/Dockerfile b/src/prefect-docker-compose-main/client/Dockerfile
new file mode 100644
index 0000000..c450a42
--- /dev/null
+++ b/src/prefect-docker-compose-main/client/Dockerfile
@@ -0,0 +1,6 @@
+FROM python:3.10
+
+RUN apt update && apt install uuid -y
+RUN pip install prefect==2.4.2
+
+WORKDIR /usr/app
diff --git a/src/prefect-docker-compose-main/client/app/weather.py b/src/prefect-docker-compose-main/client/app/weather.py
new file mode 100644
index 0000000..88200b4
--- /dev/null
+++ b/src/prefect-docker-compose-main/client/app/weather.py
@@ -0,0 +1,59 @@
+# A simple example to demonstrate Prefect is working as expected
+# Works with a local folder shared with the agents (/root/.prefect/flows by default).
+
+import json
+
+import requests
+from prefect import flow, task, get_run_logger
+from prefect.deployments import Deployment
+from prefect.filesystems import LocalFileSystem
+
+# --- Flow definition
+
+@task
+def get_city_coordinates(city: str):
+ logger = get_run_logger()
+ cities = {
+ "Paris": (2.3510, 48.8567)
+ }
+ logger.info("Getting {}'s coordinates".format(city))
+ return cities[city]
+
+
+@task
+def get_weather(longitude: float, latitude: float):
+ logger = get_run_logger()
+ logger.info(f"Getting weather of latitude={latitude} and longitude={longitude}")
+ api_endpoint = f"https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&hourly=temperature_2m"
+ response = requests.get(api_endpoint)
+ if response.status_code == 200:
+ weather_data = json.loads(response.text)
+ logger.debug(weather_data)
+ return weather_data
+ else:
+ raise Exception("Failed to query " + api_endpoint)
+
+
+@flow(name="get_paris_weather")
+def get_paris_weather():
+ city_coordinates = get_city_coordinates("Paris")
+ return get_weather(city_coordinates[0], city_coordinates[1])
+
+# --- Deployment definition
+
+if __name__ == '__main__':
+
+ block_storage = LocalFileSystem(basepath="/flows")
+ block_storage.save("local-storage", overwrite=True)
+
+ deployment = Deployment.build_from_flow(
+ name="get_weather_local_example",
+ flow=get_paris_weather,
+ storage=LocalFileSystem.load("local-storage"),
+ work_queue_name="flows-example-queue"
+ )
+ deployment.apply()
+
+ # --- Execute the flow
+
+ get_paris_weather()
diff --git a/src/prefect-docker-compose-main/client/docker-compose.yml b/src/prefect-docker-compose-main/client/docker-compose.yml
new file mode 100644
index 0000000..144b6c2
--- /dev/null
+++ b/src/prefect-docker-compose-main/client/docker-compose.yml
@@ -0,0 +1,12 @@
+version: "3.7"
+
+services:
+
+ weather:
+ build: .
+ command: python3 /usr/app/weather.py
+ volumes:
+ - /srv/docker/prefect/flows:/flows
+ - ./app:/usr/app:ro
+ environment:
+ PREFECT_API_URL: "http://172.17.0.1:4200/api"
diff --git a/src/prefect-docker-compose-main/client_docker/Dockerfile b/src/prefect-docker-compose-main/client_docker/Dockerfile
new file mode 100644
index 0000000..b436b03
--- /dev/null
+++ b/src/prefect-docker-compose-main/client_docker/Dockerfile
@@ -0,0 +1,10 @@
+FROM docker:20.10-dind-rootless
+ENV TZ="Europe/Paris"
+
+USER root
+RUN apk update && apk add build-base libffi-dev python3 python3-dev py3-pip gcc linux-headers musl-dev util-linux
+
+RUN pip3 install --upgrade pip && pip3 install prefect==2.4.2 docker==6.0.0
+
+COPY ./entrypoint.sh /entrypoint.sh
+ENTRYPOINT [ "sh", "/entrypoint.sh" ]
diff --git a/src/prefect-docker-compose-main/client_docker/app/weather.py b/src/prefect-docker-compose-main/client_docker/app/weather.py
new file mode 100644
index 0000000..4f5ca72
--- /dev/null
+++ b/src/prefect-docker-compose-main/client_docker/app/weather.py
@@ -0,0 +1,111 @@
+# A simple example to demonstrate Prefect is working as expected
+# Works with a local folder shared with the agents (/root/.prefect/flows by default).
+
+import json
+import os
+import shutil
+import tarfile
+import tempfile
+import uuid
+from datetime import datetime
+
+import requests
+from prefect import flow, get_run_logger, task
+from prefect.deployments import Deployment
+from prefect.infrastructure.docker import DockerContainer, DockerRegistry
+
+# --- Flow definition
+
+
+@task
+def get_city_coordinates(city: str):
+ logger = get_run_logger()
+ cities = {"Paris": (2.3510, 48.8567)}
+ logger.info("Getting {}'s coordinates".format(city))
+ return cities[city]
+
+
+@task
+def get_weather(longitude: float, latitude: float):
+ logger = get_run_logger()
+ logger.info(f"Getting weather of latitude={latitude} and longitude={longitude}")
+ api_endpoint = f"https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&hourly=temperature_2m"
+ response = requests.get(api_endpoint)
+ if response.status_code == 200:
+ weather_data = json.loads(response.text)
+ logger.debug(weather_data)
+ return weather_data
+ else:
+ raise Exception("Failed to query " + api_endpoint)
+
+
+@flow(name="get_paris_weather_docker")
+def get_paris_weather():
+ city_coordinates = get_city_coordinates("Paris")
+ weather_content = get_weather(city_coordinates[0], city_coordinates[1])
+ logger = get_run_logger()
+ logger.info(weather_content)
+ return True
+
+
+# --- Deployment definition
+
+if __name__ == "__main__":
+ from io import BytesIO
+ from docker import APIClient
+
+ flow_identifier = datetime.today().strftime("%Y%m%d%H%M%S-") + str(uuid.uuid4())
+
+ # Mimicking Prefect 1.x image build for Prefect 2.x
+
+ ## 1. Creating Docker build context (including flow files)
+ base_image = f"{os.environ.get('REGISTRY_ENDPOINT')}/weather/base_image:latest"
+ flow_image = (
+ f"{os.environ.get('REGISTRY_ENDPOINT')}/weather/flow_image:{flow_identifier}"
+ )
+ dockerfile = f"""
+ FROM {base_image}
+ RUN mkdir -p /usr/app
+ COPY ./flow /usr/app
+ """
+ with tempfile.TemporaryDirectory() as tmp_path:
+ ### a. Creating archive with context (flow files + Dockerfile) for Docker build API
+ os.makedirs(f"{tmp_path}/build")
+ with open(f"{tmp_path}/build/Dockerfile", "w+") as the_file:
+ the_file.write(dockerfile)
+ shutil.copytree("/usr/app", f"{tmp_path}/build/flow")
+ with tarfile.open(f"{tmp_path}/flow.tar", "w") as tar:
+ tar.add(f"{tmp_path}/build", arcname=".")
+ ### b. Build image with context
+ with open(f"{tmp_path}/flow.tar", "rb") as fh:
+ docker_build_archive = BytesIO(fh.read())
+ cli = APIClient(base_url="unix:///var/run/docker.sock")
+ for line in cli.build(
+ fileobj=docker_build_archive, custom_context=True, rm=True, tag=flow_image
+ ):
+ print(line, flush=True)
+ for line in cli.push(flow_image, stream=True, decode=True):
+ print(line, flush=True)
+
+ ## 2. Registering flow
+ dockerhub = DockerRegistry(
+ username=os.environ.get("REGISTRY_USERNAME"),
+ password=os.environ.get("REGISTRY_PASSWORD"),
+ reauth=True,
+ registry_url=f"{os.environ.get('REGISTRY_SCHEME')}://{os.environ.get('REGISTRY_ENDPOINT')}",
+ )
+ dockerhub.save("docker-storage", overwrite=True)
+ docker_block = DockerContainer(
+ image=flow_image,
+ image_registry=dockerhub,
+ )
+ docker_block.save("docker-storage", overwrite=True)
+
+ deployment = Deployment.build_from_flow(
+ name="get_weather_docker_example",
+ flow=get_paris_weather,
+ infrastructure=docker_block, # storage block is automatically detected from https://github.com/PrefectHQ/prefect/pull/6574/files
+ work_queue_name="flows-example-queue-docker",
+ path="/usr/app",
+ )
+ deployment.apply()
diff --git a/src/prefect-docker-compose-main/client_docker/docker-compose.yml b/src/prefect-docker-compose-main/client_docker/docker-compose.yml
new file mode 100644
index 0000000..5f1f724
--- /dev/null
+++ b/src/prefect-docker-compose-main/client_docker/docker-compose.yml
@@ -0,0 +1,42 @@
+version: "3.8"
+
+services:
+
+ registry:
+ restart: always
+ image: registry:2.8.1
+ ports:
+ - 5000:5000
+ volumes:
+ - ./registry/auth:/auth
+ - registry_data:/data
+ environment:
+ REGISTRY_AUTH: htpasswd
+ REGISTRY_AUTH_HTPASSWD_REALM: Registry
+ REGISTRY_AUTH_HTPASSWD_PATH: /auth/.htpasswd
+ REGISTRY_STORAGE_FILESYSTEM_ROOTDIRECTORY: /data
+
+ # The script should have access to Docker in order to register
+ # the Dockerized script (`execution.Dockerfile`) in a
+ # Docker image later used by the Prefect agent.
+ weather:
+ build: .
+ privileged: true # forced for Docker DinD
+ environment:
+ PREFECT_API_URL: "http://172.17.0.1:4200/api"
+ REGISTRY_ENDPOINT: "172.17.0.1:5000"
+ REGISTRY_SCHEME: "http"
+ REGISTRY_USERNAME: myusername
+ REGISTRY_PASSWORD: test
+ volumes:
+ - ./app:/usr/app:ro
+ - type: bind
+ source: /var/run/docker.sock
+ target: /var/run/docker.sock
+ read_only: true
+ depends_on:
+ - registry
+
+volumes:
+ registry_data:
+ flows_docker:
diff --git a/src/prefect-docker-compose-main/client_docker/entrypoint.sh b/src/prefect-docker-compose-main/client_docker/entrypoint.sh
new file mode 100644
index 0000000..5828727
--- /dev/null
+++ b/src/prefect-docker-compose-main/client_docker/entrypoint.sh
@@ -0,0 +1,3 @@
+#!/bin/sh
+docker login -u=${REGISTRY_USERNAME} -p=${REGISTRY_PASSWORD} "${REGISTRY_SCHEME}://${REGISTRY_ENDPOINT}"
+python3 /usr/app/weather.py
diff --git a/src/prefect-docker-compose-main/client_docker/execution.Dockerfile b/src/prefect-docker-compose-main/client_docker/execution.Dockerfile
new file mode 100644
index 0000000..60e049c
--- /dev/null
+++ b/src/prefect-docker-compose-main/client_docker/execution.Dockerfile
@@ -0,0 +1,4 @@
+FROM python:3.10
+
+RUN apt update && apt install uuid -y
+RUN pip3 install --upgrade pip && pip3 install prefect==2.4.2
diff --git a/src/prefect-docker-compose-main/client_s3/Dockerfile b/src/prefect-docker-compose-main/client_s3/Dockerfile
new file mode 100644
index 0000000..b526131
--- /dev/null
+++ b/src/prefect-docker-compose-main/client_s3/Dockerfile
@@ -0,0 +1,6 @@
+FROM python:3.10
+
+RUN apt update && apt install uuid -y
+RUN pip install prefect==2.4.2 psycopg2-binary==2.9.3 s3fs==2022.8.2 minio==7.1.11
+
+WORKDIR /usr/app
diff --git a/src/prefect-docker-compose-main/client_s3/app/weather.py b/src/prefect-docker-compose-main/client_s3/app/weather.py
new file mode 100644
index 0000000..35dfb7a
--- /dev/null
+++ b/src/prefect-docker-compose-main/client_s3/app/weather.py
@@ -0,0 +1,148 @@
+# A simple example to demonstrate Prefect is working as expected
+# Works with a local folder shared with the agents (/root/.prefect/flows by default).
+
+import io
+import json
+import os
+import uuid
+from datetime import datetime
+
+import requests
+from minio import Minio
+from minio.error import S3Error
+from prefect import flow, get_run_logger, task
+from prefect.deployments import Deployment
+from prefect.filesystems import RemoteFileSystem
+
+# --- Flow definition
+
+
+@task
+def create_bucket(
+ minio_endpoint,
+ minio_access_key,
+ minio_secret_key,
+ minio_use_ssl,
+ bucket_name,
+):
+ client = Minio(
+ minio_endpoint, minio_access_key, minio_secret_key, secure=minio_use_ssl
+ )
+ try:
+ client.make_bucket(bucket_name)
+ except S3Error as ex:
+ if ex.code != "BucketAlreadyOwnedByYou":
+ raise ex
+ print("Flows bucket already exist, skipping.", flush=True)
+
+
+@task
+def get_city_coordinates(city: str):
+ logger = get_run_logger()
+ cities = {"Paris": (2.3510, 48.8567)}
+ logger.info("Getting {}'s coordinates".format(city))
+ return cities[city]
+
+
+@task
+def get_weather(longitude: float, latitude: float):
+ logger = get_run_logger()
+ logger.info(f"Getting weather of latitude={latitude} and longitude={longitude}")
+ api_endpoint = f"https://api.open-meteo.com/v1/forecast?latitude={latitude}&longitude={longitude}&hourly=temperature_2m"
+ response = requests.get(api_endpoint)
+ if response.status_code == 200:
+ weather_data = json.loads(response.text)
+ logger.debug(weather_data)
+ return weather_data
+ else:
+ raise Exception("Failed to query " + api_endpoint)
+
+
+@task
+def add_text_to_bucket(
+ content: str,
+ minio_endpoint,
+ minio_access_key,
+ minio_secret_key,
+ minio_use_ssl,
+ bucket_name,
+):
+ client = Minio(
+ minio_endpoint, minio_access_key, minio_secret_key, secure=minio_use_ssl
+ )
+ content_json = json.dumps(content)
+ client.put_object(
+ object_name=f"{datetime.today().strftime('%Y%m%d%H%M%S')}/weather.txt",
+ bucket_name=bucket_name,
+ data=io.BytesIO(str.encode(content_json)),
+ length=len(content_json),
+ content_type="text/plain",
+ )
+
+
+@flow(name="get_paris_weather_s3")
+def get_paris_weather(
+ minio_endpoint: str,
+ minio_access_key: str,
+ minio_secret_key: str,
+ minio_use_ssl: bool,
+ artifacts_bucket_name: str,
+):
+ city_coordinates = get_city_coordinates("Paris")
+ weather_content = get_weather(city_coordinates[0], city_coordinates[1])
+ create_bucket(
+ minio_endpoint,
+ minio_access_key,
+ minio_secret_key,
+ minio_use_ssl,
+ artifacts_bucket_name,
+ )
+ add_text_to_bucket(
+ weather_content,
+ minio_endpoint,
+ minio_access_key,
+ minio_secret_key,
+ minio_use_ssl,
+ artifacts_bucket_name,
+ )
+ return True
+
+
+# --- Deployment definition
+
+if __name__ == "__main__":
+ bucket_name = os.environ.get("MINIO_PREFECT_FLOWS_BUCKET_NAME")
+ artifacts_bucket_name = os.environ.get("MINIO_PREFECT_ARTIFACTS_BUCKET_NAME")
+ minio_endpoint = os.environ.get("MINIO_ENDPOINT")
+ minio_use_ssl = os.environ.get("MINIO_USE_SSL") == "true"
+ minio_scheme = "https" if minio_use_ssl else "http"
+ minio_access_key = os.environ.get("MINIO_ACCESS_KEY")
+ minio_secret_key = os.environ.get("MINIO_SECRET_KEY")
+
+ flow_identifier = datetime.today().strftime("%Y%m%d%H%M%S-") + str(uuid.uuid4())
+ block_storage = RemoteFileSystem(
+ basepath=f"s3://{bucket_name}/{flow_identifier}",
+ key_type="hash",
+ settings=dict(
+ use_ssl=minio_use_ssl,
+ key=minio_access_key,
+ secret=minio_secret_key,
+ client_kwargs=dict(endpoint_url=f"{minio_scheme}://{minio_endpoint}"),
+ ),
+ )
+ block_storage.save("s3-storage", overwrite=True)
+
+ deployment = Deployment.build_from_flow(
+ name="get_weather_s3_example",
+ flow=get_paris_weather,
+ storage=RemoteFileSystem.load("s3-storage"),
+ work_queue_name="flows-example-queue",
+ parameters={
+ "minio_endpoint": minio_endpoint,
+ "minio_access_key": minio_access_key,
+ "minio_secret_key": minio_secret_key,
+ "minio_use_ssl": minio_use_ssl,
+ "artifacts_bucket_name": artifacts_bucket_name,
+ },
+ )
+ deployment.apply()
diff --git a/src/prefect-docker-compose-main/client_s3/docker-compose.yml b/src/prefect-docker-compose-main/client_s3/docker-compose.yml
new file mode 100644
index 0000000..494046a
--- /dev/null
+++ b/src/prefect-docker-compose-main/client_s3/docker-compose.yml
@@ -0,0 +1,37 @@
+version: "3.7"
+
+services:
+
+ minio:
+ image: minio/minio:RELEASE.2022-09-07T22-25-02Z
+ command: server --console-address ":9001" /data
+ ports:
+ - 9000:9000
+ - 9001:9001
+ volumes:
+ - /srv/docker/prefect/minio:/data
+ environment:
+ MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
+ MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
+ healthcheck:
+ test: ["CMD", "curl", "-f", "http://localhost:9000/minio/health/live"]
+ interval: 5s
+ timeout: 3s
+ retries: 10
+
+ weather:
+ build: .
+ command: python3 /usr/app/weather.py
+ volumes:
+ - ./app:/usr/app:ro
+ environment:
+ PREFECT_API_URL: "http://172.17.0.1:4200/api"
+ MINIO_USE_SSL: ${MINIO_USE_SSL}
+ MINIO_ACCESS_KEY: ${MINIO_ACCESS_KEY}
+ MINIO_SECRET_KEY: ${MINIO_SECRET_KEY}
+ MINIO_ENDPOINT: ${MINIO_ENDPOINT} # Must be accessible from Agent
+ MINIO_PREFECT_FLOWS_BUCKET_NAME: ${MINIO_PREFECT_FLOWS_BUCKET_NAME}
+ MINIO_PREFECT_ARTIFACTS_BUCKET_NAME: ${MINIO_PREFECT_ARTIFACTS_BUCKET_NAME}
+ depends_on:
+ minio:
+ condition: service_healthy
diff --git a/src/prefect-docker-compose-main/docker_interface.png b/src/prefect-docker-compose-main/docker_interface.png
new file mode 100644
index 0000000..0cb3922
Binary files /dev/null and b/src/prefect-docker-compose-main/docker_interface.png differ
diff --git a/src/prefect-docker-compose-main/prefect_schema_principle.drawio b/src/prefect-docker-compose-main/prefect_schema_principle.drawio
new file mode 100644
index 0000000..81aa1ca
--- /dev/null
+++ b/src/prefect-docker-compose-main/prefect_schema_principle.drawio
@@ -0,0 +1 @@
+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
\ No newline at end of file
diff --git a/src/prefect-docker-compose-main/prefect_schema_principle.jpg b/src/prefect-docker-compose-main/prefect_schema_principle.jpg
new file mode 100644
index 0000000..d067574
Binary files /dev/null and b/src/prefect-docker-compose-main/prefect_schema_principle.jpg differ
diff --git a/src/prefect-docker-compose-main/server/Dockerfile b/src/prefect-docker-compose-main/server/Dockerfile
new file mode 100644
index 0000000..8d119f7
--- /dev/null
+++ b/src/prefect-docker-compose-main/server/Dockerfile
@@ -0,0 +1,4 @@
+FROM prefecthq/prefect:2.4.2-python3.10
+
+RUN apt update && \
+ pip install psycopg2-binary==2.9.3 s3fs==2022.8.2
diff --git a/src/prefect-docker-compose-main/server/docker-compose.yml b/src/prefect-docker-compose-main/server/docker-compose.yml
new file mode 100644
index 0000000..c3c3d6a
--- /dev/null
+++ b/src/prefect-docker-compose-main/server/docker-compose.yml
@@ -0,0 +1,48 @@
+version: "3.7"
+
+services:
+
+ postgres:
+ command:
+ - postgres
+ - -c
+ - max_connections=150
+ environment:
+ POSTGRES_USER: ${POSTGRES_USER}
+ POSTGRES_PASSWORD: ${POSTGRES_PASSWORD}
+ POSTGRES_DB: ${POSTGRES_DB}
+ volumes:
+ - postgres:/var/lib/postgresql/data
+ healthcheck:
+ interval: 10s
+ retries: 60
+ start_period: 2s
+ test: pg_isready -q -d $${POSTGRES_DB} -U $${POSTGRES_USER} | grep "accepting connections" || exit 1
+ timeout: 2s
+ image: postgres:14
+ restart: always
+
+ orion:
+ restart: always
+ build: .
+
+ command: prefect orion start
+ ports:
+ - 4200:4200
+ depends_on:
+ postgres:
+ condition: service_started
+ volumes:
+ - prefect_data:/root/.prefect
+ - prefect_flows:/flows
+ environment:
+ PREFECT_ORION_API_HOST: 0.0.0.0
+ PREFECT_ORION_DATABASE_CONNECTION_URL: ${DB_CONNECTION_URL}
+ PREFECT_ORION_ANALYTICS_ENABLED: "false"
+ PREFECT_LOGGING_SERVER_LEVEL: WARNING
+ PREFECT_API_URL: ${PREFECT_API_URL}
+
+volumes:
+ postgres:
+ prefect_data:
+ prefect_flows:
\ No newline at end of file
diff --git a/src/vscode-dotnet-project/CODE_OF_CONDUCT.md b/src/vscode-dotnet-project/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..f9ba8cf
--- /dev/null
+++ b/src/vscode-dotnet-project/CODE_OF_CONDUCT.md
@@ -0,0 +1,9 @@
+# Microsoft Open Source Code of Conduct
+
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
+
+Resources:
+
+- [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/)
+- [Microsoft Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/)
+- Contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with questions or concerns
diff --git a/src/vscode-dotnet-project/LICENSE b/src/vscode-dotnet-project/LICENSE
new file mode 100644
index 0000000..4b1ad51
--- /dev/null
+++ b/src/vscode-dotnet-project/LICENSE
@@ -0,0 +1,21 @@
+ MIT License
+
+ Copyright (c) Microsoft Corporation. All rights reserved.
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in all
+ copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+ SOFTWARE
diff --git a/src/vscode-dotnet-project/Program.cs b/src/vscode-dotnet-project/Program.cs
new file mode 100644
index 0000000..ff8b47e
--- /dev/null
+++ b/src/vscode-dotnet-project/Program.cs
@@ -0,0 +1,34 @@
+var builder = WebApplication.CreateBuilder(args);
+var app = builder.Build();
+
+app.Urls.Add("http://localhost:5000");
+
+app.MapGet("/", () => "Hello World!");
+
+app.MapGet("/{cityName}/weather", GetWeatherByCity);
+
+app.Run();
+
+
+Weather GetWeatherByCity(string cityName)
+{
+ app.Logger.LogInformation($"Weather requested for {cityName}.");
+ var weather = new Weather(cityName);
+ return weather;
+}
+
+public record Weather
+{
+ public string City { get; set; }
+
+ public Weather(string city)
+ {
+ City = city;
+ Conditions = "Cloudy";
+ // Temperature here is in celsius degrees, hence the 0-40 range.
+ Temperature = new Random().Next(0,40).ToString();
+ }
+
+ public string Conditions { get; set; }
+ public string Temperature { get; set; }
+}
\ No newline at end of file
diff --git a/src/vscode-dotnet-project/README.md b/src/vscode-dotnet-project/README.md
new file mode 100644
index 0000000..d239cfa
--- /dev/null
+++ b/src/vscode-dotnet-project/README.md
@@ -0,0 +1,109 @@
+# Try Out Development Containers: .NET
+
+[![Open in Dev Containers](https://img.shields.io/static/v1?label=Dev%20Containers&message=Open&color=blue&logo=visualstudiocode)](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode-remote-try-dotnet)
+
+
+A **development container** is a running container with a well-defined tool/runtime stack and its prerequisites. You can try out development containers with **[GitHub Codespaces](https://github.com/features/codespaces)** or **[Visual Studio Code Dev Containers](https://aka.ms/vscode-remote/containers)**.
+
+This is a sample project that lets you try out either option in a few easy steps. We have a variety of other [vscode-remote-try-*](https://github.com/search?q=org%3Amicrosoft+vscode-remote-try-&type=Repositories) sample projects, too.
+
+> **Note:** If you already have a Codespace or dev container, you can jump to the [Things to try](#things-to-try) section.
+
+## Setting up the development container
+
+### GitHub Codespaces
+Follow these steps to open this sample in a Codespace:
+1. Click the **Code** drop-down menu.
+2. Click on the **Codespaces** tab.
+3. Click **Create codespace on main** .
+
+For more info, check out the [GitHub documentation](https://docs.github.com/en/free-pro-team@latest/github/developing-online-with-codespaces/creating-a-codespace#creating-a-codespace).
+
+### VS Code Dev Containers
+
+If you already have VS Code and Docker installed, you can click the badge above or [here](https://vscode.dev/redirect?url=vscode://ms-vscode-remote.remote-containers/cloneInVolume?url=https://github.com/microsoft/vscode-remote-try-dotnet) to get started. Clicking these links will cause VS Code to automatically install the Dev Containers extension if needed, clone the source code into a container volume, and spin up a dev container for use.
+
+Follow these steps to open this sample in a container using the VS Code Dev Containers extension:
+
+1. If this is your first time using a development container, please ensure your system meets the pre-reqs (i.e. have Docker installed) in the [getting started steps](https://aka.ms/vscode-remote/containers/getting-started).
+
+2. To use this repository, you can either open the repository in an isolated Docker volume:
+
+ - Press F1 and select the **Dev Containers: Try a Sample...** command.
+ - Choose the ".NET Core" sample, wait for the container to start, and try things out!
+ > **Note:** Under the hood, this will use the **Dev Containers: Clone Repository in Container Volume...** command to clone the source code in a Docker volume instead of the local filesystem. [Volumes](https://docs.docker.com/storage/volumes/) are the preferred mechanism for persisting container data.
+
+ Or open a locally cloned copy of the code:
+
+ - Clone this repository to your local filesystem.
+ - Press F1 and select the **Dev Containers: Open Folder in Container...** command.
+ - Select the cloned copy of this folder, wait for the container to start, and try things out!
+
+3. If you want to enable **HTTPS**, see [enabling HTTPS](#enabling-https) to reuse your local development cert in the container.
+
+## Things to try
+
+Once you have this sample opened, you'll be able to work with it like you would locally.
+
+Some things to try:
+
+1. **Restore Packages:** When notified by the C# extension to install packages, click Restore to trigger the process from inside the container! You can also execute `dotnet restore` command in a terminal.
+
+2. **Edit:**
+ - Open `Program.cs`
+ - Try adding some code and check out the language features.
+ - Make a spelling mistake and notice it is detected. The [Code Spell Checker](https://marketplace.visualstudio.com/items?itemName=streetsidesoftware.code-spell-checker) extension was automatically installed because it is referenced in `.devcontainer/devcontainer.json`.
+ - Also notice that the [C#](https://marketplace.visualstudio.com/items?itemName=ms-dotnettools.csharp) extension is installed. Tools are installed in the `mcr.microsoft.com/devcontainers/dotnet` image and Dev Container settings and metadata are automatically picked up from [image labels](https://containers.dev/implementors/reference/#labels).
+
+
+4. **Build, Run, and Debug:**
+ - Open `Program.cs`
+ - Add a breakpoint (e.g. on line 16).
+ - Press F5 to launch the app in the container.
+ - Navigate to the weather endpoint, for example, [http://localhost:5000/paris/weather](http://localhost:5000/paris/weather).
+ - Once the breakpoint is hit, try hovering over variables, examining locals, and more.
+ - Continue (F5). You can connect to the server in the container by either:
+ - Clicking on `Open in Browser` in the notification telling you: `Your service running on port 5000 is available`.
+ - Clicking the globe icon in the 'Ports' view. The 'Ports' view gives you an organized table of your forwarded ports, and you can access it with the command **Ports: Focus on Ports View**.
+ - Notice port 5000 in the 'Ports' view is labeled "Hello Remote World." In `devcontainer.json`, you can set `"portsAttributes"`, such as a label for your forwarded ports and the action to be taken when the port is autoforwarded.
+
+ > **Note:** In Dev Containers, you can access your app at `http://localhost:5000` in a local browser. But in a browser-based Codespace, you must click the link from the notification or the `Ports` view so that the service handles port forwarding in the browser and generates the correct URL.
+
+5. **Rebuild or update your container**
+
+ You may want to make changes to your container, such as installing a different version of a software or forwarding a new port. You'll rebuild your container for your changes to take effect.
+
+ **Open browser automatically:** As an example change, let's update the `portsAttributes` in the `.devcontainer/devcontainer.json` file to open a browser when our port is automatically forwarded.
+
+ - Open the `.devcontainer/devcontainer.json` file.
+ - Modify the `"onAutoForward"` attribute in your `portsAttributes` from `"notify"` to `"openBrowser"`.
+ - Press F1 and select the **Dev Containers: Rebuild Container** or **Codespaces: Rebuild Container** command so the modifications are picked up.
+
+5. **Install Node.js using a Dev Container Feature:**
+ - Press F1 and select the **Dev Containers: Configure Container Features...** or **Codespaces: Configure Container Features...** command.
+ - Type "node" in the text box at the top.
+ - Check the check box next to "Node.js (via nvm) and yarn" (published by devcontainers)
+ - Click OK
+ - Press F1 and select the **Dev Containers: Rebuild Container** or **Codespaces: Rebuild Container** command so the modifications are picked up.
+
+## Contributing
+
+This project welcomes contributions and suggestions. Most contributions require you to agree to a
+Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
+the rights to use your contribution. For details, visit https://cla.opensource.microsoft.com.
+
+When you submit a pull request, a CLA bot will automatically determine whether you need to provide
+a CLA and decorate the PR appropriately (e.g., status check, comment). Simply follow the instructions
+provided by the bot. You will only need to do this once across all repos using our CLA.
+
+This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
+For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
+contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
+
+## Trademarks
+
+This project may contain trademarks or logos for projects, products, or services. Authorized use of Microsoft
+trademarks or logos is subject to and must follow
+[Microsoft's Trademark & Brand Guidelines](https://www.microsoft.com/en-us/legal/intellectualproperty/trademarks/usage/general).
+Use of Microsoft trademarks or logos in modified versions of this project must not cause confusion or imply Microsoft sponsorship.
+Any use of third-party trademarks or logos are subject to those third-party's policies.
diff --git a/src/vscode-dotnet-project/SECURITY.md b/src/vscode-dotnet-project/SECURITY.md
new file mode 100644
index 0000000..e138ec5
--- /dev/null
+++ b/src/vscode-dotnet-project/SECURITY.md
@@ -0,0 +1,41 @@
+
+
+## Security
+
+Microsoft takes the security of our software products and services seriously, which includes all source code repositories managed through our GitHub organizations, which include [Microsoft](https://github.com/microsoft), [Azure](https://github.com/Azure), [DotNet](https://github.com/dotnet), [AspNet](https://github.com/aspnet), [Xamarin](https://github.com/xamarin), and [our GitHub organizations](https://opensource.microsoft.com/).
+
+If you believe you have found a security vulnerability in any Microsoft-owned repository that meets [Microsoft's definition of a security vulnerability](https://aka.ms/opensource/security/definition), please report it to us as described below.
+
+## Reporting Security Issues
+
+**Please do not report security vulnerabilities through public GitHub issues.**
+
+Instead, please report them to the Microsoft Security Response Center (MSRC) at [https://msrc.microsoft.com/create-report](https://aka.ms/opensource/security/create-report).
+
+If you prefer to submit without logging in, send email to [secure@microsoft.com](mailto:secure@microsoft.com). If possible, encrypt your message with our PGP key; please download it from the [Microsoft Security Response Center PGP Key page](https://aka.ms/opensource/security/pgpkey).
+
+You should receive a response within 24 hours. If for some reason you do not, please follow up via email to ensure we received your original message. Additional information can be found at [microsoft.com/msrc](https://aka.ms/opensource/security/msrc).
+
+Please include the requested information listed below (as much as you can provide) to help us better understand the nature and scope of the possible issue:
+
+ * Type of issue (e.g. buffer overflow, SQL injection, cross-site scripting, etc.)
+ * Full paths of source file(s) related to the manifestation of the issue
+ * The location of the affected source code (tag/branch/commit or direct URL)
+ * Any special configuration required to reproduce the issue
+ * Step-by-step instructions to reproduce the issue
+ * Proof-of-concept or exploit code (if possible)
+ * Impact of the issue, including how an attacker might exploit the issue
+
+This information will help us triage your report more quickly.
+
+If you are reporting for a bug bounty, more complete reports can contribute to a higher bounty award. Please visit our [Microsoft Bug Bounty Program](https://aka.ms/opensource/security/bounty) page for more details about our active programs.
+
+## Preferred Languages
+
+We prefer all communications to be in English.
+
+## Policy
+
+Microsoft follows the principle of [Coordinated Vulnerability Disclosure](https://aka.ms/opensource/security/cvd).
+
+
diff --git a/src/vscode-dotnet-project/appsettings.Development.json b/src/vscode-dotnet-project/appsettings.Development.json
new file mode 100644
index 0000000..ff66ba6
--- /dev/null
+++ b/src/vscode-dotnet-project/appsettings.Development.json
@@ -0,0 +1,8 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ }
+}
diff --git a/src/vscode-dotnet-project/appsettings.HttpsDevelopment.json b/src/vscode-dotnet-project/appsettings.HttpsDevelopment.json
new file mode 100644
index 0000000..8f41d8b
--- /dev/null
+++ b/src/vscode-dotnet-project/appsettings.HttpsDevelopment.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Debug",
+ "System": "Information",
+ "Microsoft": "Information"
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/vscode-dotnet-project/appsettings.json b/src/vscode-dotnet-project/appsettings.json
new file mode 100644
index 0000000..4d56694
--- /dev/null
+++ b/src/vscode-dotnet-project/appsettings.json
@@ -0,0 +1,9 @@
+{
+ "Logging": {
+ "LogLevel": {
+ "Default": "Information",
+ "Microsoft.AspNetCore": "Warning"
+ }
+ },
+ "AllowedHosts": "*"
+}
diff --git a/src/vscode-dotnet-project/vscode-remote-try-dotnet.csproj b/src/vscode-dotnet-project/vscode-remote-try-dotnet.csproj
new file mode 100644
index 0000000..06fd153
--- /dev/null
+++ b/src/vscode-dotnet-project/vscode-remote-try-dotnet.csproj
@@ -0,0 +1,10 @@
+
+
+
+ net7.0
+ enable
+ enable
+ vscode_remote_try_dotnet
+
+
+