What happens when you create a Docker container

Creating a Docker container means taking a Docker image — a blueprint that holds an application and everything it needs to run — and turning it into an actual running process on your machine. The docker run command does this in one step: it pulls the image if you don't have it, sets up an isolated environment, starts the application inside it, and gives you a way to interact with it.

The container itself is not a full operating system. It is a lightweight wrapper around your application that uses your machine's kernel but keeps the app's files, processes, and network separate from everything else on your system. This means you can run the same image ten times and get ten independent containers, each one thinking it owns the machine.

Before you create a container, you need a Docker image. You can use an image someone else built and published (like the official Node.js image from Docker Hub), or you can build your own from a Dockerfile. This guide assumes you are starting with an existing image.

Key Takeaways

  • The docker run command creates and starts a container in one step, pulling the image first if needed.
  • You must decide whether the container should run in the foreground (where you see its output) or the background (detached mode), and whether it needs access to your terminal.
  • Port mapping connects a port on your machine to a port inside the container so you can reach the application from outside.
  • Volume mounting lets the container read and write files on your machine, persisting data even after the container stops.
  • Environment variables and named containers make containers easier to manage and configure without editing commands each time.

The basic docker run command and what each part does

The simplest form is docker run image-name, where image-name is the name of the image you want to run. If you have the official Ubuntu image, you would type docker run ubuntu. Docker checks whether you have that image locally; if not, it downloads it from Docker Hub. Then it creates a new container and starts the main process inside it.

By default, docker run attaches your terminal to the container's input and output. This means you see what the container prints, and you can type commands into it if the application accepts them. When the main process inside the container stops or exits, the container stops too — but it is not deleted, just halted.

If the image is large or you do not have it yet, the first run takes longer because Docker has to download it. Subsequent runs with the same image are much faster because Docker reuses what it already has.

Running a container in the foreground versus detached mode

Foreground mode is the default. Your terminal stays connected to the container, you see all its output in real time, and you can send input to it. This is useful when you are testing something or need to watch what is happening. To stop the container, you press Ctrl+C or the application exits on its own.

Detached mode runs the container in the background. You add the -d flag: docker run -d image-name. Docker prints the container's ID and returns your prompt immediately. The container keeps running even after you close your terminal. This is how you run services that should stay up all the time — a web server, a database, a background worker.

You can check on a detached container later with docker ps (which lists running containers) or docker logs container-id (which shows what it has printed). If you need to interact with it, you can use docker exec to run a command inside the running container.

Mapping ports so you can reach the application from outside the container

By default, a container is isolated from the network. If you run a web server inside a container on port 8080, you cannot reach it by visiting localhost:8080 on your machine — the port is only visible inside the container.

Port mapping connects a port on your machine to a port inside the container. The flag is -p machine-port:container-port. For example, docker run -d -p 3000:8080 my-web-app means "listen on port 3000 on my machine, and forward traffic to port 8080 inside the container." Now you can visit localhost:3000 in your browser and reach the application.

You can map multiple ports on the same container. docker run -d -p 3000:8080 -p 5432:5432 my-app maps port 3000 on your machine to 8080 in the container, and port 5432 on your machine to 5432 in the container. This is common when a container runs both a web server and a database.

Mounting volumes to persist data and access files

A container's filesystem is temporary. When the container stops, any files it created inside itself are still there, but they disappear when you delete the container. If you need data to survive, you must store it outside the container — on your machine's disk.

Volume mounting connects a folder on your machine to a folder inside the container. The flag is -v machine-path:container-path. For example, docker run -d -v /home/user/data:/app/data my-app means "the folder /home/user/data on my machine is the same as /app/data inside the container." When the application writes to /app/data, the files actually land on your machine. When the container stops, the files remain.

You can also use a named volume, which Docker manages for you instead of pointing to a specific folder. docker run -d -v my-data:/app/data my-app creates or reuses a volume called my-data. This is cleaner if you do not care where Docker stores it physically, only that the data persists.

Setting environment variables and naming your container

Applications often need configuration — a database password, an API key, a debug flag. Instead of hardcoding these into the image, you pass them as environment variables when you create the container. The flag is -e VARIABLE=value. For example, docker run -d -e DATABASE_URL=postgres://localhost -e DEBUG=true my-app sets two variables that the application can read.

By default, Docker assigns each container a random ID. You can give it a human-readable name with --name. docker run -d --name my-web-server -p 3000:8080 my-app creates a container you can refer to as my-web-server instead of a long ID. You can then use docker stop my-web-server or docker logs my-web-server without looking up the ID.

A realistic example combining several flags: docker run -d --name api-server -p 8000:3000 -e NODE_ENV=production -e API_KEY=secret123 -v /home/user/logs:/app/logs my-node-api. This creates a detached container named api-server, maps port 8000 on your machine to port 3000 in the container, sets two environment variables, mounts a volume for logs, and runs the my-node-api image.

Checking what containers exist and stopping them

docker ps shows all running containers. It displays the container ID, the image it came from, the command it is running, when it started, and the port mappings. docker ps -a shows all containers, including ones that have stopped.

To stop a running container, use docker stop container-name-or-id. The container shuts down gracefully, giving the application time to clean up. To remove a stopped container entirely, use docker rm container-name-or-id. To remove an image you no longer need, use docker rmi image-name.

If a container is misbehaving and will not stop, docker kill forces it to stop immediately, though this can leave things in an inconsistent state. Use it only when docker stop does not work.

Frequently Asked Questions

What is the difference between an image and a container?

An image is a static blueprint — a file that contains the application code, libraries, and configuration. A container is a running instance of that image. You can create many containers from one image, and each one is independent. Think of an image as a recipe and a container as a cake you baked from that recipe.

Do I need to download the image before running docker run?

No. If you do not have the image locally, docker run downloads it automatically from Docker Hub (or wherever it is configured to look). The first run takes longer because of the download, but subsequent runs reuse the cached image.

How do I see what a running container is printing?

If the container is running in detached mode, use docker logs container-name to see everything it has printed so far. Add -f to follow the logs in real time: docker logs -f container-name. Press Ctrl+C to stop following.

Can I run a command inside a container that is already running?

Yes, with docker exec. For example, docker exec my-container bash opens a bash shell inside the running container so you can explore or debug. docker exec my-container ls /app runs a single command and shows the output.

What happens to my data if I delete a container?

Any files the container created inside itself are lost. Files stored in mounted volumes or named volumes remain on your machine. This is why volumes are important for databases, logs, and anything else you need to keep after the container is gone.