Containers and Kubernetes on macOS: A Setup for 2022

boat ride in the Seine, Paris @photosbysaurav on Instagram —

Update: I have an updated version of this article which builds upon the setup described below, you can find it here —

What Docker Desktop used to help me with

  • Creating and managing Docker Images
  • Using and Publishing Images from a Container Registry
  • Test out Kubernetes Applications on a local Kubernetes Cluster
  • And probably the most important, the ability to turn off the Docker Server when not needed

Few things about Docker and the OCI

The choices — and containerd

rancher desktop (

microK8S (

k0s (

colima (

The Setup

$ brew install colima
$ colima version
$ colima start --with-kubernetes -r containerd
$ colima nerdctl run hello-world
Hello from Docker!
This message shows that your installation appears to be working correctly.
To generate this message, Docker took the following steps:
1. The Docker client contacted the Docker daemon.
2. The Docker daemon pulled the "hello-world" image from the Docker Hub.
3. The Docker daemon created a new container from that image which runs the
executable that produces the output you are currently reading.
4. The Docker daemon streamed that output to the Docker client, which sent it
to your terminal.
To try something more ambitious, you can run an Ubuntu container with:
$ docker run -it ubuntu bash
Share images, automate workflows, and more with a free Docker ID:
For more examples and ideas, visit:

An Example — Images & Containers

$ cat index.jsconst http = require('http')const ping = (_, res) => {
message: 'ping'
const server = http.createServer(ping)const port = process.env.PORT || 5000
const host = process.env.HOST || 'localhost'
server.listen(port, host)
console.log(`started server at ${host}:${port}`)
alias docker='colima nerdctl -- -n'
$ cat DockerfileFROM node:lts-alpineWORKDIR /appCOPY index.js ./CMD node index.js$ docker build -t simple-node-server .
$ docker run -d -p 8081:80 -e HOST= -e PORT=80 simple-node-server
$ curl <http://localhost:8081>

Example Continued — with Kubernetes

apiVersion: v1
kind: Pod
name: simple-node-server
app: simple-node-server
- name: main
image: simple-node-server:latest
imagePullPolicy: IfNotPresent
memory: 250Mi
cpu: 0.25m
- name: PORT
value: "80"
- name: HOST
value: ""
---apiVersion: v1
kind: Service
name: simple-node-server
app: simple-node-server
type: NodePort
- protocol: TCP
port: 80
targetPort: 80
$ kubectl create ns simple-app
$ kubectl apply -f deployment.yaml -n simple-app
$ kubectl get svc -n simple-app simple-node-server -o json | jq '.spec.ports[0].nodePort'



Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Saurav Sahu

Opinions are my own. Full Stack Engineer. CEO of “it was just working 🤷‍♂️”