Skip to content

Cloud & Infrastructure

Docker

Containerise honestly — reproducible builds, small secure images, and a clear line where Docker ends and orchestration begins.

Overview

Docker packages an application and everything it needs to run — libraries, system tools, runtime, configuration — into an image that runs the same way on a laptop, a CI runner and a production host. It does this with OS-level virtualisation: containers share the host’s Linux kernel and are isolated with namespaces and cgroups, rather than each carrying a full guest operating system the way a virtual machine does. That shared kernel is why containers start in milliseconds, weigh megabytes instead of gigabytes, and let you run dozens on a machine that would groan under a handful of VMs.

The practical win most teams feel first is the death of “works on my machine”. An image built from a Dockerfile is deterministic: the same instructions produce the same layered filesystem, so the thing a developer tested is byte-for-byte the thing that ships. Docker Compose extends that to whole environments — your app, its database, a cache and a message broker — described in one file and brought up with a single command. For onboarding, CI and reproducing bugs, this alone justifies adopting it.

Docker is not, however, a production platform on its own. It builds and runs individual containers extremely well; it does not decide which host a container should live on, restart it across a fleet, roll it out gradually or give it a stable network identity. Those are orchestration concerns, and once you run many containers across many machines you hand off to Kubernetes, Amazon ECS or similar. We treat Docker as the foundation — the build and packaging layer — and are deliberate about where that foundation ends and the orchestrator begins.

Best for — Teams that want reproducible, portable builds and a clean packaging layer that feeds straight into cloud orchestration without dragging a full VM around.

Why teams choose Docker

  • Reproducible everywhere

    A Dockerfile produces the same layered image on every machine, so the environment a developer tested is the one that reaches production. Environment drift — the class of bug that eats afternoons — largely disappears, and new engineers get a working stack in minutes rather than a day of setup notes.

  • Lighter and faster than VMs

    Sharing the host kernel means containers start in a fraction of a second and cost megabytes, not gigabytes. You pack far more workloads onto the same hardware, spin up ephemeral environments cheaply for tests, and scale out with almost no boot latency.

  • A portable deployment unit

    An image is a self-contained artefact that runs unchanged on a laptop, in CI and on any container platform. That portability is what lets you move between clouds, adopt Kubernetes or ECS later, and keep your build pipeline decoupled from where the thing eventually runs.

Why businesses choose Docker

  • It is the de facto standard for building container images — the tooling, registries and cloud integrations all assume it, so you are never on an island.
  • The learning curve to productive is genuinely short: a Dockerfile and a Compose file get a team reproducible environments in an afternoon.
  • It decouples your build from your runtime, so you can start on a single host and adopt orchestration later without rebuilding your packaging.
  • The ecosystem — base images, scanners, registries, CI actions — is mature and well documented, which keeps operational surprises rare.

What we build with Docker

The capabilities this technology is genuinely strong at — and what we most often build with it.

  • Dockerfiles and layered images

    An image is built from an ordered set of instructions, each producing a cached filesystem layer. Understanding layer ordering — putting rarely-changing steps first so dependency installs are cached — is the difference between a ten-second rebuild and a five-minute one. We write Dockerfiles that build fast and stay legible.

  • Multi-stage builds

    A build stage compiles or bundles your app with the full toolchain; a final stage copies only the resulting artefact into a minimal runtime image. This is how you ship a 40MB image instead of an 800MB one — no compilers, no build caches, no source in the thing that runs in production, which shrinks both the attack surface and the pull time.

  • Docker Compose for local development

    One YAML file describes your whole stack — app, PostgreSQL, Redis, whatever else — with networks, volumes and environment wired together. New engineers run one command and get a working system; the same file reproduces a bug locally that a colleague hit. It is the single most effective onboarding and debugging tool Docker gives you.

  • Registries and image distribution

    Images are pushed to and pulled from registries — Docker Hub, GitHub Container Registry, ECR, GCR — and tagged so deployments are reproducible. We treat immutable digests and a private registry as the default, because “latest” in production is a footgun and public base images are part of your supply chain whether you audit them or not.

  • Volumes and persistent data

    Containers are ephemeral; their filesystems vanish on removal. Anything that must survive — databases, uploads, state — lives in named volumes or bind mounts, backed by real storage. We are deliberate here because the most common Docker disaster is treating a stateful workload as if it were stateless and discovering the loss at the worst moment.

  • Image scanning and slim base images

    Every layer you inherit carries its packages and their vulnerabilities. We build on minimal or distroless bases, pin versions, and wire vulnerability scanning into CI so a known CVE fails the build rather than reaching production. Small, scanned images are not automatic — they are a habit you enforce in the pipeline.

Use cases

  • Consistent local development environments

    A Compose stack replaces a page of setup instructions with one command. Every engineer runs the same database version, the same cache, the same service topology, and a new hire is productive on day one instead of debugging their machine.

  • CI/CD build and test pipelines

    Containers give CI clean, disposable environments per run — no state bleeding between builds, no “the runner had a different version” failures. The image tested in CI is the exact artefact promoted to production, so the pipeline verifies the real thing.

  • Packaging services for orchestration

    Microservices are built as images and handed to Kubernetes or ECS, which schedule, scale and heal them. Docker is the packaging step; the orchestrator is the runtime. Getting the image right — small, secure, correctly configured — is what makes the orchestration layer behave.

  • Legacy application modernisation

    Wrapping an older application in a container pins its runtime, dependencies and configuration in place, making an otherwise fragile system reproducible and movable. It is often the pragmatic first step of a modernisation programme — stabilise, then refactor — rather than a rewrite up front.

When Docker is the right choice

  • You want dev/prod parity and reproducible builds — every engineer, CI runner and server executes the identical image, and onboarding drops to a single command.
  • You are packaging services for a modern cloud platform (Kubernetes, ECS, Cloud Run, Fargate) where a container image is the unit of deployment.
  • You need lightweight, fast-starting isolation for many small services on shared hardware, where full VMs would waste memory and boot time.
  • It is the wrong tool if you need strong security isolation between untrusted tenants — containers share the host kernel, so a kernel escape crosses the boundary; a VM or a sandbox like Firecracker or gVisor is the honest answer there.
  • It is overkill if you run a single monolith on one server with no scaling story — a plain systemd service or a managed platform may be simpler to operate than a container toolchain you now have to maintain.

Docker: pros and cons

Strengths

  • Kills “works on my machine” — the built image is identical across dev, CI and production, so environment-specific bugs stop hiding.
  • Extremely lightweight and fast to start compared with VMs, so density and iteration speed both improve.
  • Compose makes multi-service local environments trivial to stand up, tear down and version alongside the code.
  • Images are portable artefacts that feed directly into Kubernetes, ECS and every serious cloud platform without rework.

Trade-offs

  • Docker is not orchestration — it does not schedule, self-heal, roll out or load-balance across a fleet; you still need Kubernetes or ECS for that.
  • Shared-kernel isolation is weaker than a VM; a kernel vulnerability can cross the container boundary, so it is a poor fence between untrusted tenants.
  • Stateful workloads and data persistence need real care — volumes, backups and storage drivers are easy to get subtly wrong and lose data over.
  • Image bloat and supply-chain security are disciplines, not defaults: an unscanned, fat base image ships known CVEs and hundreds of megabytes you did not need.

Architecture

Docker builds on Linux kernel primitives: namespaces isolate what a process can see (its own process tree, network stack, mounts and hostname) and cgroups limit what it can consume (CPU, memory, I/O). A container is simply one or more processes running under those constraints on the host kernel — there is no guest OS, which is the whole reason it is lighter than a VM.

Images are immutable and layered. Each Dockerfile instruction adds a read-only layer; at runtime a thin writable layer is added on top via a copy-on-write filesystem. Because layers are content-addressed and shared between images, ten services on the same base image store that base once. Getting the layer order and the .dockerignore right is most of what makes builds fast and images small.

We design the image, not just write a Dockerfile. That means a clear boundary between build-time and run-time via multi-stage builds, a deliberate base image, explicit non-root users, and configuration injected through environment and secrets rather than baked in. The output is an artefact you can reason about — small, reproducible, and honest about what is inside it.

Performance

Container start-up is near-instant because there is no OS to boot — the process simply starts under kernel isolation. On Linux hosts, CPU and memory overhead relative to running the process natively is negligible; the container abstraction is mostly free. This is what makes containers viable for high-density hosting and fast, ephemeral test environments.

The honest caveats are I/O and non-Linux hosts. Copy-on-write storage drivers add overhead for write-heavy workloads, and heavy database I/O generally belongs on a properly configured volume — or on a managed database outside containers entirely. On macOS and Windows, Docker runs inside a lightweight VM, so bind-mount filesystem performance can be poor; we work around it with named volumes and cache strategies where it matters.

Most real performance work is on the build, not the runtime: ordering layers for cache hits, using BuildKit and cache mounts, and keeping images small so pulls and cold starts stay quick. A well-structured build is the difference between a CI pipeline that takes seconds and one that takes minutes on every commit.

Security

The first thing to be blunt about: containers share the host kernel, so isolation is weaker than a virtual machine. A kernel vulnerability exploited from inside a container can reach the host. For workloads running untrusted code or separating tenants, that is not a strong enough boundary — the right answer is a VM, or a sandboxed runtime such as gVisor or Firecracker, and we will say so.

Within that model, the discipline is supply chain and least privilege. Base images carry the vulnerabilities of everything they include, so we build on minimal or distroless images, pin versions to digests, and run scanning in CI so a known CVE fails the build. Containers run as a non-root user, with read-only root filesystems and dropped capabilities where the workload allows, and secrets are injected at runtime rather than baked into a layer where they live forever in history.

Registries are part of the perimeter too. Private registries, signed images and immutable digests stop you from silently deploying a mutated “latest”, and pinning removes the risk of a base image changing under you between builds. None of this is on by default — it is a set of habits we build into the pipeline so security is enforced, not remembered.

Scalability

Docker scales a single host well: you run more containers until you run out of CPU or memory. What it does not do is scale across hosts — there is no built-in scheduler to place containers on a fleet, restart them when a node dies, or give them stable networking. That is precisely the line where orchestration begins, and pretending Docker covers it is how teams end up with brittle scripts holding production together.

For multi-host scale we hand images to Kubernetes, Amazon ECS or a managed platform like Cloud Run or Fargate, which handle scheduling, self-healing, rolling deploys and service discovery. The Docker image is the contract between our build and their runtime; if the image is small, stateless where it should be, and correctly configured, the orchestrator’s job is straightforward.

Stateful services scale differently and deserve caution. Databases, queues and anything holding data do not horizontally scale by adding containers — they need real storage strategy, backups and often a managed service rather than a container at all. We keep state deliberately at the edges and design the containerised layer to be as stateless as the domain allows.

Docker integrations & ecosystem

The technologies we most often pair with it — each links to how we work with it.

How we work

We start from how you run and ship today — the languages, the state, the deployment target — because a good Dockerfile is shaped by where the image is going. Then we build the packaging layer deliberately: multi-stage builds, minimal bases, a Compose setup that makes local development a single command, and scanning wired into CI from the outset rather than bolted on after an audit.

We are explicit about the boundary between Docker and orchestration, and about where state lives. If you need multi-host scale we design the hand-off to Kubernetes or ECS at the same time, so the images we build are the images that run. Because we operate what we build, we optimise for the things you feel in production — small images, fast builds, secure defaults — not for a demo that looks tidy and falls over under load.

The service behind it

Delivered throughCloud Engineering

What we build with Docker

The disciplines this technology most often shows up in — from a first build to taking over and stabilising an existing one.

How we deliver

  1. 01

    Discover

    We map the system, the constraints and the business it serves — including the parts nobody documented.

    Architecture brief

  2. 02

    Architect

    Decisions get made, written down and defended before a line of production code exists.

    Decision records

  3. 03

    Build

    Short cycles against working software. You see progress in the product, not in a status deck.

    Shipping increments

  4. 04

    Operate

    Monitoring, incident response and iteration. The system is alive, so the engagement is too.

    Runbooks & SLOs

Industries we use Docker in

Domain knowledge changes what gets built. A few of the sectors we know before the first meeting.

Also in Cloud & Infrastructure

Related terms

Why teams choose us for Docker

  • We operate what we build

    Our Dockerfiles are shaped by having been paged at 3am, not by tutorials. We optimise for small images, fast builds and secure defaults because those are the things that hurt in production — and we build them in from the start rather than after an incident.

  • Senior engineers only

    You work directly with people who have containerised real systems and handed them to real orchestrators. No juniors learning on your infrastructure, and no layer of account managers between you and the person writing the build.

  • Honest about the boundary

    We will tell you plainly when Docker is not the answer — when a workload needs a VM for isolation, when your data belongs in a managed database, or when a managed platform beats bespoke tooling. Absent advice beats confident but wrong advice.

Typical timeline

  1. 01

    Assess

    We map your services, dependencies, state and deployment target, and identify where containerisation genuinely helps versus where it adds toil.

  2. 02

    Build

    We write multi-stage Dockerfiles and a Compose stack, get images small and reproducible, and wire scanning and builds into CI.

  3. 03

    Harden

    Non-root users, pinned and scanned bases, secrets handled properly, and volumes/backups designed for any stateful workloads.

  4. 04

    Hand off

    We integrate with your orchestrator (Kubernetes/ECS) or managed platform, document the build and run model, and leave your team able to operate it.

How pricing works

  • Containerisation audit and Dockerfile/Compose setup: a fixed-scope engagement to get your services building reproducibly with small, scanned images and a working local stack.
  • Ongoing platform engineering: day-rate or retained senior time for CI pipelines, orchestration hand-off (Kubernetes/ECS) and production hardening.
  • We scope from your actual stack and deployment target — no per-seat licensing on our side, and we will tell you honestly when a managed platform is cheaper than us building bespoke tooling.

Hire Docker engineers

Need Docker capacity on your own team? We embed named senior engineers into your existing team — reporting to your leads, working in your rituals — so you add capacity without a hiring cycle.

Hire Docker engineers

Common questions

What is the difference between a container and a virtual machine?

A VM includes a full guest operating system and is isolated at the hardware level by a hypervisor. A container shares the host’s kernel and is isolated with kernel features (namespaces and cgroups), so it is far lighter and faster to start — but that shared kernel also means the isolation boundary is weaker than a VM’s. Use containers for density and speed; reach for VMs when you need strong isolation between untrusted workloads.

Is Docker enough to run our application in production?

For a single service on a single host, often yes. But Docker on its own does not schedule containers across machines, restart them when a node fails, roll out new versions gradually or load-balance traffic. Once you run many containers across many hosts you need an orchestrator — Kubernetes, ECS or a managed platform — with Docker as the layer that builds the images they run.

Can we run our database in a Docker container?

You can, and it is fine for local development. In production it is a judgement call: databases are stateful, and running one in a container means taking full responsibility for volumes, backups, storage performance and upgrades. For most teams a managed database is more reliable and less work. We will size that trade-off against your actual requirements rather than defaulting either way.

How do you keep Docker images small and secure?

Multi-stage builds so the final image contains only the runtime artefact, not the toolchain; minimal or distroless base images pinned to digests; a strict .dockerignore; running as a non-root user; and vulnerability scanning wired into CI so a known CVE fails the build. Small and secure are not defaults — they are habits enforced in the pipeline, which is exactly how we build them.

Does using Docker lock us into a particular cloud?

No — that is one of its strengths. A Docker image is a portable artefact that runs unchanged on any container platform across any cloud, and on your laptop. We keep the build decoupled from the runtime so you can start on one host and adopt Kubernetes, ECS, Cloud Run or another provider later without rebuilding your packaging.

Building on Docker?

A technical conversation with the engineers who would do the work. If we are not the right fit, we will say so on the call.

Two fields required. We reply to real enquiries — no list, no sequence.