---
title: "Docker"
description: "A guide on Docker."
---

# Docker

Docker allows users to easily run applications in separate, isolated containers.

Before you install Docker, make sure you consider the following security implications and firewall incompatibilities.

- If you use ufw or firewalld to manage firewall settings, be aware that when you expose container ports using Docker, these ports bypass your firewall rules. For more information, refer to [Docker and ufw](https://docs.docker.com/engine/network/packet-filtering-firewalls/#docker-and-ufw).

- Docker is only compatible with `iptables-nft` and `iptables-legacy`. Firewall rules created with `nft` are not supported on a system with Docker installed. Make sure that any firewall rulesets you use are created with `iptables` or `ip6tables`, and that you add them to the `DOCKER-USER` chain, see [Packet filtering and firewalls](https://docs.docker.com/engine/network/packet-filtering-firewalls/).

## Installation

1. Uninstall all conflicting packages:

   ```shellsession
   sudo apt remove $(dpkg --get-selections docker.io docker-compose docker-compose-v2 docker-doc podman-docker containerd runc | cut -f1)
   ```

2. Set up Docker's apt repository:

   ```shellsession
   # Add Docker's official GPG key:
   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/ubuntu/gpg -o /etc/apt/keyrings/docker.asc
   sudo chmod a+r /etc/apt/keyrings/docker.asc

   # Add the repository to Apt sources:
   sudo tee /etc/apt/sources.list.d/docker.sources <<EOF
   Types: deb
   URIs: https://download.docker.com/linux/ubuntu
   Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
   Components: stable
   Architectures: $(dpkg --print-architecture)
   Signed-By: /etc/apt/keyrings/docker.asc
   EOF

   sudo apt update
   ```

   **Note:** You may wish to run `sudo apt modernize-sources` after adding third-party Apt sources.

3. Install the Docker packages:

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

4. Verify that the installation is successful by running the hello-world image:

   ```shellsession
   sudo docker run hello-world
   ```

## Docker Compose

Instead of directly running Docker commands in your terminal, most software with Docker releases have a Docker Compose file available.

1. Create a directory to store all Docker related files:

   ```shellsession
   sudo mkdir -p /opt/docker/
   cd /opt/docker/
   ```

2. Create a new `docker-compose.yaml` file and paste the code:

   ```shellsession
   sudo nano docker-compose.yaml
   ```

3. Press <kbd>Ctrl+X</kbd>, then <kbd>Y</kbd>, and finally <kbd>Enter</kbd> to save the file.

4. Download and run the software:

   ```shellsession
   sudo docker compose pull && sudo docker compose up -d
   ```

You may combine multiple services into a same `docker-compose.yaml` file, but I recommend to keep them somewhat related (e.g., a website and a database) as every service will share the same bridge network.

If you want to have multiple `docker-compose.yaml` files, store them in separate subdirectories under `/opt/docker/`.

### Example docker-compose.yaml

```yaml title="/opt/docker/teslamate/docker-compose.yaml"
services:
  teslamate:
    image: teslamate/teslamate:latest
    restart: always
    environment:
      - ENCRYPTION_KEY=secretkey #replace with a secure key to encrypt your Tesla API tokens
      - DATABASE_USER=teslamate
      - DATABASE_PASS=password #insert your secure database password!
      - DATABASE_NAME=teslamate
      - DATABASE_HOST=database
      - MQTT_HOST=mosquitto
    ports:
      - 4000:4000
    volumes:
      - ./import:/opt/app/import
    cap_drop:
      - all

  database:
    image: postgres:18-trixie
    restart: always
    environment:
      - POSTGRES_USER=teslamate
      - POSTGRES_PASSWORD=password #insert your secure database password!
      - POSTGRES_DB=teslamate
    volumes:
      - teslamate-db:/var/lib/postgresql

  grafana:
    image: teslamate/grafana:latest
    restart: always
    environment:
      - DATABASE_USER=teslamate
      - DATABASE_PASS=password #insert your secure database password!
      - DATABASE_NAME=teslamate
      - DATABASE_HOST=database
    ports:
      - 3000:3000
    volumes:
      - teslamate-grafana-data:/var/lib/grafana

  mosquitto:
    image: eclipse-mosquitto:2
    restart: always
    command: mosquitto -c /mosquitto-no-auth.conf
    # ports:
    #   - 1883:1883
    volumes:
      - mosquitto-conf:/mosquitto/config
      - mosquitto-data:/mosquitto/data

volumes:
  teslamate-db:
  teslamate-grafana-data:
  mosquitto-conf:
  mosquitto-data:
```

### Loopback only ports

If you're running a docker container behind a reverse proxy, you may add `127.0.0.1` in front of every network port that doesn't need to be exposed to the public Internet:

```diff lang="yaml" title="/opt/docker/teslamate/docker-compose.yaml"
services:
  teslamate:
    ...
    ports:
-      - 4000:4000
+      - 127.0.0.1:4000:4000
    ...
```

## Rootless mode

Rootless mode lets you run the Docker daemon and containers as a non-root user to mitigate potential vulnerabilities in the daemon and the container runtime.

Do not use if you need access to network ports 0 to 1023, as they require root privileges. Any mounted volume will be assigned a random `uid` and `guid`.

1. Install the required packages:

   ```shellsession
   sudo apt install -y uidmap
   ```

2. Disable and remove the system Docker service:

   ```shellsession
   sudo systemctl disable --now docker.service docker.socket
   sudo rm /var/run/docker.sock
   ```

3. Run the rootless docker installation script:

   ```shellsession
   dockerd-rootless-setuptool.sh install
   ```

## Uninstall

1. Uninstall the Docker Engine, CLI, containerd, and Docker Compose packages:

   ```shellsession
   sudo apt purge docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin docker-ce-rootless-extras
   ```

2. Images, containers, volumes, or custom configuration files on your host aren't automatically removed. To delete all images, containers, and volumes:

   ```shellsession
   sudo rm -rf /var/lib/docker
   sudo rm -rf /var/lib/containerd
   ```

3. Remove source list and keyrings:

   ```shellsession
   sudo rm /etc/apt/sources.list.d/docker.sources
   sudo rm /etc/apt/keyrings/docker.asc
   ```
