aleeusgr / hs-clojure

Other
0 stars 0 forks source link

Prepare for deployment to K8s #1

Open aleeusgr opened 6 months ago

aleeusgr commented 6 months ago

Create container: nix | docker Create a cluster: https://nixos.wiki/wiki/K3s

https://circleci.com/blog/package-a-clojure-web-application-using-docker/

aleeusgr commented 6 months ago

Deploying a Leiningen project to Kubernetes involves several steps. Here's a step-by-step guide to help you achieve this:

Prerequisites:

  1. You have a Leiningen project with a project.clj file.
  2. You have a Kubernetes cluster set up (e.g., Minikube, GKE, AKS, or EKS).
  3. You have Docker installed on your system.

Step 1: Create a Docker image

Create a Dockerfile in the root of your Leiningen project with the following content:

FROM clojure:openjdk-11

# Set the working directory to /app
WORKDIR /app

# Copy the project files
COPY . /app

# Install dependencies
RUN lein deps

# Expose the port
EXPOSE 3000

# Run the application
CMD ["lein", "run"]

This Dockerfile assumes your Leiningen project is in the same directory. It uses the official Clojure image, sets up the working directory, copies the project files, installs dependencies, exposes port 3000, and sets the default command to run the application with lein run.

Step 2: Build the Docker image

Run the following command in your terminal, in the root of your Leiningen project:

docker build -t my-lein-app .

This command builds a Docker image with the name my-lein-app using the Dockerfile.

Step 3: Push the image to a container registry

You need to push the Docker image to a container registry like Docker Hub, Google Container Registry, or Amazon Elastic Container Registry. For this example, we'll use Docker Hub.

Create a Docker Hub account and login to your account using the command:

docker login

Tag your image with your Docker Hub username and push it to the registry:

docker tag my-lein-app <your-docker-hub-username>/my-lein-app
docker push <your-docker-hub-username>/my-lein-app

Step 4: Create a Kubernetes deployment YAML file

Create a file named deployment.yaml with the following content:

apiVersion: apps/v1
kind: Deployment
metadata:
  name: my-lein-app
spec:
  replicas: 1
  selector:
    matchLabels:
      app: my-lein-app
  template:
    metadata:
      labels:
        app: my-lein-app
    spec:
      containers:
      - name: my-lein-app
        image: <your-docker-hub-username>/my-lein-app
        ports:
        - containerPort: 3000

Replace <your-docker-hub-username> with your actual Docker Hub username.

Step 5: Apply the deployment YAML file

Apply the deployment.yaml file to your Kubernetes cluster using the following command:

kubectl apply -f deployment.yaml

This command creates a deployment named my-lein-app with one replica, using the Docker image from your container registry.

Step 6: Expose the service

Create a service.yaml file with the following content:

apiVersion: v1
kind: Service
metadata:
  name: my-lein-app
spec:
  selector:
    app: my-lein-app
  ports:
  - name: http
    port: 80
    targetPort: 3000
  type: LoadBalancer

Apply the service.yaml file to your Kubernetes cluster:

kubectl apply -f service.yaml

This command creates a service named my-lein-app that exposes port 80 and routes traffic to port 3000 on the deployment.

Step 7: Verify the deployment

Verify that the deployment is successful by running:

kubectl get deployments
kubectl get pods
kubectl get svc

You should see the deployment, pod, and service created successfully.

Access your application

Get the external IP address of the service using:

kubectl get svc my-lein-app -o jsonpath='{.status.loadBalancer.ingress[0].hostname}'

Access your Leiningen application by visiting http://<external-ip>:80 in your web browser.

That's it! You have successfully deployed your Leiningen project to a Kubernetes cluster.

aleeusgr commented 6 months ago

The error message exit code: 127 usually indicates that the command lein deps failed to execute successfully.

Here are a few things you can try to troubleshoot the issue:

  1. Check if Leiningen is installed: Make sure that Leiningen is installed in the Docker image. You can add a RUN command to install Leiningen before running lein deps. For example:
    RUN wget https://raw.githubusercontent.com/technomancy/leiningen/2.9.1/bin/lein && \
    chmod +x lein && \
    ./lein self-install
  2. Verify the project.clj file: Ensure that the project.clj file is in the correct location and has the correct syntax. You can try running lein deps manually in your project directory to see if it works outside of Docker.
  3. Check the lein version: Make sure that the version of Leiningen installed in the Docker image is compatible with your project.clj file. You can specify a specific version of Leiningen in your Dockerfile using RUN lein --version 2.9.1.
  4. Increase the verbosity of the build process: You can add the --no-cache flag to the docker build command to increase the verbosity of the build process. This might give you more information about what's going wrong:
    docker build --no-cache -t my-clojure-app .
  5. Check the Dockerfile: Review your Dockerfile for any syntax errors or incorrect commands. You can try breaking down the build process into smaller steps to identify where the issue is occurring.

If none of these suggestions help, please provide more details about your project, and I'll do my best to assist you further.

aleeusgr commented 6 months ago

Clojure flake:

{
  description = "An automatic dimmer for Ikea Trådfri lights that applies a scene and restores lighting based on Kodis playback status";

  inputs = {
    nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
    flake-utils.url = "github:numtide/flake-utils";
    clj-nix.url = "github:jlesquembre/clj-nix";
  };

  outputs = { self, nixpkgs, flake-utils, clj-nix }:

    flake-utils.lib.eachDefaultSystem (system: {

      packages = {

        default = clj-nix.lib.mkCljApp {
          pkgs = nixpkgs.legacyPackages.${system};
          modules = [
            {
              projectSrc = ./.;
              name = "de.thenybble/kodi-autodim";
              main-ns = "autodim.core";

              nativeImage = {
                enable = true;
                extraNativeImageBuildArgs = [
                  "--initialize-at-build-time=org.slf4j.LoggerFactory"
                  "--initialize-at-build-time=org.slf4j.simple.SimpleLogger"
                  "--initialize-at-build-time=org.slf4j.impl.SimpleLogger"
                  "--initialize-at-build-time=org.slf4j.impl.StaticLoggerBinder"
                ];
              };

              # customJdk.enable = true;
            }
          ];
        };

      };
    });
}

https://git.sr.ht/~jeeger/kodi-autodim/tree/main/item/flake.nix

aleeusgr commented 6 months ago

Simple nix container:

https://git.sr.ht/~jeeger/kodi-autodim/tree/main/item/flake.nix

aleeusgr commented 5 months ago

https://github.com/aleeusgr/hs-clojure/issues/19

Work around? https://github.com/jlesquembre/clj-nix?tab=readme-ov-file