Learn how to build, test, deploy, and maintain robust software systems.
A container packages an application together with its dependencies and configuration, so it runs the same way everywhere. The "it works on my machine" problem disappears because the machine, the dependencies, and the runtime all travel together in the container. This lesson covers what containers are, how they differ from virtual machines, how images and containers relate, how a Dockerfile builds an image in layers, and how Docker Compose runs multi-service applications during development. It ends with the security basics you should know before using containers in production.
A container is an isolated, portable environment that includes the app and everything it needs to run.
| Virtual machine | Container | |
|---|---|---|
| Isolation | Hardware virtualization + guest OS | Process/environment isolation on the host kernel |
| Startup | Slower | Fast |
| Size | Large (full OS) | Small (app + dependencies) |
| Use | Run a different OS | Run an app consistently |
An image is a packaged, immutable template. A container is a running instance of an image.
| Instruction | Purpose |
|---|---|
| FROM | The base image |
| WORKDIR | Set the working directory |
| COPY | Copy files into the image |
| RUN | Run a build command |
| ENV | Set an environment variable |
| EXPOSE | Declare a port |
| CMD | The default command |
| ENTRYPOINT | The fixed entry command |
Each instruction adds a layer. Layers are cached, so unchanged layers are reused — which is why you install dependencies before copying source code.
The build context is the files sent to the builder. A .dockerignore file excludes large or secret files (like node_modules or .env) so they are not copied into the image.
A container exposes an internal port; you map it to a host port to reach it from outside, written as host:container (for example, 3000:3000).
Configuration is passed in through environment variables, so one image can run in different environments.
A container’s filesystem is temporary. A volume is persistent storage that survives container restarts and replacement — essential for a database container.
Containers on the same network can reach each other by service name, so the web can call the api and the api can call the database.
Compose describes a multi-service application in a single file, so you can start a frontend, backend, and database together with one command during development.
A health check tells the platform whether a container is actually ready to serve traffic, so unhealthy containers can be restarted or avoided.
A multi-stage build uses one stage to compile and another, smaller stage to run, reducing the final image size.
Dependencies are installed before the source is copied, so the layer is cached when code changes.
Map the container port to a host port.
(the app is reachable at localhost:3000)
Compose starts all services at once.
(starts api and db together)