# Docker containerization: installation and basic usage

> A hands-on beginner's guide to Docker's container architecture, core commands, and the concepts of volumes and networking.

- Published: 2022-02-22
- Updated: 2026-09-07
- Category: Tools & Technologies
- Tags: Docker
- Reading time: 5 min read
- Source: https://www.muhammetsafak.com.tr/en/blog/docker-containerization-installation-and-basic-usage/
- Language: en-US
- Author: Muhammet Şafak

---
The first thing that confused me when I looked at Docker was that the word "virtualization" had become synonymous with VMs. In the context of VMware or VirtualBox, virtualization brings to mind a full OS image, a separate kernel, and a hypervisor keeping everything running. Docker sits in a different place: it uses a container architecture and shares the host operating system's kernel. That sharing model makes containers far lighter and faster to start than VMs.

Each container carries its own dependencies, libraries, and runtime environment inside itself. Docker acts as the layer that mediates communication between the host kernel and the container. This architectural difference is directly related to many of the practices we use today — from development environments to production deployments.

![Virtualization architectures: hypervisor vs. container comparison](/images/30019-virtualization-architectures.png)

## Installing Docker on Windows

Before getting to the installation, there are a few prerequisites. I'm installing on Windows 11 Home; the steps are similar on other editions.

You need to enable hardware virtualization in your BIOS settings. The exact option name varies by motherboard, but you're generally looking for **Hardware Assisted Virtualization** and **Data Execution Protection**. If you bought a pre-built system, these are usually already enabled.

Next, enable WSL2 support in Windows. Go to **Control Panel > Programs > Turn Windows features on or off**, check **Windows Subsystem for Linux** and **Virtual Machine Platform**, then restart. After the restart, run Windows Update — the WSL2 kernel arrives as an update.

To verify WSL status:

```bash
wsl --status
```

If you run into errors, Microsoft's [manual installation guide](https://docs.microsoft.com/en-us/windows/wsl/install-manual) walks through it step by step.

Once your environment is ready, download and install Docker Desktop from [docker.com/get-started](https://www.docker.com/get-started). You don't need to change anything during installation; the defaults work. At the end it will ask you to log out and back in, after which Docker will start automatically.

To verify the installation, run in your terminal:

```bash
docker version
```

If you see both client and server information, Docker is running. I'd also recommend creating a Docker Hub account — you'll need it to access official images and publish your own: [hub.docker.com](https://hub.docker.com/).

## Core Concepts

Clarifying three terms before jumping into commands makes everything easier.

An **Image** is a package that bundles one or more components. The operating system, libraries, application — all defined inside the image. Images are published and distributed via Docker Hub. Think of it like source code.

A **Container** is an isolated, running instance derived from an image. The image is the source code; the container is that code in execution. You can spin up as many containers as you want from the same image.

A **Docker Registry** is the software or service that stores and distributes images. Docker Hub is the most well-known public registry; you can also set up your own private registry.

## Core Commands

### Image Operations

Search for an image on Docker Hub:

```bash
docker search php
```

List only official images:

```bash
docker search --filter is-official=true php
```

Pull an image:

```bash
docker pull php
```

Use a tag to pull a specific version:

```bash
docker pull php:7.4-cli
```

List installed images:

```bash
docker images
```

Filter for a specific image:

```bash
docker images java:8
```

Remove an image:

```bash
docker rmi php
```

### Container Operations

The most common way to create a container is the `run` command. It combines pulling the image, creating the container, and starting it in one step:

```bash
docker run --name dbserver mysql
```

If the `mysql` image hasn't been pulled yet, it pulls it first, then creates and starts a container named `dbserver`.

The `-d` flag runs the container in the background (detach mode):

```bash
docker run -d mysql
```

Use `-it` to attach to the container's interactive terminal:

```bash
docker run -it --name dockerbash ubuntu
```

![Running a Docker container in interactive (-it) mode](/images/eccfa-docker-run-it.jpg)

Use `--rm` for one-off containers you want to automatically remove when they finish:

```bash
docker run --rm php php -v
```

List running containers:

```bash
docker ps
```

List all containers (including stopped ones):

```bash
docker ps -a
```

Stop a container:

```bash
docker stop dbserver
```

Remove a container:

```bash
docker rm dbserver
```

Rename a container:

```bash
docker container rename dbserver mysqlserver
```

View container logs:

```bash
docker container logs dbserver
```

Inspect container details:

```bash
docker container inspect dbserver
```

Export a container's filesystem as a tar archive:

```bash
docker container export -o /backup/db.tar dbserver
```

Port mapping with the `-p` flag — external port:internal port:

```bash
docker container create -p 3333:3306 mysql
```

Pass an environment variable with `-e`:

```bash
docker run -e MYSQL_ROOT_PASSWORD=123456 mysql
```

Attach your terminal to a container running in the background:

```bash
docker attach dbserver
```

## Volume Mapping

When you delete a container, any changes you made inside it are lost by default — a new container in its place starts fresh from the image every time. To persist data, you map a directory on the host to a directory inside the container. It's specified with the `-v` flag in the format `outsideDir:insideDir`:

A correction on terminology: what I'm doing here is not a **volume** in Docker's vocabulary — it's a **bind mount**. [As the documentation defines it](https://docs.docker.com/engine/storage/bind-mounts/), with a bind mount "a file or directory on the host machine is mounted from the host into a container", whereas with a volume Docker creates a new directory inside its own storage directory on the host and manages it itself. They are two different mechanisms; the example below is a bind mount.

```bash
docker run -v /opt/datadir:/var/lib/mysql mysql
```

In this example, MySQL's data directory is mounted to `/opt/datadir` on the host. When the container restarts, the data is still there — it isn't lost. Mounting your project folder into a container in a development environment works through exactly the same mechanism.

## Network Types

Docker has three default network types:

**Bridge**: The default network type, where each container gets its own local IP address (typically in the `172.17.0.*` range). [The documentation puts it this way](https://docs.docker.com/engine/network/drivers/bridge/): when Docker starts, a default bridge network is created automatically and newly-started containers connect to it unless otherwise specified. It provides isolation between containers while still allowing them to communicate with each other. The same page adds a caveat: the default `bridge` network is considered a legacy detail of Docker and is not recommended for production use — there you should create your own user-defined network.

```bash
docker run --network=bridge mysql
```

**None**: For containers that are completely isolated with no network connectivity to the outside world.

```bash
docker run --network=none mysql
```

**Host**: The container uses the host's network stack directly. Port mapping is no longer needed, but isolation is gone as well.

```bash
docker run --network=host mysql
```

### Creating a Custom Network

If you want containers on the same network to reach each other by name, create a user-defined network:

```bash
docker network create --driver bridge --subnet 182.18.0.1/24 --gateway 182.18.0.1 wordpress-network
```

List networks:

```bash
docker network ls
```

Remove a network:

```bash
docker network rm wordpress-network
```

Inspect network details:

```bash
docker inspect wordpress-network
```

Start a container on a specific network:

```bash
docker run --net wordpress-network mysql
```

---

Docker's real power goes beyond the individual commands I've covered here — there's Docker Compose for managing multiple containers together, and tools like Kubernetes for production environments. But getting to those steps is harder without a solid grasp of these basics. In my experience, the best way to start using Docker in a development environment is to add a `docker-compose.yml` to an existing project and define its services as containers. That hands-on experience quickly makes it clear how Docker actually works.

---

### Sources

- [Docker Docs: Bind mounts](https://docs.docker.com/engine/storage/bind-mounts/)
- [Docker Docs: Bridge network driver](https://docs.docker.com/engine/network/drivers/bridge/)
