---
title: "Web Relay Ingress with Docker for Mac | WebhookRelay"
meta:
  "og:description": "Web Relay ingress for Mac lets users expose their local services to the internet for testing and demoing"
  "og:title": "Web Relay Ingress with Docker for Mac"
  description: "Web Relay ingress for Mac lets users expose their local services to the internet for testing and demoing"
---

![Stripes](https://webhookrelay.com/blog/ingress-with-docker-for-mac/images/stripes.svg)

# **Web Relay Ingress with Docker for Mac**

Web Relay ingress for Mac lets users expose their local services to the internet for testing and demoing

![Docker for Mac now supports Kubernetes](https://webhookrelay.com/blog/ingress-with-docker-for-mac/images/blog/ingress-with-docker-for-mac/docker-for-mac-mashup.png)

Kubernetes became available in **Docker for Mac 17.12 CE Edge**. [Kubernetes](https://kubernetes.io/) in the last year showed that it's the most flexible and **reliable** option to run container workloads, all the major cloud providers now offer or are planning to offer a managed Kubernetes service to their customers:

- [https://cloud.google.com/kubernetes-engine](https://cloud.google.com/kubernetes-engine)
- [https://azure.microsoft.com/en-us/services/container-service](https://azure.microsoft.com/en-us/services/container-service)
- [https://aws.amazon.com/eks](https://aws.amazon.com/eks)
- [https://www.ibm.com/cloud/container-service](https://www.ibm.com/cloud/container-service)

And some great companies that help you deploy and run your own cluster:

- [https://www.ankyra.io/](https://www.ankyra.io/)
- [https://stackpoint.io/](https://stackpoint.io/)
- [https://heptio.com/](https://heptio.com/)
- [https://appscode.com/](https://appscode.com/)

After visiting last KubeCon in Austin I have seen a huge increase in the number of companies that specialize in Kubernetes consulting. This list could go on and on :)

**In this article we will:**

- Enable Kubernetes support in your **Docker for Mac**.
- Create and deploy an example Node.js application.
- Use Web Relay ingress controller to share that app running inside our Mac to the world :)

![Ingress with Docker for Mac](https://webhookrelay.com/blog/ingress-with-docker-for-mac/images/blog/ingress-with-docker-for-mac/docker-for-mac.gif)

**Prerequisites:**

- Docker for Mac **17.12 CE Edge**.
- Webhook Relay [account](https://my.webhookrelay.com/register) and [relay](https://webhookrelay.com/blog/ingress-with-docker-for-mac/v1/installation/) client command.
- `kubectl`, the Kubernetes client command. It should be included and configured by the Docker for Mac.

> If you are not using Mac or **Docker for Mac** you can still follow this tutorial step-by-step, just skip the "Enable Kubernetes in your Docker for Mac" section. This tutorial will work for ANY Kubernetes cluster as long as it has an Internet connectivity.

## [Getting started](#getting-started)

Time to get our hands dirty! Feel free to skip a few things like enabling Kubernetes if you have already done it.

### [Enable Kubernetes in your Docker for Mac](#enable-kubernetes-in-your-docker-for-mac)

To enable Kubernetes support inside your Docker for Mac, select **Enable Kubernetes** and click the **Apply and restart** button:

![Kubernetes in Docker for Mac](https://webhookrelay.com/blog/ingress-with-docker-for-mac/images/blog/ingress-with-docker-for-mac/kubernetes-enable.png)

It should take a bit of time depending on the available Internet bandwidth and once it is done, it should report that the installation is complete. If you have any problems with this step, it might make sense to visit [Docker documentation](https://docs.docker.com/docker-for-mac/#kubernetes) on this matter.

Unlike Minikube, Docker for Mac doesn't hijack kubectl context, so you have to set it:

```
kubectl config use-context docker-for-desktop
```

Check whether your `kubectl` is using the **docker-for-desktop** context.

```
$ kubectl config get-contexts
CURRENT   NAME                                                         CLUSTER                                                      AUTHINFO                                                     NAMESPACE          
          minikube                                                     minikube                                                     minikube
*         docker-for-desktop                                           docker-for-desktop-cluster                                   docker-for-desktop
```

### [Add ingress controller to your Docker for Mac Kubernetes](#add-ingress-controller-to-your-docker-for-mac-kubernetes)

Add ingress controller:

```
relay ingress init
```

Output:

```
$ relay ingress init
using manifest from 'https://raw.githubusercontent.com/webrelay/ingress/master/deployment/deployment-rbac.yaml'...
namespace "webrelay-ingress" created
serviceaccount "webrelay" created
deployment "webrelay" created
clusterrolebinding "webrelay" created
clusterrole "webrelay" created
ingress added to the cluster, configuring authentication...
key and secret not supplied, generating new access credentials...
secret "webrelay-credentials" created
```

Yeah, some of you are probably now like:

![Back in my day we used helm](https://webhookrelay.com/blog/ingress-with-docker-for-mac/images/blog/ingress-with-docker-for-mac/back-in-my-day-helm.png)

But hold on, this command creates RBAC-enabled ingress controller in `webrelay-ingress` namespace with already configured credentials for **your** account. You can read more about Web Relay ingress controller [here](https://webhookrelay.com/blog/ingress-with-docker-for-mac/v1/installation/kubernetes/).

### [Create your Node.js application](#create-your-nodejs-application)

The next step is to write the application. Create a new directory named `hello` with the filename `server.js`:

```
var http = require('http');
var port = 8080
var handleRequest = function(request, response) {
  console.log('Received request for URL: ' + request.url);
  response.writeHead(200);
  response.end('Hello Internet!');
};
var www = http.createServer(handleRequest);
console.log('Listening on http://localhost:' + port);
www.listen(port);
```

To run the application:

```
node server.js
```

You should be able to see your “Hello World!” message at [http://localhost:8080/](http://localhost:8080/).

Stop the running Node.js server by pressing **Ctrl-C**.

The next step is to package your application in a Docker container.

### [Put your application into a Docker container](#put-your-application-into-a-docker-container)

Create a file, also in the `hello` directory, named Dockerfile. A Dockerfile describes the image that you want to build. You can build a Docker container image by extending an existing image. The image in this tutorial extends an existing Node.js image.

```
FROM node:9.2.0
EXPOSE 8080
COPY server.js .
CMD node server.js
```

This Dockerfile starts from the official Node.js image found in the Docker registry, exposes port 8080, copies your server.js file to the image and starts the Node.js server. Build your Docker image:

```
docker build -t hello-node:v1 .
```

What is really nice about Docker for Mac with Kubernetes is that you can easily run locally built Docker images inside Kubernetes cluster. No need to change Docker daemons or push images to the public repositories just to test them out. Now Docker for Mac Kubernetes can run the image you built.

### [Create Deployment and Service](#create-deployment-and-service)

Kubernetes [Deployments](https://kubernetes.io/docs/concepts/workloads/controllers/deployment/) checks on the health of the [Pods](https://kubernetes.io/docs/concepts/workloads/pods/pod/) and restarts the Pod's container if it terminates. Pod can consist of more than one containers but in this example we will only have one:

```
kubectl run hello-node --image=hello-node:v1 --port=8080
```

To view Deployments:

```
kubectl get deployments
```

Output:

```
$ kubectl get deployments
NAME         DESIRED   CURRENT   UP-TO-DATE   AVAILABLE   AGE
hello-node   1         1         1            1           8s
```

Since by default Pod is only accessible by its internal IP address within the Kubernetes cluster, we need to expose it. Create a [Service](https://kubernetes.io/docs/concepts/services-networking/service/):

```
kubectl expose deployment hello-node --type=ClusterIP
```

To view created services:

```
kubectl get svc
```

Output:

```
$ kubectl get svc
NAME         TYPE        CLUSTER-IP      EXTERNAL-IP   PORT(S)    AGE
hello-node   ClusterIP   10.102.194.95   <none>        8080/TCP   1m
```

### [Define ingress and expose your app to the Internet](#define-ingress-and-expose-your-app-to-the-internet)

![Things get interesting](https://webhookrelay.com/blog/ingress-with-docker-for-mac/images/blog/ingress-with-docker-for-mac/things-get-interesting.png)

Ingresses in Kubernetes provide an easy way to define routing rules between hostnames and services. Let's get our public endpoint with `relay` command client by creating a tunnel:

```
relay tunnel create --group webrelay-ingress hellonode
```

Output:

```
$ relay tunnel create --group webrelay-ingress hellonode
pis9izc72c1wd9i21gxqxm.webrelay.io<---->http://127.0.0.1
```

Parameter _--group webrelay-ingress_ is required to let our ingress controller know which tunnels it can manage.

> Note that users with paid plans can specify any custom subdomain (as long as it is not taken) without creating a tunnel first. This allows to just easily define `ingress.yaml` and ingress controller wil create a tunnel for it.

We are only interested in this `pis9izc72c1wd9i21gxqxm.webrelay.io` (host) part. Every user gets a unique link to their tunnel. Edit this code with your tunnel hostname and save it in a folder named `hello` with the filename `ingress.yml`:

```
# ingress.yml
apiVersion: extensions/v1beta1
kind: Ingress
metadata:
  annotations:
    kubernetes.io/ingress.class: webrelay # other ingress classes will be ignored
  name: relay-ingress
  namespace: default
spec:
  rules:
    - host: pis9izc72c1wd9i21gxqxm.webrelay.io # <- host has to match tunnel host
      http:
        paths:
        - path: /
          backend:
            serviceName: hello-node
            servicePort: 8080
```

Create it:

```
kubectl create -f ingress.yml
```

Output:

```
$ kubectl create -f ingress.yml
ingress "relay-ingress" created
```

Your application is now exposed to the public Internet. See next section how to access or just enter that hostname into your browser.

### [Accessing your application through the Internet](#accessing-your-application-through-the-internet)

To view existing ingresses:

```
relay ingress ls
```

Output:

```
relay ingress ls
ID                                     NAME                                                  HOST                                 BACKENDS                  CRYPTO              AUTH                AGE
58f26c61-8e42-45f4-a982-4cb70990d7e2   webrelay-ingress-pis9izc72c1wd9i21gxqxm.webrelay.io   pis9izc72c1wd9i21gxqxm.webrelay.io   default/hello-node/8080   off                 -                   2 seconds
```

**Backends** column should show `<namespace>/<service>/<port>` of the exposed service. You can access [http://pis9izc72c1wd9i21gxqxm.webrelay.io](http://pis9izc72c1wd9i21gxqxm.webrelay.io) with your browser (just change the link to your own tunnel address).

You can also use web UI at [https://my.webhookrelay.com/tunnels](https://my.webhookrelay.com/tunnels) to view your ingresses:

[![Ingress table in web UI](https://webhookrelay.com/blog/ingress-with-docker-for-mac/images/blog/ingress-with-docker-for-mac/ingress-table.png)](https://webhookrelay.com/blog/ingress-with-docker-for-mac/images/blog/ingress-with-docker-for-mac/ingress-table.png)

## [Wrapping up](#wrapping-up)

In this article we created, deployed and exposed an app to the Internet that is running locally on our laptops. Some people say that this is an **"actual hello world"** application and not just the usual **"hello localhost"**.

With Docker for Mac Kubernetes support it's now a lot easier to develop and test our applications. Build locally, run locally and demo locally. I hope Web Relay ingress controller will serve you great in developing, testing and running your apps.

As always, if you have any questions, feel free to contact me.