14.3.1 Single Container Deployment
A focused guide to Single Container Deployment, connecting core concepts with practical Docker and container operations.
Single container deployment refers to running a production service as one container per host, or as a single instance overall, rather than across multiple replicas behind a load balancer, a legitimate and often appropriate pattern for low-traffic services, internal tools, batch jobs, or small-scale production systems where the operational complexity of a multi-replica setup outweighs its benefits.
When a single container is the right choice
Not every production service needs the redundancy of multiple replicas. An internal admin dashboard used by a handful of employees, a low-traffic API serving a niche integration, or a single-tenant deployment with a small, well-understood user base may have availability requirements that a single, well-monitored container with automatic restart genuinely satisfies, without the added complexity of load balancing, session affinity, and multi-replica coordination.
docker run -d --name my-api --restart=unless-stopped my-api:1.4.0
The --restart=unless-stopped policy is the core resilience mechanism available to a single-container deployment: if the process crashes or the host reboots, Docker restarts the container automatically, without requiring a second replica to absorb traffic during the restart.
Health checks still matter without a load balancer
Even without a load balancer making routing decisions based on health status, a health check remains valuable for a single container, since it gives the container runtime (or an external monitoring process) a clear signal of whether the service is actually functioning, not just whether the process is alive:
HEALTHCHECK --interval=15s --timeout=5s --retries=3 \
CMD curl -f http://localhost:3000/healthz || exit 1
docker inspect --format='{{.State.Health.Status}}' my-api
A process can be running and still be unhealthy, deadlocked, or unable to reach a dependency; a health check distinguishes this state from a true crash, which a restart policy alone cannot detect.
Persisting data for a single-container service
A single-container deployment that holds state still needs the same volume and backup discipline as a multi-replica one; in fact, the absence of redundant replicas makes losing that single container's data a more direct and immediate risk:
docker run -d --name my-api -v app-data:/app/data --restart=unless-stopped my-api:1.4.0
docker run --rm -v app-data:/data:ro -v "$(pwd)":/backup alpine \
tar czf /backup/app-data-$(date +%Y%m%d).tar.gz -C /data .
With no second replica to fall back on, the backup and restore process for a single-container deployment effectively is the disaster recovery plan, since there is no redundancy to absorb a failure while a fix is applied.
Deployment without downtime for a single replica
Deploying a new version of a single-container service inherently involves replacing the only instance currently serving traffic, which means avoiding downtime requires briefly running both versions side by side during the cutover rather than stopping the old one first:
docker run -d --name my-api-new my-api:1.5.0
# verify my-api-new is healthy
docker stop my-api
docker rm my-api
docker rename my-api-new my-api
Starting the new container under a temporary name, confirming it is healthy, and only then stopping the old one minimizes the downtime window to roughly the time it takes to redirect traffic, rather than the full time it takes the new container to start and become ready.
Reverse proxy in front of a single container
A reverse proxy in front of even a single backend container is still worth running, since it provides a stable point for TLS termination, request logging, and a brief buffering layer during the cutover described above:
upstream backend {
server 127.0.0.1:3000;
}
Updating the proxy's upstream target, or briefly pointing it at a temporary container during a deployment, decouples the public-facing endpoint from the exact container currently serving it.
Monitoring becomes more critical without redundancy
With no second replica to absorb load or mask a partial failure, monitoring and alerting for a single-container deployment need to be tuned to notice problems quickly, since there is no graceful degradation path the way there might be in a multi-replica setup where one unhealthy replica is simply removed from rotation while others continue serving:
docker run -d --name my-api --restart=unless-stopped --log-driver=syslog my-api:1.4.0
*/2 * * * * docker inspect --format='{{.State.Health.Status}}' my-api | grep -q healthy || curl -X POST https://alerts.example.com/webhook -d "my-api unhealthy"
A lightweight, frequent external health check, separate from the container runtime's own health check loop, gives an independent confirmation that the single instance is actually reachable and functioning, which matters more here than in a setup with built-in redundancy.
Knowing when to outgrow single-container deployment
A single-container deployment should be revisited once the service's traffic, availability requirements, or organizational importance grow past what a single instance can reasonably absorb. Signs that the pattern has been outgrown include the service becoming a frequent single point of failure during incidents, traffic exceeding what one container's resource limits can comfortably handle, or downtime during routine deployments becoming a recurring complaint.
services:
api:
image: my-api:1.5.0
deploy:
replicas: 3
Migrating from a single container to a multi-replica setup behind a load balancer is a deliberate architectural change, not something that needs to happen by default from day one.
Common mistakes
- Running a single-container production service with no restart policy at all, leaving a crashed process down until someone notices manually.
- Treating a single-container deployment's restart policy as a substitute for backups, when a restart only recovers from a process crash, not from data loss or corruption.
- Deploying a new version by stopping the old container before the new one is confirmed healthy, turning every deployment into a guaranteed downtime window.
- Under-monitoring a single-container service because it feels low-stakes, missing the fact that with no redundancy, any undetected failure is a full outage rather than a partial one.
- Continuing to run a service as a single container well past the point where its actual traffic or importance justified multiple replicas, simply because the original setup was never revisited.
Single container deployment is a reasonable, deliberate choice for genuinely low-stakes or low-traffic services, provided it still includes a restart policy, real health checking, proper data persistence and backup, and a deployment process that avoids stopping the only running instance before its replacement is confirmed healthy.