Docker and DevOps

An application that runs the same everywhere, and releases with no manual steps: this is how we ship our own products.

We set up reproducible environments and automated releases with Docker, GitHub Actions and Coolify. Hippotenus, Logaritim and pepechura.com run this way.

Last updated:

What we have built with it

All of them are live; store pages and details are on the Products page.

Hippotenus

Platform for education institutions

The API, web app and marketing site are separate Docker images, built in GitHub Actions and deployed to staging and production with Coolify.

See the product

Logaritim

Question pool and exam builder

The FastAPI back end and the front end are separate Docker images; once the tests pass, the image is built and released with Coolify.

See the product

What Docker solves

Docker packages an application together with everything it needs to run (operating-system packages, runtime, dependencies) into a single image. The same image runs the same way on a developer’s laptop, in the test environment and in production; nothing is installed on the server by hand, and “it worked on my machine” goes away. The DevOps part is making that image get tested, built and released automatically the moment code is pushed.

Where Docker fits well

  • The application has several parts, such as an API, a database and a background worker
  • You want several environments, such as staging and production, set up the same way
  • The application has to run on your own server or on a server in Türkiye
  • You want to keep the option of moving from a platform to your own server, or back

Where we would not see Docker as necessary

  • The app is a Next.js site that a platform like Vercel can deploy directly: we run Atölye Tasarım without Docker, on the platform’s own deployment flow
  • The mobile app’s back end is entirely on a managed service like Firebase: SoruVerse has no server to manage
  • Nobody will update and watch the server, and maintenance is not planned: a managed platform is the better fit then

How code reaches production

pepechura.com, Hippotenus and Logaritim follow the same path. In Hippotenus the main branch goes to production and the development branch to a staging environment. For local development, a single docker-compose file brings up PostgreSQL, Redis, the API, the web app and the marketing site together, and the API waits until the database is ready.

StepWhat happensWhy
TestTests run when code reaches the main branch; on pepechura.com and Logaritim the release depends on them passingSo a broken version never becomes an image
BuildThe Docker image is built in GitHub Actions, not on the serverSo the production server’s CPU is not busy building
RegistryThe image is tagged with the commit ID and pushed to GitHub Container RegistryIt is always clear which code is running in production
ReleaseCoolify pulls the new image and swaps the container; in Hippotenus, migrations run as the new container startsIf a migration fails the new version does not come up and the old one keeps running
CheckOn pepechura.com the workflow waits until the new container is liveA failed release does not go unnoticed; the workflow fails

Your own server or a platform

The same Dockerfile runs on a platform such as Railway (PaaS) and on your own server. Hippotenus’s Railway configuration is still in its repository; today Hippotenus, Logaritim and pepechura.com run on our own server with Coolify. Coolify is an open-source deployment panel installed on your own server: it pulls the image and manages HTTPS certificates and health checks.

Platform (e.g. Railway)Your own server (with Coolify)
SetupFast; the platform manages the serverSetting up and updating the server is on you or your maintenance team
Where data livesThe regions the platform offersThe server you choose, for example in Türkiye
CostChanges with usageMostly a fixed server price
Application imageThe same DockerfileThe same Dockerfile
Our exampleHippotenus’s previous environmentHippotenus, Logaritim, pepechura.com

Databases, background jobs, backups and monitoring

In one client project a single Docker Compose file sets up the whole system: a PostgreSQL database with no port open to the outside, a service that runs once to update the database before the application starts, the application itself, a background worker running from the same image, and Caddy, which obtains and renews the HTTPS certificate by itself. A script backs up the database and the uploaded files. In another client project, .NET services and a PostgreSQL database with the PostGIS extension run in Docker, and the Elastic Stack watches container logs, server metrics and health endpoints. In Hippotenus the databases are backed up every night, the backups are encrypted and copied to separate storage in Türkiye, and a restore has been tested.

GitHub Actions

Running tests, building images and triggering releases. We use it for pepechura.com, Hippotenus and Logaritim.

GitHub Container Registry

Where built images are stored under their commit ID. We use it in the same three projects.

Coolify

The open-source deployment panel that runs the images on our own server. pepechura.com, Hippotenus and Logaritim run on it.

Caddy and Nginx

The server in front: HTTPS, compression, upload limits. We use them for Logaritim’s front end and in client projects.

restic

Encrypted, versioned backups. We use it for the Hippotenus and Logaritim database backups.

Elastic Stack

Log collection, server metrics and uptime checks. We use it in a client project.

How a Docker and DevOps project runs

  1. 01

    Free scoping call

    30 min

    We talk about where and how the application runs today, how releases are done and what causes you the most trouble.

  2. 02

    Written scope and quote

    We write down the environments, the release flow, the backup and monitoring needs, and the acceptance criteria.

  3. 03

    Weekly releases

    Every week we deliver a working piece: first the development environment, then the test and build flow, then staging.

  4. 04

    Testing and cut-over

    A senior QA tests the version on staging before it goes to production. When moving hosts, we keep the old environment ready for a rollback for a while.

  5. 05

    The 30 days after launch

    30 days

    We fix the bugs that surface in this period free of charge; after that you can continue with monthly maintenance.

Timelines and budget ranges are published on our service and pricing pages; everything on this page follows the same figures.

Questions about Docker and DevOps

Can you move my existing application to Docker and my own server?

Yes. When we moved pepechura.com from Vercel to our own server, the site was set up to read its redirects and headers from the same file on both hosts, and the old environment was kept running for a while as a fallback. For your application we first review the current setup and then plan the move step by step.

Do you use Kubernetes?

No. In our projects so far, Docker Compose or Coolify on a single server has been enough and simpler to maintain. If your scale calls for Kubernetes, we will say so openly in the scoping call.

Is my database exposed to the internet?

No. In Hippotenus, PostgreSQL and Redis live only inside the Docker network and are not open to the outside; developers reach the production database only through an SSH tunnel. We also run the containers that hold our own server code as a non-root user.

Are backups and monitoring included?

It depends on the scope. We write backups and, where needed, log collection and uptime monitoring into the quote as separate items. The examples are above: nightly encrypted backups in Hippotenus, and monitoring with the Elastic Stack in a client project.

What do I keep when the project ends?

A perpetual licence to use the software and user documentation. If you want the source code, including the Dockerfiles and the release workflow, transferred to you, that is possible for an extra fee, stated separately in the quote.

Related services

Custom softwareWeb applicationMVP
Contact

Let’s talk about how you release

In a free 30-minute scoping call we work out where and how your application should run, and how to make its releases automatic.