In this article we will show you how to set up the deployment of an example application (a cool voting app in our case) using werf. It is better to start with a short introduction first if you haven’t read it yet.

Prepare your host

  1. Install dependencies (Docker and Git).
  2. Install multiwerf and werf.

Make sure you have werf command available in your shell before proceeding to the next step:

werf version

Prepare your Kubernetes and container registry

You should have access to the Kubernetes cluster and be able to push images to your container registry. The container registry should also be accessible from the Kubernetes cluster to pull images.

If your Kubernetes and container registry are running already:

  1. Perform the standard docker login procedure into your container registry from your host.
  2. Make sure your Kubernetes cluster is accessible from your host (if the kubectl tool is already set up and running, then werf will also work just fine).


Or use one of the following instructions to set up the local Kubernetes cluster and container registry in your OS:

Windows — minikube
  1. Install minikube.
  2. Start minikube:

    minikube start --driver=hyperv --insecure-registry registry.example.com:80
    

    IMPORTANT Param --insecure-registry allows usage of Container Registry without TLS. TLS in our case dropped for simplicity.

  3. Install NGINX Ingress Controller:

    minikube addons enable ingress
    
  4. Install Container Registry to store images:

    minikube addons enable registry
    

    Create Ingress to access Container Registry:

    kubectl apply -f - << EOF
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: registry
      namespace: kube-system
      annotations:
        nginx.ingress.kubernetes.io/proxy-body-size: "0"
    spec:
      rules:
      - host: registry.example.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: registry
                port:
                  number: 80
    EOF
    
  5. Allow usage of Container Registry without TLS for docker:

    Using menu Docker Desktop -> Settings -> Docker Engine add following configuration key:

    {
       "insecure-registries": ["registry.example.com:80"]
    }
    

    Restart Docker Desktop using right button menu of the tray Docker Desktop icon.

  6. Allow usage of Container Registry without TLS for werf:

    Set WERF_INSECURE_REGISTRY=1 environment variable in the terminal where werf would run.

    For cmd.exe:

    set WERF_INSECURE_REGISTRY=1
    

    For bash:

    export WERF_INSECURE_REGISTRY=1
    

    For PowerShell:

    $Env:WERF_INSECURE_REGISTRY = "1"
    
  7. We are going to use vote.quickstart-application.example.com and result.quickstart-application.example.com domains to access application and registry.example.com domain to access Container Registry.

    Let’s update hosts file. Get minikube IP-address:

    minikube ip
    

    Using IP-address above append line to the end of the file C:\Windows\System32\drivers\etc\hosts:

    <IP-address minikube>    vote.quickstart-application.example.com result.quickstart-application.example.com registry.example.com
    

    Should look like:

    192.168.99.99          vote.quickstart-application.example.com result.quickstart-application.example.com registry.example.com
    
  8. Let’s also add registry.example.com domain to the minikube node:

    minikube ssh -- "echo $(minikube ip) registry.example.com | sudo tee -a /etc/hosts"
    
MacOS — minikube
  1. Install minikube.
  2. Start minikube:

    minikube start --vm=true --insecure-registry registry.example.com:80
    

    IMPORTANT Param --insecure-registry allows usage of Container Registry without TLS. TLS in our case dropped for simplicity.

  3. Install NGINX Ingress Controller:

    minikube addons enable ingress
    
  4. Install Container Registry to store images:

    minikube addons enable registry
    

    Create Ingress to access Container Registry:

    kubectl apply -f - << EOF
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: registry
      namespace: kube-system
      annotations:
        nginx.ingress.kubernetes.io/proxy-body-size: "0"
    spec:
      rules:
      - host: registry.example.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: registry
                port:
                  number: 80
    EOF
    
  5. Allow usage of Container Registry without TLS for docker:

    Using menu Docker Desktop -> Settings -> Docker Engine add following configuration key:

    {
       "insecure-registries": ["registry.example.com:80"]
    }
    

    Restart Docker Desktop using right button menu of the tray Docker Desktop icon.

  6. Allow usage of Container Registry without TLS for werf:

    Set WERF_INSECURE_REGISTRY=1 environment variable in the terminal where werf would run. For bash:

    export WERF_INSECURE_REGISTRY=1
    

    To set this option automatically in new bash-sessions, add it to the .bashrc:

    echo export WERF_INSECURE_REGISTRY=1 | tee -a ~/.bashrc
    
  7. We are going to use vote.quickstart-application.example.com and result.quickstart-application.example.com domains to access application and registry.example.com domain to access Container Registry.

    Let’s update hosts file. Run the following command in the terminal:

    echo "$(minikube ip) vote.quickstart-application.example.com result.quickstart-application.example.com registry.example.com" | sudo tee -a /etc/hosts
    
  8. Let’s also add registry.example.com domain to the minikube node:

    minikube ssh -- "echo $(minikube ip) registry.example.com | sudo tee -a /etc/hosts"
    
Linux — minikube
  1. Install minikube.
  2. Start minikube:

    minikube start --driver=docker --insecure-registry registry.example.com:80
    

    IMPORTANT Param --insecure-registry allows usage of Container Registry without TLS. TLS in our case dropped for simplicity.

  3. Install NGINX Ingress Controller:

    minikube addons enable ingress
    
  4. Install Container Registry to store images:

    minikube addons enable registry
    

    Create Ingress to access Container Registry:

    kubectl apply -f - << EOF
    ---
    apiVersion: networking.k8s.io/v1
    kind: Ingress
    metadata:
      name: registry
      namespace: kube-system
      annotations:
        nginx.ingress.kubernetes.io/proxy-body-size: "0"
    spec:
      rules:
      - host: registry.example.com
        http:
          paths:
          - path: /
            pathType: Prefix
            backend:
              service:
                name: registry
                port:
                  number: 80
    EOF
    
  5. Allow usage of Container Registry without TLS for docker:

    Add new key to the file /etc/docker/daemon.json (default location):

    {
       "insecure-registries": ["registry.example.com:80"]
    }
    

    Restart Docker:

    sudo systemctl restart docker
    
  6. Allow usage of Container Registry without TLS for werf:

    Set WERF_INSECURE_REGISTRY=1 environment variable in the terminal where werf would run. For bash:

    export WERF_INSECURE_REGISTRY=1
    

    To set this option automatically in new bash-sessions, add it to the .bashrc:

    echo export WERF_INSECURE_REGISTRY=1 | tee -a ~/.bashrc
    
  7. We are going to use vote.quickstart-application.example.com and result.quickstart-application.example.com domains to access application and registry.example.com domain to access Container Registry.

    Let’s update hosts file. Run the following command in the terminal:

    echo "$(minikube ip) vote.quickstart-application.example.com result.quickstart-application.example.com registry.example.com" | sudo tee -a /etc/hosts
    
  8. Let’s also add registry.example.com domain to the minikube node:

    minikube ssh -- "echo $(minikube ip) registry.example.com | sudo tee -a /etc/hosts"
    

Deploy an example application

  1. Clone the example application’s repository:

    git clone https://github.com/werf/quickstart-application
    cd quickstart-application
    
  2. Run the converge command using your container registry for storing images (localhost:5000/quickstart-application repository in the case of a local container registry).

    werf converge --repo registry.example.com:80/quickstart-application
    

NOTE: werf uses the same settings to connect to the Kubernetes cluster as the kubectl tool does: the ~/.kube/config file and the KUBECONFIG environment variable. werf also supports --kube-config and --kube-config-base64 parameters for specifying custom kubeconfig files.

Check the result

When the converge command is successfully completed, it is safe to assume that our application is up and running.

Our application is a basic voting system. Let’s check it!

  1. Go to the following URL to vote: vote.quickstart-application.example.com

  2. Go to the following URL to check the result of voting: result.quickstart-application.example.com

How it works

To deploy an application using werf, we should define the desired state in the Git (as set out in the introduction).

  1. We have the following Dockerfiles in our repository:

    vote/Dockerfile
    result/Dockerfile
    worker/Dockerfile
    
  2. The werf.yaml file references those Dockerfiles:

    configVersion: 1
    project: quickstart-application
    ---
    image: vote
    dockerfile: vote/Dockerfile
    context: vote
    ---
    image: result
    dockerfile: result/Dockerfile
    context: result
    ---
    image: worker
    dockerfile: worker/Dockerfile
    context: worker
    
  3. Kubernetes templates for vote, db, redis, result and worker components of the application are described in the files of a .helm/templates/ directory. Components interact with each other as shown in the diagram:

Component interaction diagram

  • A front-end web app in Python or ASP.NET Core lets you vote for one of the two options;
  • A Redis or NATS queue collects new votes;
  • A .NET Core, Java or .NET Core 2.1 worker consumes votes and stores them in…
  • A Postgres or TiDB database backed by a Docker volume;
  • A Node.js or ASP.NET Core SignalR web-app shows the results of the voting in real-time.

What’s next?

Check the “Using werf with CI/CD systems” article or refer to the guides.