Stackvora.tech

OpenShift: deploy an app from a Git repo

Deploying applications directly from Git repositories is a fundamental and powerful workflow in OpenShift, enabling developers to maintain source code in…

Deploying applications directly from Git repositories is a fundamental and powerful workflow in OpenShift, enabling developers to maintain source code in version control and leverage OpenShift's built-in Source-to-Image (S2I) capabilities or Dockerfile builds. This approach streamlines the CI/CD process by automating the build and deployment phases, transforming source code into ready-to-run container images.

This article details the process of deploying an application from a Git repository to OpenShift, covering S2I builds, Dockerfile builds, and advanced configuration options. We will use the oc command-line tool, compatible with OpenShift 3.x and 4.x.

Understanding OpenShift Application Deployment from Git

When you point OpenShift to a Git repository, it initiates a build process. This process converts your source code into a container image, which is then deployed as a Pod. OpenShift supports several build strategies for this:

  • Source-to-Image (S2I): The default and often preferred strategy. OpenShift uses a builder image (e.g., Node.js, Python, Java) to inject your application source code, compile it if necessary, and create a deployable image. This abstracts away Dockerfile complexities for many common language runtimes.
  • Dockerfile: If your repository contains a Dockerfile, OpenShift can use it directly to build the image. This offers maximum control over the build process and environment.
  • Custom Build: For highly specialized scenarios, a custom builder image can be used. This is less common for typical Git deployments.

The core concept is the BuildConfig object, which defines how the application source code is built into an image. This image is then referenced by a DeploymentConfig (OpenShift 3.x) or Deployment (OpenShift 4.x, Kubernetes native) to create and manage application Pods.

Deploying with Source-to-Image (S2I)

S2I is ideal for many common language applications because it simplifies image creation. OpenShift intelligently detects the language based on repository contents or explicit builder image specification.

Basic S2I Deployment

Let's use the provided Node.js example. This command will trigger an S2I build using a pre-installed Node.js builder image in your OpenShift cluster.

oc new-project demo
oc new-app https://github.com/sclorg/nodejs-ex --name=nodejs-app
oc expose svc/nodejs-app

Let's break down these commands:

  • oc new-project demo: Creates a new project (namespace) named "demo". Projects provide isolation and resource management.
  • oc new-app https://github.com/sclorg/nodejs-ex --name=nodejs-app: This is the core deployment command.
    • https://github.com/sclorg/nodejs-ex: Points to the Git repository containing the Node.js application source.
    • --name=nodejs-app: Assigns a base name to the OpenShift objects created (DeploymentConfig, BuildConfig, Service, ImageStream). Without this, it defaults to the last part of the Git URL or a derived name.

    OpenShift will:

    1. Inspect the Git repository to detect the language (Node.js in this case).
    2. Find a suitable Node.js builder image in the cluster's ImageStream (e.g., openshift/nodejs:16).
    3. Create a BuildConfig to define the S2I process.
    4. Trigger a new build, pulling the source, injecting it into the builder image, and pushing the resulting application image to an internal ImageStream.
    5. Create a DeploymentConfig to deploy the application image.
    6. Create a Service to provide internal network access to the application Pods.
  • oc expose svc/nodejs-app: Creates a Route, which exposes the Service externally, typically via an HTTP/S hostname. You can find the URL with oc get route nodejs-app.

Monitoring the Build Process

After running oc new-app, you can monitor the build:

oc get builds
oc logs -f bc/nodejs-app

oc get builds shows the status of ongoing and completed builds. oc logs -f bc/nodejs-app streams the logs from the active build, allowing you to see the S2I process in action.

Specifying a Builder Image Version or Tag

Sometimes you need a specific version of the builder image. For example, to use Node.js 16 instead of the default:

oc new-app nodejs:16~https://github.com/sclorg/nodejs-ex --name=nodejs-app-v16

The builder:tag~repo_url syntax explicitly tells OpenShift which builder image to use.

Using a Subdirectory

If your application code isn't at the root of the Git repository, you can specify a context directory:

oc new-app nodejs:latest~https://github.com/example/my-mono-repo --context-dir=./apps/frontend --name=frontend-app

This tells the S2I build to only consider the apps/frontend directory within the repository.

Deploying with a Dockerfile

If your repository contains a Dockerfile, OpenShift will automatically detect and use it. This gives you granular control over the base image, dependencies, and build steps.

Consider a repository structure like this:

my-docker-app/
├── Dockerfile
└── app.py

To deploy this:

oc new-app https://github.com/yourorg/my-docker-app --name=docker-based-app
oc expose svc/docker-based-app

OpenShift will detect the Dockerfile at the root and create a BuildConfig with a docker strategy. The build process will then execute the instructions in your Dockerfile.

Dockerfile Build with a Subdirectory

Similar to S2I, if your Dockerfile is in a subdirectory:

oc new-app https://github.com/yourorg/my-mono-repo --context-dir=./services/backend --name=backend-service

OpenShift will look for a Dockerfile inside services/backend.

Advanced Git Deployment Configurations

Beyond basic deployments, you often need more control over the build and deployment process.

Environment Variables for Builds

You can pass environment variables to the build process, which is useful for configuring build-time dependencies or secrets (though secrets should be handled carefully).

oc new-app nodejs:latest~https://github.com/sclorg/nodejs-ex --name=nodejs-app \
    --env=NPM_CONFIG_UNSAFE_PERM=true \
    --build-env=BUILD_DEBUG=true

--env sets variables for both the build and the resulting application Pods. --build-env sets variables only for the build process.

Webhooks for Automated Builds

To trigger new builds automatically when changes are pushed to Git, configure webhooks. OpenShift can generate Git, GitHub, or GitLab webhooks. After creating your application, get the webhook URL:

oc get bc/nodejs-app -o jsonpath='{.spec.triggers[?(@.type=="GitHub")].github.secret}{"\n"}'
oc get bc/nodejs-app -o jsonpath='{.status.webhooks[?(@.type=="GitHub")].url}{"\n"}'

Take the secret and URL, then configure it in your GitHub/GitLab repository settings under "Webhooks". Every push to the configured branch will then automatically trigger a new build and deployment.

Git Reference (Branch, Tag, Commit)

By default, OpenShift builds from the master or main branch. You can specify a different branch, tag, or even a specific commit SHA:

# Deploy from 'dev' branch
oc new-app https://github.com/sclorg/nodejs-ex#dev --name=nodejs-dev

# Deploy from a specific tag
oc new-app https://github.com/sclorg/nodejs-ex#v1.2.0 --name=nodejs-v120

# Deploy from a specific commit SHA (less common for ongoing deployments)
oc new-app https://github.com/sclorg/nodejs-ex#a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0 --name=nodejs-specific-commit

The # syntax specifies the Git reference.

Private Repositories

Deploying from private Git repositories requires providing credentials. This is typically done using an SSH key or a username/password pair stored as an OpenShift Secret.

1. Create a Secret for SSH Private Key:

oc create secret generic git-ssh-key --from-file=ssh-privatekey=~/.ssh/id_rsa --type=kubernetes.io/ssh-auth
# Ensure ~/.ssh/id_rsa contains your private key for the Git repo

2. Create a Secret for Username/Password (less secure for automated builds):

oc create secret generic git-user-pass --from-literal=username=gituser --from-literal=password=gitpass --type=kubernetes.io/basic-auth

3. Link the Secret to your BuildConfig:

This cannot be done directly with oc new-app, you need to either edit the BuildConfig or create it manually. First, create the app without the secret:

oc new-app https://github.com/yourorg/private-repo.git --name=private-app

Then, patch the BuildConfig to use the secret:

oc set build-secret bc/private-app --source=git-ssh-key

For HTTPS basic authentication, the command is:

oc set build-secret bc/private-app --source=git-user-pass

Alternatively, you can edit the BuildConfig directly using oc edit bc/private-app and add the following under spec.source.sourceSecret:

apiVersion: build.openshift.io/v1
kind: BuildConfig
metadata:
  name: private-app
spec:
  source:
    git:
      ref: master
      uri: https://github.com/yourorg/private-repo.git
    sourceSecret:
      name: git-ssh-key # Or git-user-pass
    type: Git
  # ... rest of the BuildConfig

Common Pitfalls and Troubleshooting

  • Builder Image Not Found: If oc new-app fails with "no such image stream tag found", it means your OpenShift cluster doesn't have the requested builder image (e.g., nodejs:16) imported or available. Check oc get is -n openshift for available images or contact your cluster administrator.
  • Build Failures: The most common issue. Always check build logs using oc logs -f bc/<app-name>. S2I builds often fail if dependencies aren't met (e.g., missing package.json for Node.js, incorrect requirements.txt for Python) or if the application code has compilation errors.
  • Application Not Starting: If a build succeeds but Pods crash, check the Pod logs: oc get pods (find the Pod name), then oc logs <pod-name>. This usually indicates application-level issues (e.g., incorrect environment variables, port conflicts, misconfigured database connections).
  • Port Mismatch: Ensure your application listens on the port defined in its Dockerfile or S2I script (often 8080 or 8443 by default in OpenShift builder images) and that your Service and Route are configured to expose that port. OpenShift builder images usually expose 8080 by default.
  • Route Not Accessible: If you get 503 errors or timeout, verify the Route target points to the correct Service, and that the Service selects healthy Pods. Check oc get route <app-name> -o yaml and oc get svc <app-name> -o yaml.
  • Private Repo Access Denied: Double-check your Git secret. For SSH, ensure the private key is correct and that the public key is added to the Git provider. For HTTPS, verify username and password. Also confirm the sourceSecret is correctly applied to the BuildConfig.

Back to the knowledge base · Ask the AI assistant