Mert Özen Further With Every Line

Blog

Mert Özen's blog posts on software development, backend, frontend, and DevOps.

Series
15 posts found
What Is a Container? How It Differs from a VM, Namespaces, cgroups and the OCI Standard
DevOps PART 01

What Is a Container? How It Differs from a VM, Namespaces, cgroups and the OCI Standard

A container is an ordinary Linux process that shares the host's kernel, with namespaces limiting what it can see and cgroups limiting how much it can use. We watch nginx from inside and outside and compare PIDs, find the docker CLI → dockerd → containerd → runc chain in the process tree, run the same image with Podman and discuss when a container is unnecessary.

14 Nov 2026 10 min 11
Installing Docker: Docker Desktop, Docker Engine on Linux and the Alternatives
DevOps PART 02

Installing Docker: Docker Desktop, Docker Engine on Linux and the Alternatives

On Windows you install Docker Desktop with WSL 2; on a Linux server you install Docker Engine from Docker's official apt repository, not the distribution's package. With real output we look at the docker.io and Compose v1 trap on Ubuntu 24.04, prove that the docker group really is root, try rootless mode, use docker context to see which engine you talk to, and cover Desktop licensing, alternatives such as Podman and WSL containers, and the amd64/arm64 emulation trap.

14 Nov 2026 12 min 11
The Container Lifecycle: docker run, ps, logs, exec, stop and Exit Codes
DevOps PART 03

The Container Lifecycle: docker run, ps, logs, exec, stop and Exit Codes

docker stop sends SIGTERM, or the image's STOPSIGNAL, to the container's PID 1, waits 10 seconds and then sends SIGKILL; if the app was started behind a shell, the signal never arrives and the container dies with 137. With real output we cover container states, logs and exec, exit codes 0/1/137/139/143, ProcessExit no longer running on SIGTERM in .NET 10, graceful shutdown with the Generic Host, and restart policies.

14 Nov 2026 14 min 13
Inside an Image: Layers, Tags, Digests, Registries and Multi-platform Manifests
DevOps PART 04

Inside an Image: Layers, Tags, Digests, Registries and Multi-platform Manifests

An image is made of read-only layers, a config and a manifest listing them; for multi-platform images the tag points to an index with one manifest per architecture. Tags move, digests do not: on a local registry we repoint a tag to another image and see what a digest pin buys, read Docker Hub's rate-limit header, and look at the containerd image store and a semver plus SHA tag strategy instead of latest.

14 Nov 2026 13 min 10
Dockerfile Basics: FROM, RUN, COPY, WORKDIR, ENV, ARG, USER, EXPOSE, CMD and ENTRYPOINT
DevOps PART 05

Dockerfile Basics: FROM, RUN, COPY, WORKDIR, ENV, ARG, USER, EXPOSE, CMD and ENTRYPOINT

In a Dockerfile, RUN, COPY, ADD and WORKDIR touch the file system and produce layers; ENV, ARG, USER, EXPOSE, CMD and ENTRYPOINT are only written to the image config. We write the first Dockerfile for Bookstore.Tools, catch the draft's mistakes with docker build --check, and see with real output how ENTRYPOINT and CMD combine, how a token passed as ARG shows up in docker history, what .dockerignore changes, why EXPOSE opens no port, and the apt-get cache trap.

14 Nov 2026 13 min 10
Build Cache and BuildKit: Layer Order, Cache Mounts, Build Secrets and Bake
DevOps PART 06

Build Cache and BuildKit: Layer Order, Cache Mounts, Build Secrets and Bake

The build cache does not rerun a step unless its inputs change; for COPY the input is file content, so copying the csproj first and separating restore from source code keeps a code change from downloading packages again. On Bookstore.Tools we cut the build from 4.6 s to 1.6 s, measure a NuGet cache mount, pass a private feed token with a secret mount without leaking it, and look at multi-platform builds with QEMU and docker buildx bake.

14 Nov 2026 15 min 11
Multi-stage Builds in Depth: Targets, a Test Stage, Parallel Stages and Image Size
DevOps PART 07

Multi-stage Builds in Depth: Targets, a Test Stage, Parallel Stages and Image Size

In a multi-stage build the final image holds only the last stage's content, and BuildKit builds only the stages that lead to the target, running independent ones in parallel. We split Bookstore.Tools into restore, build, test, export, debug and final stages, cut the image from 1.34 GB to 143 MB, see the limits of a test stage and a chiseled image, and produce a two-architecture image without QEMU using --platform=$BUILDPLATFORM.

14 Nov 2026 16 min 10
Containerizing ASP.NET Core: .NET 10 Images, Chiseled, Non-root, Port 8080 and Globalization
DevOps PART 08

Containerizing ASP.NET Core: .NET 10 Images, Chiseled, Non-root, Port 8080 and Globalization

ASP.NET Core images listen on port 8080 and carry the non-root app user through APP_UID; a chiseled image, however, has no ICU or tzdata, so code that asks for Turkish culture or the Europe/Istanbul time zone returns 500. We containerize Bookstore.Api, compare image families, fix that bug with chiseled-extra, and see configuration through environment variables, a health check without a shell and how a memory limit affects the GC, all with real output.

14 Nov 2026 13 min 9
.NET Containers Without a Dockerfile: dotnet publish /t:PublishContainer and Container MSBuild Properties
DevOps PART 09

.NET Containers Without a Dockerfile: dotnet publish /t:PublishContainer and Container MSBuild Properties

With dotnet publish /t:PublishContainer the .NET SDK produces an image without a Dockerfile or a Docker build: it puts the publish output on the base image as one layer, sets the app user and port 8080 itself, and sends the result to the local daemon, a tar file or straight to a registry. We produce Bookstore.Api this way, try ContainerFamily, a multi-architecture index and ContainerImageFormat, and compare it with the Dockerfile path by size, layers and time.

14 Nov 2026 11 min 17
Containerizing an Angular App: a Node Build Stage, Unprivileged Nginx and Runtime Configuration
DevOps PART 10

Containerizing an Angular App: a Node Build Stage, Unprivileged Nginx and Runtime Configuration

An Angular app is compiled in a build stage with Node, and only the static files are copied into a non-root nginx image; the API address that changes per environment goes not into the build but into a config.json written from environment variables when the container starts. With real output we cover the Dockerfile for bookstore-web, SPA fallback and cache headers, runtime config with provideAppInitializer, CORS, when SSR is needed and the node_modules trap.

14 Nov 2026 11 min 13
Volumes, Bind Mounts and tmpfs: Keeping Data in Containers
DevOps PART 11

Volumes, Bind Mounts and tmpfs: Keeping Data in Containers

A container's writable layer goes away when the container is deleted; data that must persist belongs on a named volume, files from the host on a bind mount and temporary data on tmpfs. With real output we run BookstoreDb on a SQL Server 2025 container with a volume, keep the data across container deletion, back it up with BACKUP DATABASE and tar, fix the non-root SQL Server's Permission denied on a bind mount, use tmpfs for tests and avoid anonymous volumes.

14 Nov 2026 15 min 13
Docker Networking: Bridge, User-defined Networks, Container DNS and Port Publishing
DevOps PART 12

Docker Networking: Bridge, User-defined Networks, Container DNS and Port Publishing

Containers on the default bridge cannot find each other by name; on a user-defined network Docker's embedded DNS (127.0.0.11) resolves container names and aliases. With real output we connect Bookstore.Api to SQL Server with Server=bookstore-db, make bookstore-web's nginx proxy the API on the same origin, publish only the entry point on 127.0.0.1, and look at the iptables rules that bypass ufw, the experimental nftables backend and host.docker.internal.

14 Nov 2026 13 min 13
Blog Map