Category: Web Development

  • Docker Compose in Production: A Defensible Single-Host Pattern

    Docker Compose in Production: A Defensible Single-Host Pattern

    Reviewed: 29 August 2026 · Next review: 28 February 2027
    Author: Ozlin Info Editorial Team · Human review: Lin

    Docker Compose can be a practical production option for a modest application on one well-managed server. It provides a declarative description of services, networks, volumes and runtime configuration, and Docker documents a production workflow using a base Compose file with a production-specific override (Docker Docs — Use Compose in production).

    That does not make one Compose host highly available. The host, storage and Docker daemon can remain single points of failure. If the service requires automatic rescheduling across machines, multi-node availability or sophisticated traffic management, evaluate an orchestrator or managed platform instead of implying that a restart policy solves infrastructure failure.

    Define the operating target first

    Record the service-level needs before writing YAML:

    • expected traffic and resource profile;
    • tolerable downtime and data loss;
    • backup and restore objectives;
    • public and private network paths;
    • data classification and secrets;
    • patch, release and rollback ownership;
    • monitoring and alert response; and
    • conditions that require migration beyond one host.

    For a small content site, several minutes of controlled recovery may be acceptable. A payment or safety-critical service may need a very different architecture. Compose is a packaging and lifecycle tool, not a substitute for risk assessment.

    Build immutable, reviewable images

    Production application code should normally be inside a versioned image rather than bind-mounted from a mutable source directory. Use a multi-stage Dockerfile so compilers, package managers and build-time credentials stay out of the final runtime image. Choose a small, trusted base image, install only required packages and run as a non-root user where the application permits it.

    Docker notes that tags are mutable. Pinning an image digest improves reproducibility, but it also means the team must deliberately update the digest to receive fixes. Automate notifications or pull requests rather than pinning and forgetting (Docker Docs — Building best practices).

    A defensible release records:

    • source commit and build workflow;
    • image repository, tag and digest;
    • software bill of materials or dependency inventory where appropriate;
    • vulnerability-review result and accepted exceptions;
    • configuration version and database migration; and
    • deployment and rollback evidence.

    Do not bake passwords, API keys or private certificates into an image layer. Removing a secret in a later layer does not reliably erase it from earlier image history.

    Separate development and production configuration

    Keep common service definitions in compose.yaml and apply production differences through a reviewed override such as compose.production.yaml:

    services:
      web:
        image: registry.example.test/acme-web@sha256:REPLACE_WITH_APPROVED_DIGEST
        restart: unless-stopped
        read_only: true
        tmpfs:
          - /tmp
        ports:
          - "127.0.0.1:8080:8080"
        healthcheck:
          test: ["CMD", "wget", "-qO-", "http://127.0.0.1:8080/healthz"]
          interval: 30s
          timeout: 5s
          retries: 3
          start_period: 20s
        security_opt:
          - no-new-privileges:true
        networks:
          - edge
          - app
    
      database:
        image: mysql@sha256:REPLACE_WITH_APPROVED_DIGEST
        restart: unless-stopped
        volumes:
          - db-data:/var/lib/mysql
        networks:
          - app
    
    networks:
      edge: {}
      app:
        internal: true
    
    volumes:
      db-data: {}

    This is an illustration, not a drop-in deployment. The image may not support a read-only filesystem, wget, the shown port or non-root operation. Validate the actual image and application.

    Render the combined configuration before deployment:

    docker compose -f compose.yaml -f compose.production.yaml config

    Review the output for unintended port exposure, missing variables, duplicate mounts and development flags.

    Expose the minimum network surface

    Publish only ports that genuinely need host access. If a reverse proxy on the same host is the only caller, bind the application to loopback rather than every interface. Keep databases and queues on internal networks without published host ports unless an authorised operational requirement says otherwise.

    Network separation reduces accidental reachability but is not an authorisation system. The application must still authenticate callers, authorise actions, validate input and protect transport where traffic crosses an untrusted boundary.

    Avoid privileged containers, host network mode, broad Linux capabilities and Docker socket mounts unless a reviewed use case requires them. Access to the Docker socket is effectively high-impact control of the host.

    Handle secrets according to the deployment model

    Compose can mount declared secrets into a service as files, which is generally preferable to copying them into the image or printing them in environment dumps. On standalone Compose, however, the source secret is still a host file or external resource that the operator must protect. Docker Swarm secrets add encrypted transport and at-rest handling for Swarm services; those guarantees do not automatically apply to every standalone Compose deployment (Docker Docs — Manage sensitive data with Docker secrets).

    Use restrictive host permissions or an appropriate secret manager, grant each service only the secrets it needs, avoid logging values and define rotation. Treat .env as configuration convenience, not an encrypted vault, and keep secret-bearing files out of source control and build context.

    Use health checks without confusing them with monitoring

    A health check should test whether the service can perform a small, representative local function. Compose can wait for a dependency marked service_healthy before creating a dependent service (Docker Docs — Control startup order). This helps startup sequencing, but it does not guarantee that a remote user can reach the application or that every dependency works.

    Combine container health with external availability checks, application metrics, structured logs and host monitoring. Track disk, memory, CPU, file descriptors, container restarts, certificate expiry, backup results and application-specific failures. Put retention and access controls around logs because they may contain personal or security-relevant information.

    Set memory and CPU expectations carefully. A hard limit can contain one service but can also cause abrupt failure under legitimate load. Observe real usage, preserve host capacity and test behaviour when a limit is reached.

    Separate persistent data from disposable containers

    Containers should be replaceable. Store mutable application data in named volumes, bind mounts with explicit ownership or external services. Document exactly what must be backed up: database-consistent data, uploads, configuration, certificates, encryption keys and any queue or object storage required for recovery.

    A copy of a live database directory is not automatically a valid backup. Use the database's supported logical or physical backup method, protect the result and test restoration into an isolated environment. Record recovery time and recovered data point rather than merely checking that a backup file exists.

    Named volumes do not create backups, replication or geographic resilience. They only separate data lifecycle from a particular container.

    Release one controlled change at a time

    A single-host deployment can use this sequence:

    1. build and test the image in CI;
    2. approve the image digest and configuration;
    3. take or verify the required backup;
    4. pull images without replacing running containers;
    5. run backward-compatible database migrations where possible;
    6. recreate the affected service;
    7. verify health, external behaviour, logs and data; and
    8. retain a tested rollback route.

    Docker's production guide shows rebuilding and recreating one service with docker compose build web followed by docker compose up --no-deps -d web. When deploying registry images, use the equivalent controlled pull and up flow for the exact approved reference. Understand that recreating a container can cause brief downtime on one host.

    Rollback must account for data schema. Restoring an earlier application image may fail after an irreversible migration. Prefer expand-and-contract migrations, backups and explicit compatibility windows.

    Patch the complete stack

    Rebuild images regularly with updated base images and application dependencies, then test and deploy them. Also patch the host kernel, Docker Engine, Compose plugin and reverse proxy. Schedule reboot paths and verify containers return as expected.

    Review configuration drift with docker compose config, image digests and host records. Do not use latest as an undocumented release decision, and do not enable unattended replacement of stateful services without tested compatibility and rollback.

    For help designing or reviewing a scoped web hosting deployment, see Ozlin Info's web development services or contact Ozlin Info.

    Related reading: Incident response and disaster recovery: design for evidence and recovery.


    General-information disclaimer

    This article provides general technical information only. It is not a complete architecture, security assessment, availability commitment or backup design. Production controls must reflect the actual application, images, host, data and recovery requirements.

    AI-assistance disclosure

    AI tools assisted with source discovery, outlining and copyediting. A human reviewer must validate every command, image capability, deployment assumption, service claim and publication decision before release. No uptime, security or recovery outcome is guaranteed.

    Primary sources checked

    Source access date: 29 August 2026.

  • Web Accessibility with WCAG 2.2: A Practical Delivery Guide

    Web Accessibility with WCAG 2.2: A Practical Delivery Guide

    Reviewed: 29 August 2026 · Next review: 28 February 2027
    Author: Ozlin Info Editorial Team · Human review: Lin

    Web accessibility is the practice of making digital content and functionality usable by people with a wide range of disabilities, technologies and situations. It is not a final audit checkbox. Decisions made in research, content, visual design, component design, development, procurement and maintenance all affect whether people can complete a task.

    The current W3C Recommendation is Web Content Accessibility Guidelines (WCAG) 2.2. WCAG is organised around four principles: content must be perceivable, operable, understandable and robust. A Level AA conformance claim requires every applicable Level A and Level AA success criterion to be satisfied for the full pages in scope—not an average score across selected checks (W3C — WCAG 2.2).

    WCAG is a technical standard, not a complete description of every person's experience and not, by itself, a legal opinion. An organisation should separately determine which laws, procurement rules, contracts or policies apply to its website.

    Define scope and target before changing components

    Begin with the service people need to use. Record:

    • the pages, templates, states, documents and third-party journeys in scope;
    • target users, assistive technologies and supported browsers;
    • the intended WCAG version and conformance level;
    • critical tasks such as finding information, purchasing, registering or contacting support;
    • who owns design, code, content and external widgets; and
    • how defects will be prioritised, accepted and retested.

    For a new or substantially redesigned business site, WCAG 2.2 Level AA is a sensible engineering target. It includes the earlier WCAG 2.1 criteria and adds requirements such as focus not being obscured, alternatives to dragging, minimum target size, consistent help, avoiding unnecessary repeated entry and accessible authentication. WCAG 2.2 removed the obsolete 4.1.1 Parsing criterion, although a contract or policy that explicitly names an earlier WCAG version may still require separate reporting (W3C — What's New in WCAG 2.2).

    Do not publish “WCAG compliant” based only on a home-page scanner. A formal claim has specific scope and documentation requirements, and third-party content can affect the outcome.

    Prefer native, semantic HTML

    Native elements carry established keyboard and accessibility behaviour. Use a real <button> for an action, an <a href> for navigation, labelled form controls, ordered heading levels and landmarks such as header, nav, main and footer. Add ARIA only where native HTML cannot express the required name, role, state or relationship.

    A styled div with a click handler does not automatically gain button semantics, keyboard activation, focus behaviour or disabled state. Recreating these features increases code and test burden. If a custom widget is necessary, follow the appropriate WAI-ARIA Authoring Practices pattern and test the implemented behaviour; adding a role alone does not make it accessible.

    Content also needs structure and meaning:

    • give each page a descriptive title and one clear primary heading;
    • write link text that makes sense in context;
    • provide useful alternative text for informative images and empty alt text for decorative images;
    • provide captions for prerecorded video and an appropriate transcript for audio information;
    • identify the page language and language changes; and
    • present instructions and errors in text, not colour or position alone.

    Alternative text should communicate the image's purpose in that context. It is not a keyword field and does not need to describe every visible detail.

    Design for more than one way to interact

    Every interactive task should work without a mouse. Test forward and reverse keyboard navigation, logical focus order, visible focus, modal entry and exit, menus, disclosures, validation and any custom control. Focus must not be trapped or hidden behind sticky headers, cookie banners or other author-created content.

    Colour contrast matters, but colour is only one part of perceivability. Check text, controls, focus indicators and meaningful graphical objects against the applicable criterion. Do not use colour alone to communicate an error, status or selection.

    Responsive layouts must remain usable when people enlarge text or zoom. Check narrow viewports and 400% zoom for lost content, overlapping controls and two-dimensional scrolling where the criterion does not permit it. Fixed-height cards and clipped navigation often fail before the colour palette does.

    Authentication deserves particular attention. WCAG 2.2's Accessible Authentication criterion limits cognitive function tests such as memorising or transcribing information unless an alternative or assistance is available. Support password managers and paste; do not block them in the name of security without a carefully assessed reason.

    Make forms understandable and recoverable

    Each control needs a programmatically associated, visible label. Group related radio buttons or checkboxes with fieldset and legend when appropriate. Explain required formats before they are needed and identify required fields without relying on colour alone.

    When validation fails:

    1. retain safe values the user already entered;
    2. provide a clear summary and field-specific message;
    3. associate the error with its field;
    4. move or manage focus deliberately so the error is discoverable; and
    5. tell the user how to correct it.

    For an asynchronous submission, expose the result as a programmatically determinable status message. Do not unexpectedly move focus for every small update.

    Combine tools with human evaluation

    Automated tools are useful for repeatable checks such as missing accessible names, some contrast failures and certain invalid relationships. They cannot reliably judge whether alternative text is meaningful, focus order follows the task, instructions make sense or a screen-reader experience is coherent. W3C explicitly says no tool alone can determine whether a site meets accessibility guidelines (W3C — Introduction to Web Accessibility).

    A practical test set includes:

    Method What it can reveal
    Automated rules in CI Repeatable detectable regressions across known templates
    Keyboard-only walkthrough Reachability, order, traps, focus visibility and operability
    Zoom and reflow checks Clipping, overlap, loss of content and excessive scrolling
    Screen-reader checks Names, roles, headings, landmarks, reading order, status and errors
    High-contrast or forced-colour checks Information lost when authored colours are overridden
    Content review Heading logic, link purpose, instructions, captions and alternatives
    Disabled-user evaluation Barriers, workarounds and priorities that technical inspection can miss

    Test representative pages and every distinct component or state, not just URLs selected at random. Include errors, empty results, loading, authentication, session expiry and third-party flows. W3C's Easy Checks are a useful first review but are explicitly not exhaustive (W3C — Easy Checks).

    Keep an evidence-based remediation backlog

    Record each finding with the affected task, URL or component, WCAG criterion, reproducible steps, observed and expected behaviour, severity, owner, target release and retest evidence. Prioritise barriers that block critical tasks, affect many pages or create safety, privacy or financial consequences.

    Reusable components create leverage: correcting a shared navigation, dialog, form field or error summary can remove the same barrier across many pages. Add a regression test where automation is reliable, but retain manual checks in the definition of done.

    An accessibility statement should be accurate about scope, known limitations and contact paths. It should not claim perfection or replace a working way for people to report a barrier. Give accessibility reports an owner and response process.

    Treat accessibility as ongoing quality

    Content edits, plugin updates, third-party scripts and new features can reintroduce barriers. Review accessibility during discovery and design, test components before release, run automated rules in continuous integration and schedule periodic task-based evaluation. Train the people who publish content as well as the developers who build templates.

    For help reviewing a website workflow, component library or remediation backlog, see Ozlin Info's web development services or contact Ozlin Info.

    Related reading: 10 WordPress performance checks before optimisation.


    General-information disclaimer

    This article provides general technical information only. It is not legal, regulatory, procurement or accessibility-conformance advice. A conformance claim requires evaluation of the complete defined scope against the relevant standard and may require qualified legal or accessibility advice.

    AI-assistance disclosure

    AI tools assisted with source discovery, outlining and copyediting. A human reviewer must verify every technical statement, link, service claim and publication decision before release. Automated or AI-assisted checks do not prove accessibility or WCAG conformance.

    Primary sources checked

    Source access date: 29 August 2026.