Test your apps in Docker or Kubernetes locally

Today I’m going to talk about a few things that happen to me pretty often, which is that developers don’t like to test their changes more than some basic examples or only in to write box way, no one likes testing neither use Linux (which is the OS where most of the production apps run) so their development environment is far different from what apps are supposed to work with. Let’s talk about a few things, one of them which is import for everyone is SDLC.
Software Development Life Cycle
So, coding is an important part of the SDLC or the product itself but pushing your code to the repository is neither the end nor the beginning, there are a lot (really a lot) of things happening previously and after that!
Graph took from [HERE](https://www.geeksforgeeks.org/software-development-life-cycle-sdlc/)

So it’s significant to understand the complete SDLC, why? Because one of the final aspects of it is the deployment! And the deployment is totally dominated by the Linux OS.

But people don’t use Linux in the personal or working computers, not as much as Windows, so that creates us a problem where developers try their apps on Windows then push their code and end up uploading that code to a Linux machine. So here if there is an error because the OS works differently.
How we can solve it?
One of the many solutions for these is something that is quite popular in the recent decade and is containers, I’m not going to explain what they are or how they're work, but rather why we should use them at least for local development, even if your server doesn’t run another OS.
Proposal #1: Docker
Using the docker engine we can build what is called Dockerfiles here is an example of a Golang app running GIN a web framework.
# DEV
FROM golang:alpine3.20 AS build
WORKDIR /app
COPY . /app
RUN go mod download
RUN GOARCH=amd64 go build -o ./bin/InfobaeAPI ./src/main.go
# PROD
FROM alpine:3.20
RUN addgroup -S appgroup && adduser -S infobae -G appgroup
WORKDIR /app
COPY --from=build /app/bin/InfobaeAPI /app/bin/InfobaeAPI
ENV GIN_MODE=release
USER infobae
ENV PORT=3000
EXPOSE ${PORT}
ENTRYPOINT ["/app/bin/InfobaeAPI"]
If our apps communicate with other components, or we just want to have an easier read of the panorama (or just type less) we can create a compose.yml
services:
infobae:
container_name: infobae
## https://hackernoon.com/how-to-harden-your-docker-containers-using-seccomp-security-profile-81153ucz
security_opt:
- no-new-privileges
- seccomp=./security/seccomp.json
- apparmor=./security/non-root.profile
restart: unless-stopped
cap_add:
- CHOWN
- NET_BIND_SERVICE
cap_drop: ["ALL"]
build:
context: .
dockerfile: Dockerfile
ports:
- "${PORT}:3000"
In this example, I’m creating a service with a unique container that has some security constraints.
This container is going to build in an operating system called alpine which is a minimal operating system often used for work fulls that don’t need that many things.
With docker compose up -d while having the compose and Dokerfile in hand, we can create a docker container that will run our app with the base OS and our app.

The end result is something like this where I see my app running, if my machine was a windows one, and I wanted to try how it works in a Linux environment, this was a success (at least for runtime apps, read something about build time just in case)
This workflow is valid in simple environments where Kubernetes is not into mind. Next we are going to cover the Kubernetes part.
Proposal 2: Minikube
Post used as reference [HERE](https://www.digitalocean.com/community/tutorials/how-to-use-minikube-for-local-kubernetes-development-and-testing)
In some workflows there are Kubernetes clusters with are part of the entire infrastructure, so testing docker would be fine since the container itself is part of the pods which is the smallest components in the Kubernetes ecosystem, but maybe we want to try more components of it, that’s why building a local cluster can be handy.
But you may be thinking, building a local cluster won’t be hard for a developer? Is not even part of their job, well kinda. Their job is to make the app work no matter what, so testing locally in a real scenario would be ideal for them. Lucky enough, there are solutions like Minikube which creates clusters for local development quite easily.
Now let’s get into practice, In my case I used Kompose to convert the compose.yml into Kubernetes manifestos, with a command like this kompose -f compose.yml convert I got this file
apiVersion: apps/v1
kind: Deployment
metadata:
annotations:
kompose.cmd: kompose -f docker-compose.yml convert
kompose.version: 1.34.0 (HEAD)
labels:
io.kompose.service: infobae
name: infobae
spec:
replicas: 1
selector:
matchLabels:
io.kompose.service: infobae
template:
metadata:
annotations:
kompose.cmd: kompose -f docker-compose.yml convert
kompose.version: 1.34.0 (HEAD)
labels:
io.kompose.service: infobae
spec:
containers:
- image: dyallo/infobae_api
name: infobae-dev
ports:
- containerPort: 3000
protocol: TCP
securityContext:
allowPrivilegeEscalation: false
capabilities:
add:
- CHOWN
- NET_BIND_SERVICE
drop:
- ALL
restartPolicy: Always
And this one too
apiVersion: v1
kind: Service
metadata:
annotations:
kompose.cmd: kompose -f docker-compose.yml convert
kompose.version: 1.34.0 (HEAD)
labels:
io.kompose.service: infobae
name: infobae
spec:
ports:
- name: "5000"
port: 5000
targetPort: 3000
selector:
io.kompose.service: infobae
type: NodePort
Now using kubectl we can do something like kubectl -f apply . and apply all changes of the manifestos we created before with kompose

Here I make sure that the cluster is running with minikube start, apply the manifestos with kubectl apply -f ./kubernetes, check that the service is running kubectl get services grab the IP from the cluster since I’m using NodeIP in the service with minikube ip and curl the app (since is an API).
Conclusion
It is always necessary to test (also with testing!) your apps before publishing into the server, do not be satisfied only by running things like npm run dev or npm run build your OS is not always the same as the server! Learn more about what happens before and after you start coding.
Don’t be a code monkey.




