How to install Docker in Linux
This guide installs Docker Engine, Docker CLI, containerd, Docker Buildx, and Docker Compose on Debian 13 (Trixie) using Docker's official APT repository.
Docker officially supports Debian 13 Trixie.
1. Update the System
sudo apt update
sudo apt upgrade -y
Optionally install common prerequisites:
sudo apt install -y \
ca-certificates \
curl
2. Remove Conflicting Packages
If Docker, Podman compatibility packages, containerd, or runc were previously installed from Debian repositories, remove them first.
Docker recommends removing conflicting packages including:
docker.iodocker-composedocker-docdocker-buildxpodman-dockercontainerdrunc
Run:
sudo apt remove -y \
docker.io \
docker-compose \
docker-doc \
docker-buildx \
podman-docker \
containerd \
runc
It is safe if APT reports that some of these packages are not installed.
Existing Docker data under
/var/lib/dockeris not automatically deleted when Docker packages are removed.
Install Docker from Official Repository
3. Install Docker Engine
Run the official Docker installation script:
curl -fsSL https://get.docker.com | sudo sh
This installs Docker Engine and configures Docker's package repository automatically.
4. Verify Docker Service
Check Docker:
sudo systemctl status docker
You should see:
Active: active (running)
If it is not running:
sudo systemctl start docker
Enable Docker during boot:
sudo systemctl enable docker
Enable containerd as well:
sudo systemctl enable containerd
5. Verify Docker Installation
Check the Docker version:
docker --version
More detailed information:
sudo docker version
Check daemon information:
sudo docker info
6. Run Test Container
Run Docker's hello-world container:
sudo docker run --rm hello-world
Docker should:
- Contact Docker Hub.
- Download the
hello-worldimage. - Create a container.
- Execute it.
- Print a successful installation message.
Check existing containers:
sudo docker ps -a
Check downloaded images:
sudo docker images
Docker Compose
Docker Compose is installed as the official Docker CLI plugin when you install:
docker-compose-plugin
Docker's supported command is therefore:
docker compose
rather than the older standalone:
docker-compose
Docker documents installing the Compose plugin through the package repository.
Verify:
docker compose version
Allow Current User to Run Docker
By default, Docker commands normally require sudo.
For example:
sudo docker ps
To allow your current user to run Docker without sudo, add the user to the docker group.
Create the group if necessary:
sudo groupadd docker 2>/dev/null || true
Add the current user:
sudo usermod -aG docker $USER
Apply the new group immediately:
newgrp docker
Or log out and log back in.
Test:
docker ps
Then:
docker run --rm hello-world
Security: Membership in the
dockergroup effectively provides root-equivalent privileges on a normal Docker Engine installation. Only trusted users should be added to this group.
Docker Service Management
Start Docker
sudo systemctl start docker
Stop Docker
sudo systemctl stop docker
Restart Docker
sudo systemctl restart docker
Check Status
sudo systemctl status docker
Enable at Boot
sudo systemctl enable docker
Disable at Boot
sudo systemctl disable docker
Docker Data Directory
Docker normally stores its runtime data under:
/var/lib/docker
containerd normally stores its data under:
/var/lib/containerd
Check Docker disk usage:
sudo du -sh /var/lib/docker
Or use Docker's built-in disk usage command:
docker system df
Example:
TYPE TOTAL ACTIVE SIZE
Images 10 4 4.2GB
Containers 8 3 1.1GB
Local Volumes 5 5 10GB
Build Cache 12 0 2GB
Docker Daemon Configuration
Docker daemon configuration is normally stored at:
/etc/docker/daemon.json
The file may not exist by default.
Create the directory:
sudo mkdir -p /etc/docker
Create/edit the configuration:
sudo nano /etc/docker/daemon.json
Example:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "5"
}
}
Restart Docker:
sudo systemctl restart docker
Verify:
docker info
Configure Docker Log Rotation
Without limits, container JSON log files can become very large.
A basic server configuration:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "5"
}
}
Save as:
/etc/docker/daemon.json
Restart:
sudo systemctl restart docker
This limits each container's Docker-managed log files to approximately:
50 MB × 5 files
before old files are rotated.
Existing containers may need to be recreated before new logging settings apply to them.
Example Docker Compose Application
Create a directory:
mkdir -p ~/docker/demo
cd ~/docker/demo
Create:
nano compose.yml
Example:
services:
nginx:
image: nginx:alpine
container_name: demo-nginx
ports:
- "8080:80"
restart: unless-stopped
Start:
docker compose up -d
Check:
docker compose ps
View logs:
docker compose logs
Follow logs:
docker compose logs -f
Stop:
docker compose down
Recommended Compose Directory Layout
For server deployments, a useful layout is:
/opt/docker/
├── redis/
│ ├── compose.yml
│ ├── .env
│ └── data/
│
├── nginx/
│ ├── compose.yml
│ └── config/
│
├── application-1/
│ ├── compose.yml
│ ├── .env
│ └── data/
│
└── application-2/
├── compose.yml
├── .env
└── data/
Create the root directory:
sudo mkdir -p /opt/docker
Set ownership if the current administrator should manage it:
sudo chown -R $USER:$USER /opt/docker
Common Docker Commands
List Running Containers
docker ps
List All Containers
docker ps -a
List Images
docker images
Pull an Image
docker pull redis:latest
Start Container
docker start <container>
Stop Container
docker stop <container>
Restart Container
docker restart <container>
Remove Container
docker rm <container>
Remove Image
docker rmi <image>
Container Logs
Show logs:
docker logs <container>
Follow logs:
docker logs -f <container>
Last 100 lines:
docker logs --tail 100 <container>
Follow starting from the last 100 lines:
docker logs \
--tail 100 \
-f \
<container>
Enter a Container
For containers with Bash:
docker exec -it <container> bash
For Alpine/minimal containers:
docker exec -it <container> sh
Example:
docker exec -it demo-nginx sh
Inspect Container
docker inspect <container>
Example:
docker inspect demo-nginx
Get only the IP address:
docker inspect \
-f '{{range.NetworkSettings.Networks}}{{.IPAddress}}{{end}}' \
demo-nginx
Docker Networks
List networks:
docker network ls
Create network:
docker network create backend
Inspect:
docker network inspect backend
Remove:
docker network rm backend
Docker Volumes
List volumes:
docker volume ls
Create:
docker volume create application-data
Inspect:
docker volume inspect application-data
Remove:
docker volume rm application-data
Disk Cleanup
Check Docker disk usage:
docker system df
Remove unused containers:
docker container prune
Remove unused images:
docker image prune
Remove unused networks:
docker network prune
Remove unused build cache:
docker builder prune
Clean unused Docker resources:
docker system prune
More aggressive cleanup:
docker system prune -a
Be careful with pruning commands. They can remove images and resources that are not currently attached to running containers.
Avoid running:
docker system prune -a --volumes
without verifying that unused volumes contain no important persistent data.
Docker Logs
Check Docker daemon logs:
sudo journalctl -u docker
Follow:
sudo journalctl -u docker -f
Show logs since boot:
sudo journalctl -u docker -b
containerd logs:
sudo journalctl -u containerd
Check Docker Networking
Docker bridge:
ip addr show docker0
Networks:
docker network ls
Default bridge details:
docker network inspect bridge
Firewall Considerations
Docker configures firewall rules for container networking and published ports.
For example:
ports:
- "8080:80"
can make TCP port 8080 reachable through the host depending on host networking and firewall configuration.
Docker specifically warns that published container ports can interact with or bypass some firewall rules depending on how the host firewall is configured. Review Docker's firewall guidance when operating Internet-facing hosts.
Do not assume that:
ufw deny 8080
by itself always provides the intended Docker networking policy.
For production servers, verify the effective firewall rules and limit public port publishing.
Bind Only to a Specific Host Address
Instead of:
ports:
- "6379:6379"
you can bind a service to a private IP:
ports:
- "10.10.10.20:6379:6379"
Or localhost only:
ports:
- "127.0.0.1:6379:6379"
This is useful for databases, Redis, internal APIs, and administrative interfaces.
Recommended Restart Policies
For production containers, commonly use:
restart: unless-stopped
Example:
services:
app:
image: example/app:latest
restart: unless-stopped
Other policies include:
no
always
on-failure
unless-stopped
Upgrade Docker
Update package lists:
sudo apt update
See available upgrades:
apt list --upgradable
Upgrade Docker packages:
sudo apt install \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
Docker's APT repository is then used for normal future package updates.
Verify:
docker version
docker compose version
Check Installed Docker Packages
dpkg -l | grep -E 'docker|containerd'
Typical packages:
docker-ce
docker-ce-cli
docker-buildx-plugin
docker-compose-plugin
containerd.io
Docker Version Information
docker version
Example structure:
Client:
Version: ...
Server:
Engine:
Version: ...
Compose:
docker compose version
Buildx:
docker buildx version
containerd:
containerd --version
Docker Health Check
Basic daemon test:
docker info >/dev/null && echo "Docker OK"
Container execution test:
docker run --rm hello-world
Check service:
systemctl is-active docker
Expected:
active
Check boot configuration:
systemctl is-enabled docker
Expected:
enabled
Recommended Server Configuration
A basic Debian 13 Docker host should have:
Docker Engine
Docker CLI
containerd
Docker Compose Plugin
Docker Buildx
Verify:
docker --version
docker compose version
docker buildx version
Recommended daemon configuration:
{
"log-driver": "json-file",
"log-opts": {
"max-size": "50m",
"max-file": "5"
}
}
Location:
/etc/docker/daemon.json
Then:
sudo systemctl restart docker
Quick Installation
For a fresh Debian 13 server:
sudo apt update
sudo apt install -y \
ca-certificates \
curl
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL \
https://download.docker.com/linux/debian/gpg \
-o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc
echo \
"deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/debian \
$(. /etc/os-release && echo "$VERSION_CODENAME") stable" | \
sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt update
sudo apt install -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin
sudo systemctl enable --now docker
sudo docker run --rm hello-world
Allow the current user to use Docker:
sudo usermod -aG docker $USER
Then log out and log back in, or run:
newgrp docker
Verify:
docker version
docker compose version
docker ps
Uninstall Docker
Remove Docker Engine packages:
sudo apt purge -y \
docker-ce \
docker-ce-cli \
containerd.io \
docker-buildx-plugin \
docker-compose-plugin \
docker-ce-rootless-extras
Remove unused dependencies:
sudo apt autoremove -y
Docker does not automatically delete stored images, containers, volumes, and networks when packages are uninstalled.
To completely remove Docker data:
sudo rm -rf /var/lib/docker
sudo rm -rf /var/lib/containerd
Remove repository configuration:
sudo rm -f /etc/apt/sources.list.d/docker.list
sudo rm -f /etc/apt/keyrings/docker.asc
Then:
sudo apt update
Warning: Removing
/var/lib/dockerand/var/lib/containerdpermanently deletes local Docker container data.
References
- Docker officially supports Debian 13 Trixie and documents installation through Docker's APT repository.
- The official installation includes
docker-ce,docker-ce-cli,containerd.io,docker-buildx-plugin, anddocker-compose-plugin. - Docker Compose on Debian is available through the official
docker-compose-pluginpackage and is invoked usingdocker compose.





