Skip to content

How to Dockerize an Application Safely

Run the app with contract, multi-step Dockerfile, user non-root, external configuration, healthcheck, volume, secret, CI and Dockerize secure test.

Author Bipida Editorial Team Published
Share this article

Dockerize is defining a replicable build and replaceable runtime, not just writing.FROMBefore Dockerfile can run, it needs to know how the program starts and stops, what configuration and dependency it needs, where the state is written, and when it's actually ready to receive traffic.

Quick answer:Inventory contract execution and dependencies, separate build and runtime and narrow the context, pin the base/dependence version and run the process non-root. Exit the config and secret, put the data in permanent storage and log on stdout/stderr. Then test build, vulnerability, signal, health, backup and rollback in CI and staging.

Step Zero: Is Docker the right choice?

Specify the problem in question: dependency conflict, environmental differences, unrepeatable release or service isolation? If the answer is simply "upgrade", network, storage and patch image costs are not justified.The Docker decision guideIt explains the criteria for selection.

Write the application contract

  • Start and exit code.
  • Port and protocol.
  • Environment/config required
  • Network and startup dependencies
  • Read/write paths and persistent data
  • health/readiness and shutdown behavior
  • Migration and rollback data

If the program only comes with SSH and manual change, first make the behavior scripted and idempotent. The container should not be dependent on an interactive terminal to start or vague downloads from the Internet.

Smaller build context

Docker daemon/buildkit reads context files for build. Large repository, backup, secret and local dependency should not be entered into context for no reason..dockerignoreThink of it as the boundary between security and performance, but ignoring the secret revealed, rotation doesn't make it unnecessary.

.git
.env
*.log
tmp/
backups/
node_modules/

This is just a sample and should be matched to the stack; some paths may be required to build your build. Before using it, make sure the necessary file is not deleted and the wildcard secret pattern does not enter the runtime required image.

Choose Base Image wisely

Consider runtime versions, CPU architecture, native library, timezone, and CA certificate. A very minimal image makes the operation difficult if the necessary debug and compatibility tool is removed. A large, unlimited image also raises the level of package and transfer.

Tag and Digest

The tag is useful for reading, but can be moved to other content. Build and promotion production must record the digest artifact. A full digest pin also requires a bot or update process; permanent stability of the base image, i.e. security patches, are not received.

Install repeatable dependencies

Enter the lockfile and package manager version of build and click the dependency step so that the cache can be used. Download The latest version will not be able to repeat any output in any build. Enter the private credential registry with build secret, no.ARGOr a permanent layer.

Multi-stage Build

The build phase has a compiler and development tools, and the runtime phase only receives the required artifact. This reduces the size and level of the runtime tool.COPY --fromIt must be accurate to prevent cache, source or secret build from entering the final image. Test the native artifact and library in the target architecture.

Layers are arranged.

Copy low-change files such as manifest dependency before the source variable to improve cache build. Do not convert multiple unrelated commands to a complex shell just to reduce the layer; readings, exit-on-error and cache are important. The temporary installation file must be managed at the same time and in a package manager manner.

User non-rooted

Run the process runtime with a specified UID/GID and limited access. Own only the required write paths; write the entire filesystem or777Do not. A down port, package install or host change should not be required during runtime. The root inside the container is not the same as the root host, but it also increases the risk of escape and mount.

File system read-only as much as possible

The code and binary should not change in runtime. Manage the temp, upload and cache required in a specified route with a quota. The read-only root filesystem reveals unwanted changes, but you must first inventory all the actual write of the program so that the production is not taken by surprise.

One process or multiple processes?

The important rule is a manageable lifecycle and responsibility; not an absolute prohibition of multiple processes. Web and worker with different scale/restart usually require separate containers. init and signal handling are important for child processes.

ENTRYPOINT and CMD

The command must send the signal to the main process and quote it predictably. The shell wrapper must correct the exit code in error and replace the child with the appropriate method. Do not run long migration blindly in any startup replica; concurrency and rollback migration must be designed.

Graceful Shutdown

The program must take the stop signal, interrupt the receipt of the new request, and complete the current task within a limited time. If the kill is immediately executed, the request, queue, or file write is half-finished. Termination grace is synchronized with the real shutdown time and is tested in the staging.

Config and Secret out of the picture.

The same image should be executed in environments with different configurations. Do not include the secret in Dockerfile, layer, Git, or log. The environment variable is not always confidential and may be seen in the inspect or crash report.

Port and Network

The container-based application listens to the appropriate interface, but only the required port is published on the host. The database and cache usually require an internal network. The container-based localhost does not refer to another container. Use the service name DNS and do not hard-code the container IP.

State and Volume

The upload, database, and artifact generated must remain separate from the writeable layer. Owner and permission volume must be consistent with user runtime. Mounting the entire host or socket runtime provides great access.

Standard log

The log is structured on stdout/stderr and is not secret; the collector is responsible for transmission and retention. Multiline stack trace and request ID must be processed. The rotation driver is essential for the disk host to be filled.

Healthcheck is correct.

The healthcheck should be fast, time-out and cost-effective. Liveness only measures process continuity; readiness to receive traffic. Depending on liveness to an external API can restart all replicas when it fails.

Resource Limit

The CPU and memory limit limit limit limit the fault range, but the random value OOM or throttling. Baseline and load test are required. See total host limits and capacity. Event OOM and throttling should be monitored; restart loop is not a treatment for capacity shortages.

Build and Run locally controlled.

docker build -t example-app:test .
docker image inspect example-app:test
docker run --rm example-app:test

The image name is a sample and the actual execution will likely require port, config, network and secret. Do not put the secret on the command line or history.

The Image Test

  • Start with a valid configuration and clear failure with a defective configuration.
  • Implementing non-root and permission routes
  • Signal and graceful shutdown.
  • health/readiness and dependency failure
  • No secret and build tools in the final image
  • Vulnerability and License Dependence
  • Volumes, architecture and reproducibility

Compose for the Integration Test

Upload the program, database and cache with temporary network and volume in CI. Prefer readiness to fixed sleep. Test data should not be connected to production. After testing, clear the resources with the name project limited; the command to delete large volume on the shared host is dangerous.

Migration database

migration must be job controlled, backup and forward/backward compatibility. Simultaneous execution by all replicas races. Image rollback after a disagreeable schema is not possible. Expand/contract and rollout are the most appropriate stages for large changes.

CI/CD and Registry

Once the image is created in CI, test and scan it, and then promote the same digest to staging and production. Build again for production may take on another dependency. The registry must have access control, retention, and artifact required for rollback.

Production Readiness

  1. Image digest and manifest release are recorded.
  2. Secret, network and volume are defined.
  3. Backup and Restore data is tested.
  4. health, log, metric and Alert are active.
  5. Resource limit and capacity are measured by load test.
  6. Code rollback and migration are practiced.
  7. Runbook has deployment and incident properties.

The server monitoring guideThe host, container and user experience signals for production.

Common Mistakes

  • Running root and mount host extensions
  • Secret is committed to Dockerfile or env.
  • The latest in production.
  • Data in the writeable layer
  • It wasn't a graceful shutdown.
  • Healthcheck is dependent on all services.
  • Migration in startup all replicas
  • Build separately for each environment

When do you need special assistance?

If the app is stateful, has multiple runtimes or migration-sensitive, a Dockerfile doesn't seem to be working enough for production.The application is Dockerized.It can design image, user, secret, volume, health, CI and reversible rollout in a single design.

Common Questions

Should each service be a separate container?

Services with independent lifecycle, scale and failure are usually separate; the standard of operational responsibility is not a formal rule.

Is the.env safe?

No, inherently; it can be committed or inspected. Permission and secret management are required.

Why isn't the container app connected to the localhost database?

Localhost is the same container; use separate database for shared service names and networks.

Should we build an image on the production server?

It's better to build, test and promote the same artifact once in CI so that production tools don't build and output differently.

What Is Docker and When Do You Really Need It?
Docker packs apps and dependencies into a repeatable image; check its benefits, limitations, and criteria for team, production, and MVP selection.