From c985eb6f8da4dda3ffa6285a6219d3d73b8e21da Mon Sep 17 00:00:00 2001 From: Haziq Abiyyu Mahdy <haziq.a.mahdy@gmail.com> Date: Fri, 10 Jan 2025 11:37:47 +0700 Subject: [PATCH] feat: integrate train task to airflow --- Dockerfile.temp => Dockerfile.airflow | 15 ++++++++ Dockerfile.mlflow | 21 +++++++++++ airflow/airflow-webserver.pid | 2 +- airflow/airflow.db | Bin 15167488 -> 18427904 bytes airflow/dags/functions/train_model.py | 2 +- docker-compose.yml | 51 +++++++++++++++++++++++++- requirements/mlflow.txt | 3 ++ 7 files changed, 91 insertions(+), 3 deletions(-) rename Dockerfile.temp => Dockerfile.airflow (67%) create mode 100644 Dockerfile.mlflow create mode 100644 requirements/mlflow.txt diff --git a/Dockerfile.temp b/Dockerfile.airflow similarity index 67% rename from Dockerfile.temp rename to Dockerfile.airflow index 6c1cda8..8f76273 100644 --- a/Dockerfile.temp +++ b/Dockerfile.airflow @@ -1,4 +1,5 @@ FROM apache/airflow:latest + USER root RUN apt-get update && \ @@ -7,8 +8,22 @@ RUN apt-get update && \ apt-get clean ENV JAVA_HOME /usr/lib/jvm/java-17-openjdk-amd64/ + RUN export JAVA_HOME USER airflow +RUN pip install apache-airflow + +RUN pip install pyspark + RUN pip install apache-airflow-providers-apache-spark + +RUN pip install boto3 + +RUN pip install scikit-learn + +RUN pip install mlflow + + + diff --git a/Dockerfile.mlflow b/Dockerfile.mlflow new file mode 100644 index 0000000..471ecfa --- /dev/null +++ b/Dockerfile.mlflow @@ -0,0 +1,21 @@ +FROM python:3.9-slim + +ENV MLFLOW_HOME=/mlflow +ENV PATH=$MLFLOW_HOME/bin:$PATH + +RUN apt-get update && apt-get install -y \ + curl \ + libpq-dev \ + gcc \ + && apt-get clean + +WORKDIR $MLFLOW_HOME + +COPY ./requirements/mlflow.txt /tmp/requirements.txt + +EXPOSE 5000 + +CMD ["mlflow", "server", \ + "--backend-store-uri", "postgresql://mlflow:mlflow@mlflow-db:5432/mlflow", \ + "--default-artifact-root", "/mlflow/artifacts", \ + "--host", "0.0.0.0"] diff --git a/airflow/airflow-webserver.pid b/airflow/airflow-webserver.pid index 4099407..2bd5a0a 100644 --- a/airflow/airflow-webserver.pid +++ b/airflow/airflow-webserver.pid @@ -1 +1 @@ -23 +22 diff --git a/airflow/airflow.db b/airflow/airflow.db index 907a8e95c536a310efee44d72a78275f219ca44d..e2c8f2dfbdc40e38f71a8e1d116ab2643da855c3 100644 GIT binary patch delta 49759 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 B&8PqX delta 9231 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 diff --git a/airflow/dags/functions/train_model.py b/airflow/dags/functions/train_model.py index 6d814be..ef79478 100644 --- a/airflow/dags/functions/train_model.py +++ b/airflow/dags/functions/train_model.py @@ -34,7 +34,7 @@ def train_model(df_dict_str): model = RandomForestClassifier(n_estimators=100, random_state=42) - mlflow.set_tracking_uri("http://127.0.0.1:5000") + mlflow.set_tracking_uri("http://mlflow:5000") model_name = "customer_churn_model" # Start MLflow run with mlflow.start_run(run_name="model_training"): diff --git a/docker-compose.yml b/docker-compose.yml index 679b080..fe2e645 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,10 @@ version: "3" + services: sleek-airflow: build: context: . - dockerfile: Dockerfile.temp + dockerfile: Dockerfile.airflow volumes: - ./airflow:/opt/airflow - ./workspace:/opt/workspace @@ -71,9 +72,57 @@ services: volumes: - minio-data:/data + mlflow: + image: mlflow/mlflow:latest + container_name: mlflow-server + ports: + - "5000:5000" + environment: + MLFLOW_TRACKING_URI: "http://0.0.0.0:5000" + BACKEND_STORE_URI: "postgresql://mlflow:mlflow@mlflow-db:5432/mlflow" + ARTIFACT_STORE_URI: "s3://mlflow-artifacts" + volumes: + - ./artifacts:/mlflow/artifacts + build: + context: . + dockerfile: Dockerfile.mlflow + depends_on: + - mlflow-db + - minio + networks: + - spark-cluster + + mlflow-db: + image: postgres:13 + container_name: mlflow-db + environment: + POSTGRES_USER: mlflow + POSTGRES_PASSWORD: mlflow + POSTGRES_DB: mlflow + ports: + - "5432:5432" + volumes: + - ./postgres_data:/var/lib/postgresql/data + networks: + - spark-cluster + + minio-client: + image: minio/mc + depends_on: + - minio + entrypoint: > + /bin/sh -c " + until (/usr/bin/mc alias set mlflow http://minio:9000 minioadmin minioadmin) do echo 'waiting for minio'; sleep 5; done; + /usr/bin/mc mb -p mlflow/mlflow-artifacts; + /usr/bin/mc policy set public mlflow/mlflow-artifacts; + " + networks: + - spark-cluster + volumes: shared-workspace: minio-data: + postgres_data: networks: spark-cluster: diff --git a/requirements/mlflow.txt b/requirements/mlflow.txt new file mode 100644 index 0000000..a3740c5 --- /dev/null +++ b/requirements/mlflow.txt @@ -0,0 +1,3 @@ +mlflow +boto3 +psycopg2-binary -- GitLab