October 8, 2024

Werf: Deploy or Not Deploy, There is No Try - Part 1

This article is the first in a series dedicated to Werf. We cover the basics, with a focus on building Docker images.

Werf: Deploy or Not Deploy, There is No Try - Part 1

This article is the first in a series dedicated to Werf. We cover the basics, with a focus on building Docker images.

Kubernetes: a very, very, very… vast universe

In the world of DevOps, SRE and Platform Engineering, Kubernetes is hailed as the undisputed standard for container orchestration. Yet for many a padawan, diving into this ecosystem feels like exploring the Outer Rim, where every parsec travelled could land you straight in the gaping maw of an exogorth. Between YAML files as cryptic as Tusken Raider jargon and a swarm of acronyms to decipher, Kubernetes can quickly turn into a real headache — even for the most seasoned Kaminoans.

The core problem?

Kubernetes is not just a tool. It is the engine of a complex ecosystem, and like any great power, it comes with great responsibility. Whether it’s juggling multiple configurations, handling version upgrades, security, or scalability, Kubernetes demands rigorous technical mastery. For many DevOps and SRE teams, dealing with these aspects day in, day out can become a genuine challenge.

The solution: Werf, your trusted copilot

Picture Han Solo at the controls of the Millennium Falcon without his faithful copilot Chewbacca. However talented he may be, flying solo through space would be a perilous mission. That is exactly what Werf is! It’s the Chewbacca of your Kubernetes deployments, always there to back you up. With Werf, every build and deploy command becomes as easy as jumping to lightspeed 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, rest assured, you are not alone. Even the most battle-hardened DevOps engineers sometimes come out bruised.

But what if you could master this Force and become a true DevOps Master?

Ready to master Kubernetes? Then buckle up, and may the Force be with you!

Werf stands out for its ability to automate and simplify build and deployment processes, two essential aspects of using Kubernetes well. It is particularly powerful when used on a platform like Kontainers, which I use every day.

Manage your Docker images with peace of mind

Werf takes care of everything related to building Docker images. With a single Dockerfile and one simple command, you can orchestrate your entire build process. No more wrangling complex scripts or rebuilding everything from scratch after each change: the smart container caching system Werf relies on makes sure only the modified parts get rebuilt, saving you precious time.

The process is smooth and predictable, with no nasty surprises. Whether you’re still in development or ready to ship to production, Werf streamlines these steps so you can focus on what matters:

Installing Werf on Linux and macOS

Installing Werf is quick and easy, whether you’re on Linux or macOS. Here’s how.

The following command automatically downloads and installs Werf on a Linux distribution, sparing you any tricky manual configuration.

curl -L https://werf.io/install.sh | bash

On macOS, you can install Werf using Homebrew, the famous 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 made up of a Go backend and an HTMX frontend. Let’s assume you have two separate directories: one for the backend application and another for the user interface.

1. Project structure

Here is an example 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/           # Folder for static files
   └── Dockerfile        # Dockerfile for the frontend

└── werf.yaml             # Werf configuration file

2. Dockerfile for the Go backend (multi-stage build)

A multi-stage build lets you compile the Go application in a first stage, then copy only the executable into a lighter image for production. This reduces both the size of the final image and its attack surface.

Here is the content of the Dockerfile for Go:

# Stage 1: Build the Go application
FROM golang:1.22-alpine3.20 AS builder
# Working directory for compilation
WORKDIR /app
# Copy the Go files into the container
COPY go.mod ./
COPY go.sum ./
RUN go mod download
COPY main.go ./
# Compile the Go application
RUN go build -o main .
# Stage 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 port
EXPOSE 8080
# Command to run the application
CMD ["./main"]

3. Dockerfile for the HTMX frontend

To deploy the HTMX-based frontend, we will use an alpine-based NGINX server to serve the static files.

Here is a suitable Dockerfile example:

# Use a lightweight NGINX image
FROM nginx:1.27-alpine3.20
# Copy the HTML and static files into the container
COPY ./static /usr/share/nginx/html/static
COPY ./index.html /usr/share/nginx/html
# Expose the port for NGINX
EXPOSE 80

4. The werf.yaml file

The werf.yaml file is the heart of your Werf configuration. It defines the Docker images to build and the deployment steps. Here is 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: the version of the Werf configuration.

  • project: the project name, here padawan-trainer.

  • images: the container image names Werf will use to identify the backend and the frontend.

  • dockerfile: the relative path to the container definition files. You can find the complete syntax for Werf files in the documentation:

  • Werf v1.2 documentation

  • Werf v2 documentation

5. Building and pushing the Docker images

We’ve reached the final step of this first article! Build the Docker images for your application’s backend and frontend with a single command.

werf build --repo ttl.sh/padawan-trainer --dev

This command builds and pushes your images to the specified Docker repository (in our case: ttl.sh, a temporary registry that is perfect for our example), making sure your changes are properly taken into account for a future deployment.

Conclusion

Congratulations! You survived this first article — you are officially a promising padawan. You’ve discovered how Werf can simplify building Docker images, making the whole process remarkably easy.

But this is only the beginning! In an upcoming article on our blog, we will dig deeper into using Werf to deploy Kubernetes applications with Helm. We’ll see how Helm and Werf complement each other to automate and streamline your deployments, building a robust and reliable process.