diff --git a/.gitea/workflows/README-nomad-job.md b/.gitea/workflows/README-nomad-job.md new file mode 100644 index 0000000..44ad95d --- /dev/null +++ b/.gitea/workflows/README-nomad-job.md @@ -0,0 +1,88 @@ + +### **Top-Level Job Configuration** +#### `job` +- **Purpose**: Defines the Nomad job. +- **Attributes**: + - `region`: Specifies the Nomad region where the job should run. [Reference: Nomad Regions](https://developer.hashicorp.com/nomad/docs/regions) + - `datacenters`: Lists the datacenters in which the job is eligible to run. [Reference: Job Placement](https://developer.hashicorp.com/nomad/docs/job-specification/datacenters) + - `type`: Defines the job type (`service` in this case). Service jobs are typically long-running. [Reference: Job Types](https://developer.hashicorp.com/nomad/docs/job-specification/job) + +--- + +### **Update Block** +#### `update` +- **Purpose**: Specifies rolling update strategy for service jobs. +- **Attributes**: + - `stagger`: Time between starting updates for each allocation. + - `max_parallel`: Number of allocations to update simultaneously. + - `progress_deadline`: Time to wait for a deployment to progress before failing. +- [Reference: Update Stanza](https://developer.hashicorp.com/nomad/docs/job-specification/update) + +--- + +### **Group Configuration** +#### `group` +- **Purpose**: Defines a group of tasks that should be placed together on the same node. +- **Attributes**: + - `count`: Number of task groups to run. +- [Reference: Task Group](https://developer.hashicorp.com/nomad/docs/job-specification/group) + +--- + +### **Network Configuration** +#### `network` +- **Purpose**: Specifies networking requirements for the task group. +- **Attributes**: + - `port`: Defines a named port mapping for the task group. + - `to`: Specifies the internal port the application listens to within the container. +- [Reference: Network Stanza](https://developer.hashicorp.com/nomad/docs/job-specification/network) + +--- + +### **Consul Integration** +#### `service` +- **Purpose**: Registers the service with Consul for discovery. +- **Attributes**: + - `provider`: Specifies the service discovery provider (`consul`). + - `name`: The name of the service in Consul. + - `port`: References the named port defined in the `network` block. + - `tags`: Metadata tags to annotate the service (e.g., for routing in Traefik). + - `check`: Defines health check parameters for the service. + - `name`: Name of the health check. + - `type`: Health check type (`tcp` in this case). + - `interval`: Frequency of the health check. + - `timeout`: Maximum duration for the health check. +- [Reference: Consul Service Stanza](https://developer.hashicorp.com/nomad/docs/job-specification/service) + +--- + +### **Task Configuration** +#### `task` +- **Purpose**: Defines a single executable unit of work. +- **Attributes**: + - `driver`: Specifies the driver (`docker` in this case). + - `config`: Driver-specific configuration. + - `image`: Docker image for the task. + - `ports`: References the named port defined in the `network` block. + - `env`: Sets environment variables for the task. + - `resources`: Specifies resource requirements for the task. + - `cpu`: CPU allocation in MHz. + - `memory`: Memory allocation in MB. +- [Reference: Task Stanza](https://developer.hashicorp.com/nomad/docs/job-specification/task) + +--- + +### **Dynamic Port Allocation** +#### `${NOMAD_PORT_}` +- **Purpose**: Refers to the dynamically allocated host port mapped to the internal container port. +- **Usage**: This is used in the `env` and `tags` sections to dynamically configure the application and Consul registration. +- [Reference: Port Variables](https://developer.hashicorp.com/nomad/docs/runtime/environment#ports) + +--- + +### **Key Takeaways** +1. This job defines a **service** that runs as a Docker container, listens on a dynamically assigned port, and registers itself in **Consul** for service discovery. +2. The `network` stanza ensures that Nomad assigns a dynamic host port, while the `${NOMAD_PORT_}` variable is used to pass this information to the container and Consul. +3. The `update` stanza ensures smooth rolling updates for the service. + +For further details and advanced configurations, refer to the [Nomad Job Specification Documentation](https://developer.hashicorp.com/nomad/docs/job-specification). \ No newline at end of file diff --git a/.gitea/workflows/main.yml.tmpl b/.gitea/workflows/main.yml.tmpl new file mode 100644 index 0000000..4da38f5 --- /dev/null +++ b/.gitea/workflows/main.yml.tmpl @@ -0,0 +1,61 @@ +name: Build, Push, and Deploy to Nomad + +on: + push: + branches: + - main + +jobs: + docker-nomad: + runs-on: self-hosted + steps: + - name: Check out code + uses: actions/checkout@v3 + + - name: Log in to Container Registry + run: echo ${{ secrets.password }} | docker login registry.i80.dk -u ${{ secrets.username }} --password-stdin + + - name: Build Docker Image + run: | + COMMIT_HASH=$(git rev-parse --short HEAD) + docker build -t registry.i80.dk/gitea/portugalfaq:latest -t registry.i80.dk/gitea/portugalfaq:${COMMIT_HASH} . + + + - name: Push Docker Image + run: | + COMMIT_HASH=$(git rev-parse --short HEAD) + echo "registry.i80.dk/gitea/portugalfaq:latest" + echo "registry.i80.dk/gitea/portugalfaq:${COMMIT_HASH}" + docker push registry.i80.dk/gitea/portugalfaq:${COMMIT_HASH} + docker push registry.i80.dk/gitea/portugalfaq:latest + + + - name: Validate Nomad Job + env: + NOMAD_ADDR: https://nomad.i80.dk + run: nomad job validate .gitea/workflows/nomad-job.hcl + + - name: Stop old deployment + env: + NOMAD_ADDR: https://nomad.i80.dk + run: nomad job stop -purge -no-shutdown-delay portugalfaq + continue-on-error: true + + + - name: Apply Nomad Job + env: + NOMAD_ADDR: https://nomad.i80.dk + run: nomad job run .gitea/workflows/nomad-job.hcl + + - name: Update Nginx Configuration + run: ssh runner@nomad sudo /opt/nginx_updater/venv/bin/python3 /opt/nginx_updater/nginx_updater.py portugalfaq + + + +# - name: Restart Nomad Job +# env: +# NOMAD_ADDR: https://nomad.i80.dk +# run: | +# nomad job stop portugalfaq +# sleep 5 # Optional: Wait to ensure the old allocation is stopped +# nomad job run .gitea/workflows/nomad-job.hcl diff --git a/.gitea/workflows/nomad-job.hcl.tmpl b/.gitea/workflows/nomad-job.hcl.tmpl new file mode 100644 index 0000000..42bb3c8 --- /dev/null +++ b/.gitea/workflows/nomad-job.hcl.tmpl @@ -0,0 +1,60 @@ +job "portugalfaq" { + region = "global" + datacenters = ["dc1"] + type = "service" + + update { + stagger = "60s" + max_parallel = 1 + progress_deadline = "6m" + } + + group "portugalfaq-group" { + count = 1 + + network { + port "port-app" { + to = 9912 # Internal application port + } + } + + # Register the service with Consul + service { + provider = "consul" + name = "portugalfaq" + port = "port-app" + + # Traefik-specific tags for routing + tags = [ + "PORT=${NOMAD_PORT_port-app}" + ] + + # Define a health check using TCP + check { + name = "tcp_check" + type = "tcp" + interval = "10s" + timeout = "2s" + } + } + + task "portugalfaq-task" { + driver = "docker" + + config { + image = "registry.i80.dk/gitea/portugalfaq:latest" + ports = ["port-app"] + } + + env { + APP_ENV = "production" + PORT = "${NOMAD_PORT_port-app}" + } + + resources { + cpu = 250 + memory = 80 + } + } + } +} diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 0000000..cc33f2b --- /dev/null +++ b/Dockerfile @@ -0,0 +1,25 @@ +# Base image with Python 3.11 +FROM python:3.11-slim + +# Set the working directory in the container +WORKDIR /app + +# Copy the requirements file to the working directory +COPY requirements.txt . + +# Install Python dependencies +RUN pip install --no-cache-dir -r requirements.txt + +# Copy the rest of the application code +COPY . . + +# Expose the port the app runs on (default Flask port) +EXPOSE 5000 + +# Define environment variables +ENV FLASK_APP=app.py +ENV FLASK_RUN_HOST=0.0.0.0 +ENV PORT=5000 +# Command to run the application +#CMD ["flask", "run", "--port", "${PORT}"] +CMD flask run --port ${PORT} \ No newline at end of file