Command To Create A Docker Container

Command To Create A Docker Container

Reading time1 min
#DevOps#Containers#Cloud#Docker#DockerRun#Containerization

Mastering the Essential Command to Create a Docker Container: Beyond Basics

Modern containerization relies on speed, reproducibility, and granular control—automation at scale demands more than GUIs or simple Compose files. At the core is docker run, the CLI interface that distills container lifecycle and configuration into a precisely defined command. Ignore it at your own risk: troubleshooting emergencies, scaling batch jobs, and CI/CD workflows benefit directly from a practical grasp of docker run syntax and options.


Anatomy: docker run

Typical form:

docker run [OPTIONS] IMAGE[:TAG|@DIGEST] [COMMAND] [ARG...]

What really happens:

  1. If the image isn’t found locally, Docker pulls it (default: Docker Hub, unless overridden).
  2. A writable container layer is created atop the image.
  3. Your specified runtime config tweaks (resources, network, mounts) are applied.
  4. The container is started; PID 1 runs the given COMMAND (else default ENTRYPOINT/CMD).

Example minimal run:
Deploys an ephemeral Ubuntu shell, deleting on exit.

docker run --rm -it ubuntu:22.04 bash

Notice --rm ensures no local residue—a best practice for testing.


Essential Flags, Pragmatic Uses

FlagPurposeTypical Use-case
-dDetached mode (daemonizes process)Long-running HTTP/services
-itInteractive TTYAd-hoc shell/debugging
-pPort mapping (HOST:CONTAINER)Expose http/other ports
-eSet environment variableConfig w/o rebuild
-vBind mount or volumePersist data, config injection
--nameContainer name for scripting/consistencyAutomations, exec attach
--memory, --cpusResource limitsProduction/sandbox controls

Non-obvious tip:
--init adds a minimal init process (PID 1), handling zombie processes—essential for containers running more than a single process or subprocesses, as PID 1 in a container doesn’t forward signals and reaping unless addressed. This avoids subtle memory leaks.


Real-World: Deploying a Node.js Service

Encountered often in dev and CI pipelines. For strict build reproducibility and log persistence:

docker run -d \
  --name node-api-1 \
  -p 3100:3000 \
  -e NODE_ENV=production \
  --init \
  -v $PWD/log:/usr/app/log \
  node-app:1.19.3

Observations:

  • Tag specificity (:1.19.3) prevents silent upgrades—surprisingly common cause of “works on my machine” bugs.
  • --init defends against PID 1 signal issues.
  • -v $PWD/log persists logs for postmortem review.
  • Port mapped from 3100 (host) → 3000 (app), allowing multiple app instances on the same node.

Known issue:
If $PWD includes a symlink or resolves oddly (e.g., via certain CI runners), Docker volume mounts may fail or log errors such as:

mounts denied: 
  The path /some/symlinked/dir does not exist

Workaround: always resolve to an absolute path before script execution.


Gotcha: Environment vs. Dockerfile Defaults

Setting env vars via -e always overrides ENV declarations inside the image Dockerfile, but fails silently if you misspell names. Always double-check variable casing—it’s case-sensitive. Consider --env-file for longer lists.


Performance & Control

Resource limits aren’t always strictly enforced, particularly on macOS Docker Desktop or Windows. On bare-metal Linux:

docker run --memory="128m" --cpus="0.5" nginx:1.25.3

But on Docker Desktop (Mac), these may not have the precise effect due to VM layer overhead. For multi-tenant setups, prefer native resource isolation (cgroups) on Linux.


Process: Scaling, Scriptability

Spinning up a batch of parameterized containers:

for i in {1..5}; do
  docker run -d --name api-$i -e INSTANCE=$i ...
done

Scripted deployments should always leverage --name and unique env vars for observability. Log/monitor via docker logs or attach sidecar log shippers as required.


Networking: Bridge, Host, Custom

  • Default: bridge network, NATted traffic, isolated from host.
  • --network host: direct host network stack; faster, but unsandboxed (supported on Linux only).
  • For service meshes or custom routing: create custom networks, e.g. docker network create mynet and attach via --network mynet.

Note:
Overlapping networks or duplicate container names lead to cryptic errors (e.g., “Error response from daemon: Conflict. The container name ... is already in use by container ...”). Handle cleanup with explicit docker rm or unique scripting logic.


Summary

Mastering docker run—with all its rarely-remembered flags—unlocks more than mere container launches. Immediate troubleshooting access, reproducible releases, and fine-grained resource management follow. Deep command-line fluency is still essential for any engineer maintaining real systems, especially when automation or incident response is at stake.

Test, tune, inspect logs, and handle edge cases. For most production clusters, orchestrators like Kubernetes take over at scale, but root cause and custom workflows always rely on explicit, well-formed docker run invocations. Learn them; you’ll need them.