Subham9126 commited on
Commit
0383bfc
·
verified ·
1 Parent(s): 509d686

Upload 7 files

Browse files
Files changed (7) hide show
  1. Dockerfile +29 -16
  2. config.sh +39 -0
  3. entrypoint.sh +42 -0
  4. nginx.conf +65 -0
  5. refresh_service.py +76 -0
  6. requirements.txt +7 -2
  7. supervisord.conf +38 -0
Dockerfile CHANGED
@@ -1,24 +1,37 @@
1
- FROM apache/airflow:2.9.2-python3.11
2
 
3
- USER root
4
- RUN apt-get update && apt-get install -y git && apt-get clean && rm -rf /var/lib/apt/lists/*
5
 
6
- COPY startup.sh /startup.sh
7
- RUN chmod +x /startup.sh
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  USER airflow
10
 
11
- ENV AIRFLOW__CORE__LOAD_EXAMPLES=False
12
- ENV AIRFLOW__CORE__EXECUTOR=LocalExecutor
13
- ENV AIRFLOW__CORE__DAGS_FOLDER=/opt/airflow/dags
14
- ENV AIRFLOW__SCHEDULER__DAG_DIR_LIST_INTERVAL=30
15
- ENV AIRFLOW__LOGGING__LOGGING_LEVEL=ERROR
16
- ENV AIRFLOW__LOGGING__BASE_LOG_FOLDER=/tmp/airflow/logs
17
- ENV AIRFLOW__LOGGING__DAG_PROCESSOR_MANAGER_LOG_LOCATION=/tmp/airflow/logs/dag_processor_manager/dag_processor_manager.log
18
- ENV AIRFLOW__SCHEDULER__CHILD_PROCESS_LOG_DIRECTORY=/tmp/airflow/logs/scheduler
19
- ENV AIRFLOW__WEBSERVER__EXPOSE_CONFIG=False
20
- ENV AIRFLOW__WEBSERVER__WEB_SERVER_PORT=7860
 
 
21
 
22
  EXPOSE 7860
23
 
24
- ENTRYPOINT ["/startup.sh"]
 
1
+ FROM ubuntu:22.04
2
 
3
+ ENV DEBIAN_FRONTEND=noninteractive
4
+ ENV AIRFLOW_HOME=/opt/airflow
5
 
6
+ RUN apt-get update && apt-get install -y --no-install-recommends \
7
+ python3 \
8
+ python3-pip \
9
+ python3-venv \
10
+ nginx \
11
+ git \
12
+ supervisor \
13
+ curl \
14
+ && rm -rf /var/lib/apt/lists/* \
15
+ && useradd -m -u 1000 airflow
16
+
17
+ RUN mkdir -p /var/log/supervisor /var/log/nginx /run/nginx /var/lib/nginx /opt/airflow/dags \
18
+ && chown -R airflow:airflow /opt/airflow /var/log/supervisor /var/log/nginx /run/nginx /var/lib/nginx
19
 
20
  USER airflow
21
 
22
+ ENV PATH="/home/airflow/.local/bin:${PATH}"
23
+
24
+ COPY --chown=airflow:airflow requirements.txt /tmp/requirements.txt
25
+ RUN pip install --no-cache-dir -r /tmp/requirements.txt
26
+
27
+ COPY --chown=airflow:airflow config.sh /config.sh
28
+ COPY --chown=airflow:airflow supervisord.conf /etc/supervisord.conf
29
+ COPY --chown=airflow:airflow nginx.conf /etc/nginx/nginx.conf
30
+ COPY --chown=airflow:airflow entrypoint.sh /entrypoint.sh
31
+ COPY --chown=airflow:airflow refresh_service.py /refresh_service.py
32
+
33
+ RUN chmod +x /entrypoint.sh /config.sh
34
 
35
  EXPOSE 7860
36
 
37
+ ENTRYPOINT ["/bin/bash", "/entrypoint.sh"]
config.sh ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ # ===========================================
3
+ # Airflow Configuration - SINGLE SOURCE OF TRUTH
4
+ # ===========================================
5
+ # All configurable values are defined here with defaults
6
+ # Override by setting environment variables or HF Secrets
7
+
8
+ # ---- Directory Paths ----
9
+ export AIRFLOW_HOME="${AIRFLOW_HOME:-/opt/airflow}"
10
+ export DAGS_DIR="${AIRFLOW_HOME}/dags"
11
+ export LOGS_DIR="${AIRFLOW_HOME}/logs"
12
+
13
+ # ---- Database Connection (Set via HF Secret for production) ----
14
+ export AIRFLOW__DATABASE__SQL_ALCHEMY_CONN="${AIRFLOW__DATABASE__SQL_ALCHEMY_CONN:-postgresql://postgres.ffetkispaxytayrnmxvj:uKInpRkBXsCUfVg1@aws-1-ap-south-1.pooler.supabase.com:5432/postgres}"
15
+
16
+ # ---- DAG Repository ----
17
+ export DAG_REPO_URL="${DAG_REPO_URL:-https://github.com/subhamgiri460/myworkflows.git}"
18
+ export DAG_REPO_BRANCH="${DAG_REPO_BRANCH:-main}"
19
+
20
+ # ---- Admin Credentials (Set via HF Secrets for production) ----
21
+ export AIRFLOW_ADMIN_USER="${AIRFLOW_ADMIN_USER:-admin}"
22
+ export AIRFLOW_ADMIN_PASSWORD="${AIRFLOW_ADMIN_PASSWORD:-admin}"
23
+
24
+ # ---- Internal Ports ----
25
+ export AIRFLOW_WEB_PORT="${AIRFLOW_WEB_PORT:-8080}"
26
+ export REFRESH_SERVICE_PORT="${REFRESH_SERVICE_PORT:-5000}"
27
+ export NGINX_PORT="${NGINX_PORT:-7860}"
28
+
29
+ # ---- Airflow Core Settings ----
30
+ export AIRFLOW__CORE__LOAD_EXAMPLES="${AIRFLOW__CORE__LOAD_EXAMPLES:-False}"
31
+ export AIRFLOW__CORE__EXECUTOR="${AIRFLOW__CORE__EXECUTOR:-LocalExecutor}"
32
+
33
+ # ---- Airflow Webserver Settings ----
34
+ export AIRFLOW__WEBSERVER__WEB_SERVER_PORT="${AIRFLOW_WEB_PORT}"
35
+ export AIRFLOW__WEBSERVER__WEB_SERVER_MASTER_TIMEOUT="${AIRFLOW__WEBSERVER__WEB_SERVER_MASTER_TIMEOUT:-300}"
36
+ export AIRFLOW__WEBSERVER__WORKER_CLASS="${AIRFLOW__WEBSERVER__WORKER_CLASS:-gevent}"
37
+
38
+ # ---- Airflow Scheduler Settings ----
39
+ export AIRFLOW__SCHEDULER__DAG_DIR_LIST_INTERVAL="${AIRFLOW__SCHEDULER__DAG_DIR_LIST_INTERVAL:-30}"
entrypoint.sh ADDED
@@ -0,0 +1,42 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/bin/bash
2
+ set -e
3
+
4
+ echo "=== Loading configuration ==="
5
+ source /config.sh
6
+
7
+ echo "Configuration:"
8
+ echo " DAG_REPO_URL: ${DAG_REPO_URL}"
9
+ echo " DAG_REPO_BRANCH: ${DAG_REPO_BRANCH}"
10
+ echo " DAGS_DIR: ${DAGS_DIR}"
11
+ echo " AIRFLOW_WEB_PORT: ${AIRFLOW_WEB_PORT}"
12
+ echo " REFRESH_SERVICE_PORT: ${REFRESH_SERVICE_PORT}"
13
+
14
+ echo ""
15
+ echo "=== Syncing DAG repository ==="
16
+ if [ ! -d "${DAGS_DIR}/.git" ]; then
17
+ rm -rf "${DAGS_DIR:?}"/* 2>/dev/null || true
18
+ git clone --depth 1 --branch "${DAG_REPO_BRANCH}" "${DAG_REPO_URL}" "${DAGS_DIR}"
19
+ echo "Repository cloned successfully"
20
+ else
21
+ cd "${DAGS_DIR}"
22
+ git fetch origin "${DAG_REPO_BRANCH}" && git reset --hard "origin/${DAG_REPO_BRANCH}"
23
+ echo "Repository updated successfully"
24
+ fi
25
+
26
+ echo ""
27
+ echo "=== Running database migrations ==="
28
+ airflow db migrate || true
29
+
30
+ echo ""
31
+ echo "=== Creating admin user ==="
32
+ airflow users create \
33
+ --username "${AIRFLOW_ADMIN_USER}" \
34
+ --firstname Admin \
35
+ --lastname User \
36
+ --role Admin \
37
+ --email admin@example.com \
38
+ --password "${AIRFLOW_ADMIN_PASSWORD}" || true
39
+
40
+ echo ""
41
+ echo "=== Starting services ==="
42
+ exec /usr/bin/supervisord -c /etc/supervisord.conf
nginx.conf ADDED
@@ -0,0 +1,65 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ worker_processes 1;
2
+ error_log /var/log/nginx/error.log warn;
3
+ pid /run/nginx/nginx.pid;
4
+
5
+ events {
6
+ worker_connections 1024;
7
+ }
8
+
9
+ http {
10
+ include /etc/nginx/mime.types;
11
+ default_type application/octet-stream;
12
+
13
+ log_format main '$remote_addr - $remote_user [$time_local] "$request" '
14
+ '$status $body_bytes_sent "$http_referer" "$http_user_agent"';
15
+
16
+ access_log /var/log/nginx/access.log main;
17
+ sendfile on;
18
+ keepalive_timeout 65;
19
+
20
+ client_body_temp_path /run/nginx/client_temp;
21
+ proxy_temp_path /run/nginx/proxy_temp;
22
+ fastcgi_temp_path /run/nginx/fastcgi_temp;
23
+ uwsgi_temp_path /run/nginx/uwsgi_temp;
24
+ scgi_temp_path /run/nginx/scgi_temp;
25
+
26
+ upstream airflow {
27
+ server 127.0.0.1:8080;
28
+ }
29
+
30
+ upstream refresh {
31
+ server 127.0.0.1:5000;
32
+ }
33
+
34
+ server {
35
+ listen 7860;
36
+ server_name _;
37
+ client_max_body_size 100M;
38
+
39
+ location /refresh {
40
+ proxy_pass http://refresh;
41
+ proxy_set_header Host $host;
42
+ proxy_read_timeout 120s;
43
+ }
44
+
45
+ location /config {
46
+ proxy_pass http://refresh;
47
+ proxy_set_header Host $host;
48
+ }
49
+
50
+ location /health {
51
+ proxy_pass http://refresh;
52
+ proxy_set_header Host $host;
53
+ }
54
+
55
+ location / {
56
+ proxy_pass http://airflow;
57
+ proxy_set_header Host $host;
58
+ proxy_set_header X-Real-IP $remote_addr;
59
+ proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
60
+ proxy_set_header X-Forwarded-Proto $scheme;
61
+ proxy_read_timeout 300s;
62
+ proxy_connect_timeout 75s;
63
+ }
64
+ }
65
+ }
refresh_service.py ADDED
@@ -0,0 +1,76 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from flask import Flask, jsonify
3
+ import subprocess
4
+
5
+ app = Flask(__name__)
6
+
7
+ DAGS_DIR = os.environ.get('AIRFLOW_HOME', '/opt/airflow') + '/dags'
8
+ DAG_REPO_URL = os.environ.get('DAG_REPO_URL', 'https://github.com/subhamgiri460/myworkflows.git')
9
+ DAG_REPO_BRANCH = os.environ.get('DAG_REPO_BRANCH', 'main')
10
+
11
+
12
+ @app.route('/refresh', methods=['GET', 'POST'])
13
+ def refresh_dags():
14
+ try:
15
+ if os.path.exists(os.path.join(DAGS_DIR, '.git')):
16
+ fetch_result = subprocess.run(
17
+ ['git', 'fetch', 'origin', DAG_REPO_BRANCH],
18
+ cwd=DAGS_DIR, capture_output=True, text=True, timeout=60
19
+ )
20
+ if fetch_result.returncode != 0:
21
+ return jsonify({
22
+ 'status': 'error',
23
+ 'message': f'Git fetch failed: {fetch_result.stderr}'
24
+ }), 500
25
+
26
+ reset_result = subprocess.run(
27
+ ['git', 'reset', '--hard', f'origin/{DAG_REPO_BRANCH}'],
28
+ cwd=DAGS_DIR, capture_output=True, text=True, timeout=60
29
+ )
30
+ result = reset_result
31
+ action = 'updated'
32
+ else:
33
+ result = subprocess.run(
34
+ ['git', 'clone', '--depth', '1', '--branch', DAG_REPO_BRANCH, DAG_REPO_URL, DAGS_DIR],
35
+ capture_output=True, text=True, timeout=120
36
+ )
37
+ action = 'cloned'
38
+
39
+ if result.returncode == 0:
40
+ return jsonify({
41
+ 'status': 'success',
42
+ 'message': f'DAGs {action} successfully',
43
+ 'repo': DAG_REPO_URL,
44
+ 'branch': DAG_REPO_BRANCH
45
+ }), 200
46
+ else:
47
+ return jsonify({
48
+ 'status': 'error',
49
+ 'message': result.stderr or 'Unknown error'
50
+ }), 500
51
+
52
+ except subprocess.TimeoutExpired:
53
+ return jsonify({'status': 'error', 'message': 'Operation timed out'}), 500
54
+ except Exception as e:
55
+ return jsonify({'status': 'error', 'message': str(e)}), 500
56
+
57
+
58
+ @app.route('/health')
59
+ def health():
60
+ return jsonify({'status': 'healthy'}), 200
61
+
62
+
63
+ @app.route('/config')
64
+ def show_config():
65
+ return jsonify({
66
+ 'dags_dir': DAGS_DIR,
67
+ 'repo_url': DAG_REPO_URL,
68
+ 'branch': DAG_REPO_BRANCH,
69
+ 'airflow_web_port': os.environ.get('AIRFLOW_WEB_PORT', '8080'),
70
+ 'refresh_service_port': os.environ.get('REFRESH_SERVICE_PORT', '5000')
71
+ }), 200
72
+
73
+
74
+ if __name__ == '__main__':
75
+ port = int(os.environ.get('REFRESH_SERVICE_PORT', 5000))
76
+ app.run(host='0.0.0.0', port=port)
requirements.txt CHANGED
@@ -1,2 +1,7 @@
1
- apache-airflow-providers-http
2
- apache-airflow-providers-common-sql
 
 
 
 
 
 
1
+ apache-airflow[postgres]==2.10.3
2
+ apache-airflow-providers-postgres
3
+ apache-airflow-providers-ssh
4
+ flask
5
+ gunicorn
6
+ gevent
7
+ requests
supervisord.conf ADDED
@@ -0,0 +1,38 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [supervisord]
2
+ nodaemon=true
3
+ user=airflow
4
+ logfile=/var/log/supervisor/supervisord.log
5
+ pidfile=/run/nginx/supervisord.pid
6
+ loglevel=info
7
+
8
+ [program:nginx]
9
+ command=/usr/sbin/nginx -g "daemon off;"
10
+ autostart=true
11
+ autorestart=true
12
+ stderr_logfile=/var/log/supervisor/nginx.err.log
13
+ stdout_logfile=/var/log/supervisor/nginx.out.log
14
+ priority=5
15
+
16
+ [program:airflow-webserver]
17
+ command=airflow webserver
18
+ autostart=true
19
+ autorestart=true
20
+ stderr_logfile=/var/log/supervisor/webserver.err.log
21
+ stdout_logfile=/var/log/supervisor/webserver.out.log
22
+ priority=20
23
+
24
+ [program:airflow-scheduler]
25
+ command=airflow scheduler
26
+ autostart=true
27
+ autorestart=true
28
+ stderr_logfile=/var/log/supervisor/scheduler.err.log
29
+ stdout_logfile=/var/log/supervisor/scheduler.out.log
30
+ priority=30
31
+
32
+ [program:refresh-service]
33
+ command=gunicorn --bind 127.0.0.1:5000 --workers 1 --worker-class gevent --chdir / refresh_service:app
34
+ autostart=true
35
+ autorestart=true
36
+ stderr_logfile=/var/log/supervisor/refresh.err.log
37
+ stdout_logfile=/var/log/supervisor/refresh.out.log
38
+ priority=10