Daily Docker Commands
Core Docker Tools
There are three main Docker tools you will interact with:
docker— The main command for managing the lifecycle of containers.docker-compose— Runs and coordinates multiple containers together using a YAML configuration file.docker-machine— Works with remote servers that have Docker installed, allowing you to control them from your local machine.
Listing Images and Containers
View local images
docker images
# or
docker image list
View only the image IDs:
docker images -q
List running containers
docker ps
List all containers (running and stopped)
docker ps -a
The -a flag includes stopped containers. For stopped ones, it also shows the exit code.
List only container IDs
docker ps -aq
The -q flag outputs only the hash IDs, which is useful for passing to other commands.
Running Containers
The docker run command creates a new container from an image and runs it. If the image is not available locally, Docker downloads it from Docker Hub first.
docker run imageName:tag
The tag is the version of the image — for example ubuntu:22.04.
Run a container and exit immediately
docker run ubuntu:22.04
This runs the image and exits right away because there is nothing keeping it alive. Containers only stay running as long as there is an active process inside them.
Run a command inside a container
docker run ubuntu:22.04 ls -lah
This spins up the container, runs ls -lah inside it, then stops. The ls output shows files inside the container — not your host machine.
docker run ubuntu:22.04 echo "Hello World"
Name a container with --name
Without a name, Docker assigns a random name. Use --name to set one explicitly:
docker run -d --name=mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=my-app \
-e MYSQL_USER=app-user \
-e MYSQL_PASSWORD=app-pass \
mysql:latest
Note: The
-eflag sets environment variables inside the container. Replace the example values above with your own.
What docker ps shows
CONTAINER_ID IMAGE COMMAND CREATED STATUS PORTS NAMES
CONTAINER_ID— the unique hash IDIMAGE— the image the container is based onNAMES— the container name (auto-generated or set with--name)
Inspecting Containers
docker inspect container_name_or_id
This outputs a JSON object with details about the container — networking, mounts, environment, and more.
Get the IP address using Go templates
# Get the main IP address
docker inspect --format="{{.NetworkSettings.IPAddress}}" container_name_or_id
# Get the IP address for all connected networks
docker inspect --format="{{range .NetworkSettings.Networks}}{{.IPAddress}}{{end}}" container_name_or_id
Parse the JSON output with jq
If you have jq installed, you can format and filter the output more easily:
# Pretty-print the full output
docker inspect container_name_or_id | jq
# Get the main IP address
docker inspect container_name_or_id | jq -r ".[0].NetworkSettings.IPAddress"
# Get the bridge network IP address
docker inspect container_name_or_id | jq -r ".[0].NetworkSettings.Networks.bridge.IPAddress"
The output is a JSON array, so .[0] targets the first container in that array.
Cleaning Up Containers and Images
Every docker run creates a new container. Over time, stopped containers accumulate. Clean them up regularly.
Remove a single stopped container
docker rm container_name_or_id
This only removes stopped containers — it will not touch running ones.
Remove all stopped containers
docker rm $(docker ps -aq)
$(docker ps -aq) outputs all container IDs, which are passed to docker rm.
Force remove (including running containers)
docker rm -f $(docker ps -aq)
The -f flag forces removal. Adding -v also removes any anonymous volumes attached to those containers:
docker rm -fv $(docker ps -aq)
Run a container and auto-remove it when it stops
docker run --rm ubuntu:22.04 ls -lah
The --rm flag deletes the container automatically once it finishes. You will not see it listed in docker ps -a afterward.
Remove images
Remove a specific image by its ID or name:
docker rmi image_id_or_name:tag
Remove all images at once:
docker rmi $(docker images -q)
If you get a conflict error saying an image is used by a stopped container, remove those containers first, then retry.
Interactive Containers
To run an interactive session inside a container, use the -i and -t flags together:
docker run -it ubuntu:22.04 bash
-i(--interactive) — keeps STDIN open so you can type commands-t(--tty) — allocates a terminal so you get proper output
Once inside the container:
root@abc123:/# pwd
/
root@abc123:/# whoami
root
root@abc123:/# ps aux
Notice that ps aux inside a container shows very few processes — usually just bash and ps aux itself. Containers run a single main process (PID 1). When that process exits, the container stops.
Exit the container
exit
After exiting, docker ps -a will show the container in a stopped state.
Restart a stopped container
You can restart a stopped container without re-creating it. Docker remembers the original settings:
docker start container_id_or_name
This starts it in detached mode. To restart and attach interactively:
docker stop container_id_or_name
docker start -i container_id_or_name
Port Mapping
Use -p to map a port on your host machine to a port inside the container:
docker run -it -p 80:80 ubuntu:22.04 bash
The format is -p host_port:container_port. So -p 80:80 maps your machine's port 80 to port 80 inside the container.
To use a different host port:
docker run -it -p 8080:80 ubuntu:22.04 bash
On macOS and Windows, Docker runs inside a virtualization layer. Port mapping is required to access services from your browser or host terminal.
Sharing Volumes
Use -v to share a directory between your host and the container:
docker run -it -p 80:80 -v /full/path/to/local/folder:/var/www/html ubuntu:22.04 bash
You must use the full path — relative paths like ./test are not accepted.
A convenient alternative is $(pwd) to use the current directory:
docker run -it -p 80:80 -v $(pwd):/var/www/html ubuntu:22.04 bash
When a volume is mounted, the container directory will show the contents of your host folder. Any existing files in that container directory are hidden (not deleted) by the mount.
Executing Commands in a Running Container
Use docker exec to run a command inside a container that is already running:
docker exec -it container_name bash
This is different from docker run -it:
docker run -it image_name bash— creates a new container and opens bashdocker exec -it container_name bash— opens bash inside an existing running container
This is useful for debugging or inspecting a container while it is live.
Committing Changes to a New Image
When you install something inside a running container, those changes exist only in that container. To save them as a reusable image, use docker commit.
View the diff between the base image and the container
docker diff container_name_or_id
This shows all files that were added, changed, or deleted — similar to git diff.
Commit the container as a new image
docker commit -a "Author Name" -m "Describe the change" container_name_or_id repository:tag
Example:
docker commit -a "Your Name" -m "Added nginx" abc123 myapp/nginx:0.1.0
Now you can run this new image:
docker run -it myapp/nginx:0.1.0 bash
View the history of an image
docker history image_name_or_id
This shows all the layers that make up the image.
PID 1 and Foreground Processes
Inside a container, PID 1 is the main process that keeps the container alive. If PID 1 exits, the container stops.
This matters for services like Nginx. By default, Nginx daemonizes itself (runs in the background). When you run it in a container without extra configuration, Nginx forks itself, the original process (PID 1) exits, and the container shuts down.
To prevent this, tell Nginx to run in the foreground:
echo "daemon off;" >> /etc/nginx/nginx.conf
After this, running nginx will keep the process in the foreground as PID 1, and the container will stay alive.
Run a container in detached (background) mode
The -d flag detaches the container from your terminal and runs it in the background:
docker run -d -p 80:80 myapp/nginx:0.1.0 nginx
You can then check it with docker ps.
Building Images with a Dockerfile
A Dockerfile automates the process of building an image. Instead of manually running commands and committing, you describe all the steps in a file and Docker builds the image from it.
Each line in a Dockerfile adds a layer to the image. Docker caches these layers, so builds are fast when only the later steps change.
Example Dockerfile
FROM ubuntu:22.04
RUN apt-get update && apt-get install -y nginx \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/* \
&& echo "daemon off;" >> /etc/nginx/nginx.conf
CMD ["nginx"]
FROM— the base image to start fromRUN— runs a shell command and commits the result as a new layerCMD— the default command to run when the container starts
Build the image
docker build -t myapp/nginx:0.1.0 .
-t— sets the name and tag of the resulting image.— the build context (the directory Docker uses to resolve file paths in the Dockerfile)
You can apply multiple tags in one build:
docker build -t myapp/nginx:0.1.0 -t myapp/nginx:latest .
Specify a custom Dockerfile path
If your Dockerfile has a different name or is in a different location:
docker build -f ./nginx.dockerfile -t myapp/nginx:latest .
Build command breakdown
docker build -f ./Dockerfile -t myapp/nginx:latest ./build
build— build from a Dockerfile-f ./Dockerfile— path to the Dockerfile (optional if it is namedDockerfilein the current directory)-t myapp/nginx:latest— name and tag for the image./build— the build context directory (used whenCOPYorADDreferences external files)
Run a container from the built image
docker run -d -p 80:80 myapp/nginx:0.1.0
When the Dockerfile includes a CMD, you do not need to append the command — it runs automatically. You can override it:
docker run -d -p 80:80 myapp/nginx:0.1.0 nginx
Docker Volumes
Volumes persist data beyond the lifecycle of a container. When a container is removed, its filesystem is gone — but named volumes survive.
List volumes
docker volume ls
Inspect a volume
docker volume inspect volume_name | jq
Look for the Mountpoint field, which shows where Docker stores the data on disk.
Access volumes on macOS and Windows
On macOS and Windows, Docker runs inside a virtualization layer. The /var/lib/docker path does not exist on your host machine directly. To browse volume contents, use this trick with Alpine Linux:
docker run --rm -it -v /:/vm-root alpine:latest ls -l /vm-root/var/lib/docker/volumes
This mounts the host root filesystem at /vm-root inside the Alpine container, giving you access to Docker's internal directories.
Create a named volume
docker volume create --driver=local --name=mysqldata
Remove all volumes
docker volume rm $(docker volume ls -q)
Run a container with a named volume
docker run -d --name=mysql \
-v mysqldata:/var/lib/mysql \
-e MYSQL_ROOT_PASSWORD=secret \
-e MYSQL_DATABASE=my-app \
-e MYSQL_USER=app-user \
-e MYSQL_PASSWORD=app-pass \
mysql:latest
Because the data lives in the named volume, you can stop and delete this container, then run a new one using the same volume — and all your database data will still be there.
View logs of a running container
docker logs -f container_name_or_id
The -f flag tails the log output in real time.
Docker Compose
Docker Compose lets you define and run multiple containers together using a docker-compose.yml file. Instead of typing long docker run commands with all the flags, you put everything into the YAML file and use a single command to manage it all.
Validate your configuration
docker-compose config
Start all services in detached mode
docker-compose up -d
List running services
docker-compose ps
You must run
docker-composecommands from the directory containing thedocker-compose.ymlfile.
View logs
docker-compose logs
# or follow in real time
docker-compose logs -f
Stop and remove containers
docker-compose down
This stops all services and removes the containers and networks. Volumes are not deleted — they persist across down/up cycles. To also remove volumes:
docker volume rm $(docker volume ls -q)
Networks and volumes after docker-compose up
docker network ls
docker volume ls
These commands show the networks and volumes currently active on your system.
Use a specific compose file with -f
docker-compose -f docker-compose.custom.yml up -d
Pass variables to Docker Compose
If your docker-compose.yml uses variables like ${APP_PORT}, you can set them before running:
APP_PORT=8080 docker-compose up -d
Or export them first:
export APP_PORT=8080
docker-compose up -d
Combine multiple compose files
docker-compose -f docker-compose.base.yml -f docker-compose.dev.yml up -d
Docker merges the two files, so you can separate base configuration from environment-specific overrides.
Individual Compose lifecycle steps
docker-compose build # Build images defined in the compose file
docker-compose create # Create containers without starting them
docker-compose start # Start already-created containers
docker-compose up # Build, create, and start — all in one command