DEV Community

Cover image for Docker in Production: What Changes When Containers Meet Reality?
Sreekanth Kuruba
Sreekanth Kuruba

Posted on

Docker in Production: What Changes When Containers Meet Reality?

post 8:

You run a container.

It starts successfully.

The application works.

So… is it production-ready?

Not necessarily.

The real test of a production container isn't what happens when everything works.

It's what happens when something goes wrong.

What happens when the application consumes all available memory?

What happens when the process crashes?

What happens when the application is running, but isn't actually healthy?

Where do the logs go?

How do you know something is wrong before users tell you?

And when the container fails, how do you find the actual cause?

Running Docker in production isn't just about starting containers.

It's about making them reliable, observable, manageable, and recoverable.


1. Production Starts With Boundaries

A container that works perfectly on a developer's laptop can behave very differently under production load.

Development often prioritizes:

  • Speed
  • Convenience
  • Easy debugging
  • Frequent changes

Production prioritizes:

  • Reliability
  • Predictability
  • Security
  • Observability
  • Recovery

One of the first production questions is:

What happens if this container consumes more resources than expected?

That's where resource limits come in.


2. Resource Limits – Don't Let One Container Consume Everything

Without appropriate resource limits, a container can consume more host resources than intended.

For example:

docker run \
  --memory=512m \
  --cpus=1.0 \
  nginx
Enter fullscreen mode Exit fullscreen mode

This limits the container to:

  • 512 MB memory
  • 1 CPU

Why does this matter?

Imagine one application suddenly starts consuming several gigabytes of memory.

Without appropriate limits, it could affect other workloads running on the same host.

Resource limits create boundaries between workloads.

But remember:

A resource limit doesn't fix a memory leak.

It only limits how much damage that container can cause to the host.

So now we have another question:

What if the container is running, but the application inside it is broken?


3. Health Checks – Running Doesn't Mean Healthy

One of the most important production concepts is the difference between:

Container is running

and

Application is healthy.

A container can be running while the application inside is:

  • Hung
  • Unable to connect to a database
  • Returning errors
  • Failing internal checks

Docker supports health checks.

For example:

HEALTHCHECK --interval=30s --timeout=5s \
  CMD curl -f http://localhost:8080/health || exit 1
Enter fullscreen mode Exit fullscreen mode

Now Docker can track the application's health status.

The important idea is:

Process alive ≠ application healthy

A health check only reports the container's health status. Docker does not automatically restart a container simply because it becomes unhealthy.

An orchestrator or external health-monitoring tool is needed to take further action.

Health vs. Recovery

Situation What happens
Process exits A restart policy can restart the container
Health check becomes unhealthy Docker reports the status; it doesn't automatically restart the container
Container repeatedly crashes A restart policy may keep retrying
Application is unhealthy but still running Monitoring or orchestration is needed to take further action

So what happens when the application actually crashes and exits?

That's where restart policies come in.


4. Restart Policies – What Happens After a Crash?

Applications crash.

Processes exit unexpectedly.

Production systems need a recovery strategy.

Docker provides restart policies such as:

docker run --restart=unless-stopped nginx
Enter fullscreen mode Exit fullscreen mode

Common policies include:

  • no
  • on-failure
  • always
  • unless-stopped

For example:

--restart=on-failure
Enter fullscreen mode Exit fullscreen mode

tells Docker to restart the container when it exits with a failure.

Notice the distinction:

Health check → reports health

Restart policy → reacts to container exits

A restart policy doesn't automatically fix an application that is alive but unhealthy.

And if an application crashes repeatedly, restarting it doesn't solve the underlying problem.

It simply keeps trying to recover.

Recovery and diagnosis are two different problems.

Which leads to another question:

When something fails, where is the evidence?


5. Logging – Keep the Evidence

When something fails in production, logs are often your first source of evidence.

Docker captures container output from:

stdout
stderr
Enter fullscreen mode Exit fullscreen mode

You can inspect it with:

docker logs <container>
Enter fullscreen mode Exit fullscreen mode

Follow logs in real time:

docker logs -f <container>
Enter fullscreen mode Exit fullscreen mode

And limit the output:

docker logs --tail 100 <container>
Enter fullscreen mode Exit fullscreen mode

But don't treat docker logs as your complete production logging strategy.

Docker's default json-file logging driver can grow over time and consume host disk space if log rotation isn't configured.

Production environments should consider log rotation using options such as:

max-size
max-file
Enter fullscreen mode Exit fullscreen mode

For high-volume applications, a non-blocking logging mode can also help prevent logging from affecting application performance.

Larger environments may also send logs to a centralized logging system for:

  • Log retention
  • Search and filtering
  • Centralized access
  • Alerting

Logs are your first witness. Treat them like evidence, not decoration.

They tell you what happened. But what if you want to know what is happening right now?


6. Monitoring – Know Before Users Tell You

Logs tell you what happened.

Metrics help you understand what is happening.

At minimum, monitor things such as:

  • CPU usage
  • Memory usage
  • Network activity
  • Container restarts
  • Disk usage
  • Application response time
  • Error rates

Docker provides a simple starting point:

docker stats
Enter fullscreen mode Exit fullscreen mode

This gives you a live view of container resource consumption.

But production monitoring usually goes further.

You want to know:

Is the application healthy before customers start reporting that it is broken?

That's where metrics, dashboards, and alerts become important.

But even with monitoring, failures will happen.

The next skill is knowing how to investigate them.


7. Troubleshooting – Don't Just Restart Everything

When a container isn't working, don't randomly restart everything.

Use a systematic approach.

Step 1: Check the container status

docker ps -a
Enter fullscreen mode Exit fullscreen mode

Look for:

  • Exited containers
  • Restarting containers
  • Unexpectedly stopped services

Step 2: Check the logs

docker logs <container>
Enter fullscreen mode Exit fullscreen mode

Look for:

  • Application errors
  • Configuration problems
  • Connection failures
  • Permission issues

Step 3: Inspect the container

docker inspect <container>
Enter fullscreen mode Exit fullscreen mode

Check:

  • Environment variables
  • Mounts
  • Networks
  • Restart policies
  • Health status

Step 4: Check resource usage

docker stats
Enter fullscreen mode Exit fullscreen mode

Look for:

  • High CPU
  • High memory
  • Unusual resource consumption

Step 5: Check networking

If the application cannot reach another service, verify:

  • Network configuration
  • Service/container name
  • Ports
  • DNS resolution
  • Connectivity between containers

Step 6: Check the image

Sometimes the problem isn't the container.

It's the image.

Check:

  • Image version
  • Recent changes
  • Application dependencies
  • Base image updates

The goal is to move from:

“The container isn't working.”

to:

“This specific component is failing for this specific reason.”


8. Image Versions – Know What You're Running

Consider:

FROM nginx:latest
Enter fullscreen mode Exit fullscreen mode

It looks convenient.

But latest can change over time.

The same Dockerfile may produce different results later because the underlying image changed.

Using a known version gives you more predictable deployments:

FROM nginx:1.29
Enter fullscreen mode Exit fullscreen mode

Production environments can go even further by using carefully controlled image versions or immutable image references.

The principle is simple:

Know exactly what you're deploying.


9. Smaller Images – Reduce What You Ship

Production images should contain only what the application needs.

Smaller images can provide:

  • Faster image pulls
  • Faster deployments
  • Smaller attack surface
  • Less unnecessary software

Multi-stage builds can help.

For example:

FROM node:22 AS build

WORKDIR /app
COPY . .
RUN npm ci && npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
Enter fullscreen mode Exit fullscreen mode

The build environment doesn't need to be included in the final runtime image.

This separates:

Build environment

from

Runtime environment


10. Make Containers Replaceable

Here's another important production mindset:

Containers should be replaceable, not precious.

Don't rely on manually changing files inside a running container as a permanent fix.

For example:

docker exec -it <container> bash
Enter fullscreen mode Exit fullscreen mode

can be useful for troubleshooting.

But manually editing application files inside the container creates a change that disappears when the container is replaced.

Instead:

  1. Change the configuration or code
  2. Build a new image
  3. Test it
  4. Deploy the new version
  5. Replace the old container

This makes deployments predictable and repeatable.

And this raises another important question:

What happens to data when the container disappears?


11. Separate Application Lifecycle From Data Lifecycle

Containers are usually treated as disposable.

Application data may not be.

For example:

  • Database data
  • Uploaded files
  • Application-generated persistent data

That's where Docker volumes or external storage come in.

The container can be replaced while the data remains.

This separation is important:

Application lifecycle ≠ Data lifecycle

The application can change.

The container can disappear.

The data should survive when it needs to.


12. Security Still Matters

Production reliability doesn't replace security.

The security principles from the previous article still apply:

  • Don't run applications as root when unnecessary
  • Avoid --privileged
  • Use appropriate capabilities
  • Keep images updated
  • Use seccomp and other security controls
  • Scan images
  • Limit container resources

A production container isn't secure simply because it is running.

Reliability, security, and observability have to work together.


13. A Practical Production Checklist

Before running a container in production, ask:

  • [ ] Is the image version controlled?
  • [ ] Is the container running as a non-root user where possible?
  • [ ] Are CPU and memory limits defined?
  • [ ] Is a health check configured?
  • [ ] Is an appropriate restart policy configured?
  • [ ] Is log rotation configured?
  • [ ] Are important metrics being monitored?
  • [ ] Are alerts configured for critical failures?
  • [ ] Is persistent data stored outside the container filesystem?
  • [ ] Can the container be safely replaced?
  • [ ] Is the image regularly updated and scanned?
  • [ ] Is there a documented troubleshooting process?

You don't need every advanced platform feature on day one.

But you should know what happens when something goes wrong.


Summary

Running Docker in production isn't simply:

docker run
Enter fullscreen mode Exit fullscreen mode

It's about designing for what happens after the container starts.

You need to think about:

  • Resources → How much can the container consume?
  • Health → Is the application actually working?
  • Recovery → What happens when it crashes?
  • Logs → Where is the evidence?
  • Monitoring → How do we know something is wrong?
  • Troubleshooting → How do we find the cause?
  • Images → Do we know exactly what we're deploying?
  • Data → What survives when the container disappears?
  • Security → What privileges does the workload actually need?

A container that runs successfully is only the beginning.

Production readiness starts when you ask what happens when things go wrong.


Question for You

What's the first thing you check when a Docker container fails in production — logs, resources, health status, or something else?


Next Topic

Rootless Docker & Advanced Security: Running Containers With Fewer Privileges

Top comments (0)