Container image / container
An image is your app frozen with its whole environment; a container is one running copy of it. The cure for 'works on my machine'.
See it
What it is
A container image is a frozen snapshot of everything your app needs to run: the user-space files of a slim base distribution, the language runtime, your dependencies, your code, and the command that starts it. It is not a whole operating system. There is no kernel inside it, because containers borrow the host's kernel, and that is exactly the line between a container and a virtual machine. A container is one running copy of that image, an isolated process with its own filesystem view. Image is the recipe, container is the meal. Images are built from a Dockerfile in stacked layers, tagged, and pushed to a registry (Docker Hub, GitHub Container Registry, ECR) so any machine can pull the exact same bytes.
Reach for containers when the platform expects them (Kubernetes, AWS ECS, Google Cloud Run, Fly.io, Railway), when your app needs something a managed platform will not install for you (ffmpeg, ImageMagick, a system font, an odd Python wheel), or when you want local dev and production to be provably the same. If you are shipping a plain Next.js app to a PaaS, you probably do not need to write a Dockerfile at all.
Gotchas that bite everyone once: the filesystem inside a container is throwaway, so anything written to disk vanishes on restart unless you mount a volume or use object storage. Images bloat fast (a careless Node image can hit 1.5GB), so use multi-stage builds and copy only the production artifact into a slim final stage. The 'latest' tag is a moving target, not a version, so pin real tags or digests. And a build on an Apple Silicon laptop is arm64 by default, which will not boot on an amd64 host unless you build for the target platform.
Ask AI for it
Containerize this app with a production-grade multi-stage Dockerfile. Stage one installs dev dependencies and builds; the final stage starts from a slim base (node:22-slim or alpine), copies only the built output and production dependencies, runs as a non-root user, and sets an explicit CMD. Add a .dockerignore that excludes node_modules, .git, and local env files, expose the port via the PORT env var, add a HEALTHCHECK hitting /healthz, and write nothing to the local filesystem at runtime. Then give me the build and run commands, including the flag to build for linux/amd64 from an Apple Silicon machine.