Frameworks & hosting / Insta UI Lab

Serve a Static UI with Docker and Nginx

A container can package a static website and its web server into a repeatable release. Learn how to organize the public files, configure directory URLs, run a local preview, inspect responses, and plan a controlled deployment.

Orange hosting card reading Small Site, Solid Deploy, with purple server shapes, a cyan container, rainbow frame, and InstaUI.com branding.

A static UI needs a dependable way to deliver its HTML, styles, scripts, and images. Docker and Nginx can package that delivery into an image that is easy to identify and move between suitable environments. The container does not change the website's basic architecture: prepared files remain prepared files. Its value is a repeatable relationship between those files and the server configuration that serves them.

This guide uses an illustrative local setup for a site with directory-based URLs. It assumes Docker is already available and that the website has been built into a public directory. For the underlying concepts, see the Docker interface deployment guide. The examples are starting points to adapt, not a claim that InstaUI.com provides container hosting.

Decide whether a container helps this deployment

A container is useful when the team already manages containerized workloads or needs the same server configuration across environments. It can give a release a concrete identity and place the public files alongside the configuration used to deliver them. That is helpful when several people need to reproduce a deployment issue.

A simple static host may be easier when the only requirement is uploading public files. Compare the maintenance you are willing to own: image updates, runtime configuration, logging, certificates, and the host itself. Choose Docker because those responsibilities fit your environment. A static site does not require a container merely because its build process used developer tools.

Prepare a deliberate public directory

Put only publishable output in the directory copied into the image. It should contain the homepage, nested page directories, compiled assets, and any sitemap or feed files. Keep source notes, environment files, editor settings, and build dependencies outside it. This boundary makes it easier to inspect what visitors can request.

Confirm that a clean route has a corresponding directory and index document. For example, the public route /about/ should have an index document inside an about directory. Keep internal page links consistent with that convention. Do not depend on a development server to invent a response for a route that has no deployed file.

Use a small image definition

The official Nginx image documentation describes copying static content into its web content directory and supplying configuration. The following illustrative Dockerfile uses that pattern. Place it next to a directory named public and the configuration file shown in the next section.

FROM nginx:stable-alpine
COPY nginx.conf /etc/nginx/conf.d/default.conf
COPY public/ /usr/share/nginx/html/

The public directory should already contain the compiled stylesheet and finished pages. This keeps the serving image focused on delivery. If a separate build stage is useful in your project, keep its output boundary equally explicit: only the final site should enter the serving stage. The deployed container should not need to install frontend packages before it can show a page.

The example uses a moving image tag for readability. For a release that must be reproduced precisely, record or pin the reviewed image digest and establish an update process. A fixed digest identifies an image; it does not remove the need to review later maintenance updates. Keep the release identifier of your own site image distinct from the base image reference.

Preserve directory URLs without application routing

Create the following illustrative nginx.conf file for the image's default server configuration. It serves ordinary files and directories, with an index document for directory requests. Adapt the port and server selection when integrating it into a larger environment.

server {
    listen 80;
    server_name _;
    root /usr/share/nginx/html;
    index index.html;

    location / {
        try_files $uri $uri/ =404;
    }
}

The important behavior is that an unknown path produces a missing-resource response. Avoid sending the homepage for every unknown route on a multi-page static site. That fallback can hide broken links and make a missing stylesheet look like an HTML response. The Nginx static interface guide explains how server behavior relates to the site's public paths.

Build and inspect a local preview

Run these illustrative commands from the directory containing the Dockerfile. The first command builds a named preview image. The second checks the Nginx configuration inside that image. Start the preview only after the configuration check succeeds.

docker build --pull -t instaui-static:preview .
docker run --rm instaui-static:preview nginx -t
docker run --rm --name instaui-preview -p 127.0.0.1:8080:80 instaui-static:preview

The port mapping explicitly uses the host's loopback address for this local preview. Open http://127.0.0.1:8080/ in the browser. The final command keeps the preview attached to the terminal, which makes its output visible; stop that preview when the review is complete. Review your own runtime's network behavior before adapting the mapping for a shared environment.

Verify responses as well as appearances

Open the homepage, a nested page, an article, and an asset directly. Reload each page at its public route. Follow navigation across sections and inspect the browser's request log for missing files. A correct homepage is not enough: nested URLs often reveal path assumptions that the first page does not exercise.

Inspect an intentionally missing address and confirm that it produces a 404 response. Check that a stylesheet is delivered as a stylesheet and that images load from the expected locations. If using command-line inspection, request headers as well as a page body. The purpose is to confirm the relationship between a requested address, the returned content, and the reported status.

Choose a meaningful readiness check

Define what a healthy release means for this particular site. A response from the homepage establishes one useful fact, but your review should also confirm a representative asset and a nested document. Choose a small, stable set of addresses that exercises the delivery paths you rely on. If a release changes those paths, update the checks with it. Keep the check lightweight enough to repeat during deployment, and make its failure message identify the address and expected result. This gives an operator a concrete starting point when a release appears online but part of the interface is missing.

Keep configuration changes reviewable

Add caching, compression, redirects, and additional headers only with a clear reason and a corresponding check. For example, a long cache lifetime requires an asset naming and update strategy that prevents old files from persisting unexpectedly. Decide whether HTML and versioned assets need different behavior. Record that decision beside the configuration.

When placing the container behind another server or gateway, document where TLS terminates and which layer owns redirects. Test the public address through that full path. A container responding correctly on a local port does not establish that the externally visible hostname, scheme, and navigation behavior are correct. The webserver planning guide helps organize these responsibilities.

Plan updates around a known release

Build a new image when the public files or serving configuration change. Give it a release identifier that the deployment process can record. Review the candidate image in the same way as the current one before switching traffic. Keep the previous working image available for the period in which a rollback may be needed.

A useful rollback plan names the image to restore and the steps that reselect it. It also identifies any external configuration that changed with the release. For a purely static site, the public files may be the main moving part, but a changed domain rule or cache policy can still affect the visitor experience. Record these together so recovery does not depend on memory.

Diagnose problems from the outside inward

If a page fails, begin with the requested public address and the observed response. Check whether the request reached the expected server, whether the server selected the intended root, and whether the file exists in that image. For styling problems, inspect the asset request before changing CSS. The wrong path and the wrong content can look similar in a browser.

Keep logs useful for these questions without treating them as a place for unnecessary sensitive data. Distinguish build-time problems from serving problems: a missing compiled stylesheet must be fixed in the output, while an incorrect root belongs in the server configuration. Rebuild after the relevant correction and repeat the failed check.

Conclusion: package an inspectable result

A dependable static deployment has a clear public directory, a small serving configuration, a known image, and a repeatable review. Docker and Nginx work well when they make those boundaries easier to operate. Finish the interface itself with the static prototype checklist, then validate the exact image that will deliver it. The release should be understandable from its files, behavior, and recorded configuration.

Follow the topic further

Keep the ideas moving

Read next.

All Insta UI Lab articles