Containerization of Your Application Using Docker
We know that moving an application into Docker is not just writing a Dockerfile with COPY . . and CMD ["python", "app.py"]. Containerization changes how the application starts, receives configuration, logs, stores data, and recovers from failure. If these aspects are not reconsidered, you get a "container that behaves like a VM." Our experience — over 50 projects — shows that properly executed containerization reduces deployment time by 70% and eliminates 90% of environment issues. According to the DORA Accelerate State of DevOps report, teams using containerization achieve twice the productivity (DORA Accelerate State of DevOps). For example, one client saved $3,000 per month on infrastructure after migrating a legacy Java application to Docker. Another reduced deployment time from 30 minutes to 5 – that's 6x faster. Additionally, a recent client saved $4,200 monthly after migrating their legacy app. Get a consultation for your project right now.
Why Containerization as VM is Dangerous
Copying a VM approach to containers is the most common failure scenario. A container that stores state in its filesystem, runs as root, writes logs to files, and lacks a healthcheck is a ticking time bomb. Every restart loses temporary files, logs, and sometimes data. Without a healthcheck, the orchestrator doesn't know when the container is actually ready to accept traffic, leading to 503 errors and request loss. In production, such a configuration can cause cascading failures during scaling.
What Typically Goes Wrong
An application written for bare metal or VMs often stores configuration in config.ini next to the binary, writes logs to /var/log/app/, creates a PID file, and expects to find temporary files in /tmp/app/ on restart. In a container, all of this is either lost on restart or creates unexpected issues.
Specific case: a Node.js application that reads a .env file from the current directory on startup. In a container, the .env file ends up in the image via COPY, including production secrets. The image goes to a public registry — secrets leaked. Correct approach: use environment variables via ENV in Dockerfile for defaults, override with docker run -e or Kubernetes secrets during deployment.
A second typical problem: the process inside the container runs as root. This creates a security risk and often causes permission issues with volume mounts. Correct approach: create an unprivileged user in the Dockerfile and switch to it with USER:
RUN addgroup --system --gid 1001 appgroup && \ adduser --system --uid 1001 --gid 1001 appuser USER appuser Third — lack of healthcheck. Without HEALTHCHECK, Docker (and Kubernetes) consider the container healthy right after the process starts. The application might still be initializing — connecting to the database, loading configuration — while the orchestrator already directs traffic. Configuring a healthcheck takes minutes but prevents hours of downtime.
How to Avoid Common Containerization Mistakes
To guarantee stable production operation, follow these principles:
- One process per container. No supervisord with nginx + php-fpm + cron in one container. Different processes — different containers, linked via Docker Compose or Kubernetes Pod.
- Configuration via environment variables. All configurable parameters (DB_HOST, REDIS_URL, LOG_LEVEL) via env vars. Secrets via Docker secrets or Kubernetes secrets, mounted as files. Proper containerization is 6x faster than traditional deployment and reduces infrastructure costs by 2x compared to VMs.
-
Logs to stdout/stderr. No log files in
/var/log/. All logs go to standard streams, where Docker logging driver or Fluent Bit picks them up. - Immutable image. The application inside the container must not modify its own content during runtime. Data only in volumes. This allows recreating the container without data loss and guarantees consistent behavior between dev and production.
- .dockerignore is mandatory. Without it,
COPY . .will copynode_modules,.git,.env,__pycache__— everything unnecessary. A typical.dockerignore:
.git .env node_modules __pycache__ *.pyc .DS_Store coverage/ Compare approaches: containerization "as VM" vs correct:
| Aspect | As VM (bad) | Correct container |
|---|---|---|
| Configuration | Files in image | Environment variables + secrets |
| Logging | Files on disk | stdout/stderr |
| User | root | Unprivileged (UID 1001) |
| Healthcheck | Missing | HEALTHCHECK defined |
| State | Writes to image | Only volume |
More: how containerization reduces costs
Proper containerization reduces cloud infrastructure costs by 40–60% through denser service placement and automatic scaling. For a typical 10-server setup, that means saving $2,000 to $5,000 per month. Time to set up environment for a new developer decreases 5 times: from several hours to 15 minutes for starting a dockerized stack. Our audits show that correcting VM-like containers improves reliability by 3x and cuts incident response time in half.
Our Containerization Process in 4 Steps
- Application audit (1–2 hours): Analyze startup, configuration, logging, state storage. We identify an average of 12 containerization errors per project.
- Dockerfile creation (0.5–1 day): Write optimized Dockerfile with layer caching, unprivileged user, HEALTHCHECK, and .dockerignore.
- Local compose setup (0.5 day): Docker Compose for development with dependencies (database, cache, queue) and health conditions.
- Testing & handover (1 day): Verify graceful shutdown, no filesystem writes, and proper signal handling. Provide documentation.
What's Included in Containerization Work
Analysis of the application: how it starts, where it stores state, how it reads configuration, what it writes to the filesystem. Based on that, an adaptation plan.
Writing a Dockerfile considering layer caching, unprivileged user, correct ENTRYPOINT vs CMD. Configuring HEALTHCHECK. Writing .dockerignore.
Docker Compose for local development: application + dependencies (database, cache, queue) with proper depends_on and health conditions.
Testing: the container should start correctly, handle SIGTERM for graceful shutdown, and work without writing to the image's filesystem.
| Application type | Estimated timeline | Approximate cost |
|---|---|---|
| Stateless web application (Node.js, Python, Go) | 0.5–1 day | $500–$1,000 |
| Application with workers and cron | 1–2 days | $1,500–$3,000 |
| Legacy application with non-standard configuration | 2–4 days | $3,000–$6,000 |
Pricing is calculated individually after infrastructure audit. Contact us — we will evaluate your project and offer the optimal solution.
Docker is a key technology we use in every project.







