Run Docker on Linux Without Docker Desktop


Here's how to run Docker on Linux without Docker Desktop.

This essentially follows the official docker docs guide.

Docker Desktop is an easy way to run docker for your dev machine. It comes bundled with Docker Engine. That's the thing that you really need. So, if you don't want that gui hanging around, cluttering up your window space, run docker engine as a daemon from your terminal.

Here's how:

Removed potential conflicts

Docker comes in various shapes, possibly even already installed on your Linux system. Remove this other packages, because they might conflict with running Docker Engine:

for pkg in docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc; do sudo apt remove $pkg; done

Access the package

Second, set up your package manager, such as apt, to access the docker engine packages:

# Add Docker's official GPG key:
sudo apt update
sudo apt install ca-certificates curl
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 the repository to Apt sources:
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 update

Install docker engine

Finally, install Docker Engine (ie, docker-ce):

sudo apt install docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

Excited yet?

Test install

Finally, test that docker engine is installed and running by typing:

sudo docker run hello-world

If successful, you should get some output like this:

❯ sudo docker run hello-world
Unable to find image 'hello-world:latest' locally
latest: Pulling from library/hello-world
e6590344b1a5: Pull complete
Digest: sha256:dd01f97f252193ae3210da231b1dca0cffab4aadb3566692d6730bf93f123a48
Status: Downloaded newer image for hello-world:latest

Hello from Docker!
This message shows that your installation appears to be working correctly.
...

You did it. Now you should be able to do real Docker stuff.

Test starting container

Pull your image and start your container:

docker pull postgres
# 1st time
docker run -d --name some-postgres -e POSTGRES_USER=postgres -e POSTGRES_PASSWORD=postgres -p 5432:5432 postgres
# 2nd time
docker start some-postgres

Optional: Previous Docker Desktop

If you've previously-installed Docker Desktop, you could have an additional hurdle. It is possible that when you try to start your container, you'll get a message like this:

Cannot connect to the Docker daemon at unix:///home/jaketrent/.docker/desktop/docker.sock. Is the docker daemon running?
Error: failed to start containers: some-postgres

Note that command is attempting to start your container on the Docker Desktop socket. This is not where our Docker Engine (non-Desktop) is running.

See the status:

❯ sudo systemctl status docker
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2025-06-17 10:30:39 MDT; 14min ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 19260 (dockerd)
      Tasks: 74
     Memory: 802.9M
        CPU: 12.251s
     CGroup: /system.slice/docker.service
● docker.service - Docker Application Container Engine
     Loaded: loaded (/lib/systemd/system/docker.service; enabled; vendor preset: enabled)
     Active: active (running) since Tue 2025-06-17 10:30:39 MDT; 14min ago
TriggeredBy: ● docker.socket
       Docs: https://docs.docker.com
   Main PID: 19260 (dockerd)
      Tasks: 74
     Memory: 802.9M
        CPU: 12.251s
     CGroup: /system.slice/docker.service
             ├─19260 /usr/bin/dockerd -H fd:// --containerd=/run/containerd/containerd.sock
             ├─24107 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 5672 -container-ip 172.17.0.2 -container-port 5672 -use-listen-fd
             ├─24114 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 5672 -container-ip 172.17.0.2 -container-port 5672 -use-listen-fd
             ├─24122 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 15672 -container-ip 172.17.0.2 -container-port 15672 -use-listen-fd
             ├─24132 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 15672 -container-ip 172.17.0.2 -container-port 15672 -use-listen-fd
             ├─24487 /usr/bin/docker-proxy -proto tcp -host-ip 0.0.0.0 -host-port 5432 -container-ip 172.17.0.3 -container-port 5432 -use-listen-fd
             └─24494 /usr/bin/docker-proxy -proto tcp -host-ip :: -host-port 5432 -container-ip 172.17.0.3 -container-port 5432 -use-listen-fd

Jun 17 10:30:39 jakeangel dockerd[19260]: time="2025-06-17T10:30:39.119342724-06:00" level=warning msg="Error (Unable to complete atomic operation, key modified) deleting >
Jun 17 10:30:39 jakeangel dockerd[19260]: time="2025-06-17T10:30:39.183709215-06:00" level=info msg="Loading containers: done."
Jun 17 10:30:39 jakeangel dockerd[19260]: time="2025-06-17T10:30:39.204888467-06:00" level=info msg="Docker daemon" commit=45873be containerd-snapshotter=false storage-dri>
Jun 17 10:30:39 jakeangel dockerd[19260]: time="2025-06-17T10:30:39.204913940-06:00" level=info msg="Initializing buildkit"
Jun 17 10:30:39 jakeangel dockerd[19260]: time="2025-06-17T10:30:39.205038488-06:00" level=warning msg="CDI setup error /var/run/cdi: failed to monitor for changes: no suc>
Jun 17 10:30:39 jakeangel dockerd[19260]: time="2025-06-17T10:30:39.205042784-06:00" level=warning msg="CDI setup error /etc/cdi: failed to monitor for changes: no such fi>
Jun 17 10:30:39 jakeangel dockerd[19260]: time="2025-06-17T10:30:39.231441685-06:00" level=info msg="Completed buildkit initialization"
Jun 17 10:30:39 jakeangel dockerd[19260]: time="2025-06-17T10:30:39.236527127-06:00" level=info msg="Daemon has completed initialization"
Jun 17 10:30:39 jakeangel dockerd[19260]: time="2025-06-17T10:30:39.236591792-06:00" level=info msg="API listen on /run/docker.sock"
Jun 17 10:30:39 jakeangel systemd[1]: Started Docker Application Container Engine.

See that the socket that Docker Engine is running on is /run/docker.sock.

If you have multiple docker environments, they are under different contexts. You can see them with this command:

❯ docker context ls
NAME                TYPE                DESCRIPTION                               DOCKER ENDPOINT
default             moby                Current DOCKER_HOST based configuration   unix:///var/run/docker.sock
desktop-linux *     moby                Docker Desktop                            unix:///home/jaketrent/.docker/desktop/docker.sock

The context with the * is the current context. Switch contexts with:

docker context use default

Optional: Post-install on Linux

It is possible that you'll want to follow the optional post-install setup instructions for Linux. I did these as a part of getting my system set up right, but the docs indicate that they're optional.

Create a new user group called docker:

sudo groupadd docker

Add your current user to that group:

sudo usermod -aG docker $USER

Load the members of that new user group without restarting:

newgrp docker

Check which groups your user has:

groups

docker should now be listed amongst the others.

The instructions also give details on how to make the docker daemon start on system boot. I don't like this. I'd rather manually start the system hog so I can pay attention to when it's running and only run it when necessary.