Logo
← Back to Blog

Development and optimization

Docker Notes

A practical reference for installing and using Docker, managing images and containers, working with volumes and networks, building Dockerfiles, using Docker Compose, and running CUDA containers.

These notes are organized as a command reference collected from my Docker setup and usage workflow.

Install Docker

Install from the Docker repository

Bash
# Update package information
sudo apt-get update

# Install curl and certificates
sudo apt-get install ca-certificates curl

# Create the keyring directory and add Docker's GPG key
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# Add Docker repository
echo \
  "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu \
  $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}") stable" | \
  sudo tee /etc/apt/sources.list.d/docker.list > /dev/null

sudo apt-get update

# Install Docker Engine and plugins
sudo apt-get install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Check and start the Docker service

Bash
sudo systemctl status docker
sudo systemctl start docker

Run Docker without sudo

Bash
# Method from the original note
sudo chmod 666 /var/run/docker.sock

# Alternative from the original note
sudo usermod -a -G docker <user>

Start and stop Docker

The original note compares service management using systemctl and the older service command.

Comparison of systemctl and service commands for starting, stopping, restarting, and checking a service
Systemd and SysV-style service command comparison from the original notes.
Bash
sudo systemctl start docker
sudo systemctl stop docker
sudo systemctl restart docker
sudo systemctl status docker

Images and containers

01

Image

An image can contain an operating system, packages, and other software. Images can be pulled from Docker Hub.

02

Container

When an image is run, it becomes a container.

03

Docker Hub

A registry where Docker images can be searched and pulled.

Inspect images and containers

Bash
# Search Docker Hub
docker search "keyword"

# List local images
docker images
docker image ls

# List containers
docker ps -a
docker ps

# Image history
docker image history <imageId or REPOSITORY:TAG>

# Detailed image or container information
docker inspect <image or container>

Commands with images

Pull an image

Bash
docker pull <REPOSITORY:TAG>

# Examples
docker pull ubuntu
docker pull ubuntu:latest
docker pull ubuntu:24.04

Remove an image

Bash
docker image rm <imageId>
docker image rm <REPOSITORY:TAG>

# Remove dangling images
docker image prune -f

Run an image

Bash
docker run <options> <REPOSITORY:TAG or ImageId>

docker run <options> --name <newName> \
  -h <hostName> <REPOSITORY:TAG or ImageId>

# Common examples from the note
docker run -it ubuntu:22.04
docker run -it --name testUbuntu -h ducan ubuntu:22.04
docker run -itd --name testUbuntu -h ducan 9d

# Run once, then remove the container
docker run -it --rm busybox
Common options from the note

-i keeps standard input open, -t allocates a terminal, -d runs detached, -it is interactive with a terminal, and --rm removes the container when it stops.

Save, load, and tag an image

Bash
docker save --output <filename.tar> <REPOSITORY:TAG or ImageId>

docker load -i <my_image.tar>

docker tag <image_id> <name_image:version>

Commands with containers

Inspect the operating system inside a container

Bash
cat /etc/*release

Start, attach, detach, and stop

Bash
docker start <containerId or containerName>

docker attach <containerId or containerName>

# Detach from an attached container without stopping it
Ctrl+P, Ctrl+Q

docker stop <containerId or containerName>

# From inside the container
exit

Remove a container

Bash
docker rm <containerId or containerName>
docker rm -f <containerId or containerName>

Execute a command from outside

Bash
docker exec <containerId or containerName> <command>

# Example
docker exec testUbuntu1 ls

Create an image from a container

Bash
docker commit <containerId or containerName> <newREPOSITORY:newTAG>

Check container changes

Bash
docker diff <containerId or containerName>

Logs and resource usage

Bash
# All logs
docker logs <container>

# Last N lines
docker logs --tail <length> <container>

# Follow logs in real time
docker logs -f <container>

# Resource usage
docker stats
docker stats <container>

Volumes in Docker

The original note treats a volume as persistent storage for data used by Docker containers.

Create and manage volumes

Bash
docker volume create <volumeName>

# Create a Docker managed volume backed by a host directory
docker volume create \
  --opt device=<pathToYourDirectory> \
  --opt type=none \
  --opt o=bind \
  <volumeName>

docker volume ls

docker volume inspect <volumeName>

docker volume rm <volumeName>
Location noted in the source

Docker-managed volumes are commonly stored under /var/lib/docker/volumes/.

Bind a host directory into a container

Bash
docker run -it --name <newContainerName> \
  -v <hostDirectory:containerDirectory> \
  <REPOSITORY:TAG or ImageId>

# Example
docker run -it --name C1 \
  -v /home/myn13/Documents/self-learning/docker:/home/dulieu \
  ubuntu:20.04

Share volumes from another container

Bash
docker run -it --name <containerName> \
  --volumes-from <anotherContainer> \
  ubuntu:20.04

Mount a named Docker volume

Bash
docker run -it --name <newContainerName> \
  --mount source=<dockerVolume>,target=<containerPath> \
  <REPOSITORY:TAG or ImageId>

# Alternative syntax
docker run -it -v <volumeName>:<containerPath> \
  <REPOSITORY:TAG or ImageId>

Networks in Docker

The original note identifies bridge as the default Docker network when no network is explicitly assigned.

Inspect and manage networks

Bash
docker network ls

docker network inspect <typeOfNetwork>

docker network create --driver <typeOfNetwork> <nameOfNewNetwork>

docker network rm <nameOfNetwork>

Create a container on a specific network

Bash
docker run -it --name <newContainerName> \
  --network <nameOfNetwork> \
  <imageName or imageId>

Map a host port to a container port

Bash
docker run -it --name <nameOfContainer> \
  -p <hostPort>:<containerPort> \
  <imageName or imageId>

# Example
docker run -it --name B2 -p 8888:80 busybox

Connect an existing container to a network

Bash
docker network connect <nameOfNetwork> <nameOfContainer>

# Test connectivity
ping <IP or containerName>

Dockerfile

Build an image

Bash
docker build -t myapp:latest <directoryOfCurrentDockerfile>

# Specify another Dockerfile
docker build -t myapp:latest -f ./docker/Dockerfile1 .

# Rebuild without cache
docker build --no-cache -t myapp:latest .
Flags from the note

-t assigns the image tag and -f specifies the Dockerfile path.

Docker Compose

Build services

Bash
docker compose build
docker compose build --no-cache --pull

Start services

Bash
docker compose up
docker compose up <service>
docker compose up --build

docker compose -f <composeFile> up
docker compose -f <composeFile> up --build

Stop and remove services

Bash
docker compose down
docker compose down -v
Action Command
Start everything in background docker compose up -d
Tear down completely and remove data docker compose down -v
Restart everything docker compose restart
Stop everything and keep data docker compose stop
Rebuild one service after code changes docker compose build app && docker compose up -d app
View logs of one service docker compose logs -f app
See what is running docker compose ps
Rebuild without cache and pull latest images docker compose build --no-cache --pull
Start a specific Compose file docker compose -f <compose-file> up

Using CUDA for Docker

Set up the NVIDIA container repository

Bash
distribution=$(. /etc/os-release; echo $ID$VERSION_ID) \
  && curl -fsSL https://nvidia.github.io/libnvidia-container/gpgkey | \
  sudo gpg --dearmor -o /usr/share/keyrings/nvidia-container-toolkit-keyring.gpg \
  && curl -s -L https://nvidia.github.io/libnvidia-container/$distribution/libnvidia-container.list | \
  sed 's#deb https://#deb [signed-by=/usr/share/keyrings/nvidia-container-toolkit-keyring.gpg] https://#g' | \
  sudo tee /etc/apt/sources.list.d/nvidia-container-toolkit.list

Install NVIDIA Docker support

Bash
sudo apt-get update
sudo apt-get install -y nvidia-docker2

sudo systemctl restart docker

Pull and run a CUDA image

Bash
docker pull nvidia/cuda:11.3.1-base-ubuntu20.04

docker run -it --gpus all nvidia/cuda:11.0.3-base-ubuntu20.04

Common issues

Docker does not start automatically in WSL

The original note suggests adding a boot command in /etc/wsl.conf.

/etc/wsl.conf
[boot]
command="service docker start"