Werf : Deploy or Not Deploy, There is No Try — Part 1
This article is the first in a series dedicated to Werf. We will cover the basics, focusing on building Docker images. Whether you’re a beginner or an experienced user, you’ll learn how Werf simplifies your builds and facilitates deployment on Kubernetes.
You can find the original article in French on our blog
Kubernetes : A very very very vast …. universe
In the world of DevOps/SRE and Platform Engineering, Kubernetes is widely regarded as the go-to standard for container orchestration. However, for many padawans, diving into this ecosystem is like venturing into the Outer Rim, where every parsec traveled could lead you into the jaws of a giant exogorth. Between the YAML files, as cryptic as the Tusken Raiders’ language, and the multitude of acronyms to decipher, Kubernetes can quickly become a real headache, even for the most seasoned Kaminoans.
The main issue?
Kubernetes is not just a tool. It is the engine of a complex ecosystem, and like all great power, it comes with great responsibility. Whether it’s managing multiple configurations, handling version upgrades, ensuring security, or maintaining scalability, Kubernetes requires rigorous technical expertise. For many DevOps and SRE teams, managing these aspects on a daily basis can become a real challenge.
The solution: Werf, your trusted co-pilot
Imagine Han Solo driving the Millennium Falcon without his loyal co-pilot Chewbacca. No matter how he’s skilled, flying alone in space would be a perilous mission. This is exactly what Werf represents! It’s the Chewbacca of your Kubernetes deployments, always there to back you up. With Werf, every build and deployment command becomes as easy as jumping into hyperspace with a T-14 Hyperdrive generator.
A new hope
If deploying an application on Kubernetes feels as intimidating as piloting the Millennium Falcon through an asteroid field, don’t worry — you’re not alone. Even the most seasoned DevOps professionals can sometimes struggle.
But what if you could master this Force and become a true DevOps Master?
Ready to master Kubernetes? Then fasten your seatbelts, and may the Force be with you!
Werf stands out for its ability to automate and simplify build and deployment processes, two essential aspects for effectively using Kubernetes. It is particularly powerful when used on a solution like Kontainers, which I use daily.
Manage your Docker images with complete peace of mind
Werf handles everything related to building Docker images. With a single Dockerfile and a simple command, you can orchestrate your entire build process. No more dealing with complex scripts or rebuilding everything with each change: Werf’s smart container caching system ensures that only modified elements are rebuilt, saving you valuable time.
The process is smooth and predictable, with no unpleasant surprises. Whether you’re in development or ready for production, Werf simplifies these steps so you can focus on what truly matters.
Installing Werf on Linux and macOS
Installing Werf is quick and easy, whether you’re running Linux or macOS. Here’s how.
The following command automatically downloads and installs Werf on a Linux distribution, sparing you any complicated manual configuration.
curl -L https://werf.io/install.sh | bash
On macOS, you can install Werf using Homebrew, the popular package manager for macOS.
brew install werf
Building a Go and HTMX application with Werf
Now that Werf is installed, let’s see how to use it to build an application with a Go backend and a HTMX frontend. Suppose you have two separate directories: one for the backend application and another for the user interface.
1. Project structure
Here is an example of a project structure for this application:
/my-app
│
├── backend/
│ ├── main.go # Go files for the backend
│ └── Dockerfile # Dockerfile for the backend
│
├── frontend/
│ ├── index.html # Main HTML file with HTMX
│ ├── static/ # Directory for static files
│ └── Dockerfile # Dockerfile for the frontend
│
└── werf.yaml # Werf configuration file
2. Dockerfile for Go backend (multi-stage build)
The multi-stage build allows you to build the Go application in the first stage, then copy only the executable into a lighter image for production. This reduces the size of the final image and the attack surface.
# Step 1: Build the Go application
FROM golang:1.22-alpine3.20 AS builder
# Working directory for compilation
WORKDIR /app
# Copy Go files into the container
COPY go.mod ./
COPY go.sum ./
# Download Go dependencies
RUN go mod download
COPY main.go ./
# Compile the Go application
RUN go build -o main .
# Step 2: Production image
FROM alpine:3.20
# Working directory for production
WORKDIR /app
# Copy the executable from the build stage
COPY --from=builder /app/main .
# Expose the application's port
EXPOSE 8080
# Command to run the application
CMD ["./main"]
Step 1: We use a Go image to compile the application. This compilation step takes place in the builder phase.
Step 2: The final image is based on Alpine, a much lighter image, which reduces the overall size. Only the compiled Go executable is copied into this image, improving both the security and efficiency of the deployment.
3. Dockerfile for the HTMX frontend
To deploy the HTMX-based frontend, we’ll use an alpine-based NGINX server to serve the static files. Here’s an example of an adapted Dockerfile:
# Using a lightweight NGINX image
FROM nginx:1.27-alpine3.20
# Copy HTML and static files into the container
COPY ./static /usr/share/nginx/html/static
COPY ./index.html /usr/share/nginx/html
# Expose the NGINX default port
EXPOSE 80
4. The werf.yaml file
The werf.yaml
file is the heart of Werf configuration. It defines the Docker images to be built and the deployment steps. Here’s a basic configuration example for this project, including a backend and a frontend:
configVersion: 1
project: padawan-trainer
---
image: backend
dockerfile: ./backend/Dockerfile
---
image: frontend
dockerfile: ./frontend/Dockerfile
Definitions :
- configVersion : Version of the Werf configuration.
- project : Project name, in this case padawan-trainer.
- images : the names of the container images that will be used by Werf to identify the backend and frontend.
- dockerfile : relative path to container definition files.
Note : All the documentation on configuring the `werf.yaml` file is available here :
- Documentation Werf v1.2
- Documentation Werf v2
5. Build and push Docker images
We’ve come to the final step of this first article! Build Docker images for your application’s backend and frontend in a single command.
werf build --repo ttl.sh/padawan-trainer --dev
This command will build and send your images to the specified Docker repo (in our case: ttl.sh, which is a temporary repo perfect for our example), ensuring that your changes are correctly taken into account for future deployment.
Conclusion
Congratulations! You’ve made it through this first article and are now officially a promising padawan. You’ve learned how Werf simplifies the creation of Docker images, making the process incredibly straightforward.
But this is only the beginning! In the next article, we’ll dive deeper into using Werf for deploying Kubernetes applications with Helm. We’ll explore how Helm and Werf complement each other to automate and simplify your deployments, establishing a robust and reliable process.