Docker gives you everything you need to build and run containers on your Linux system. Containers are similar to lightweight virtual machines. They let you create portable application images which run using your host’s operating system kernel.

You can use Docker on Debian, Fedora, CentOS and Raspbian platforms. Derivatives of those distributions will work too. Docker provides x86/x64 and ARM builds for most supported platforms. We’re using a Debian system with the apt package manager for this guide. Instructions specific to other distributions can be found in the Docker docs.

Docker Compose lets you build and run stacks of multiple containers. You create a YAML file which configures your application’s containers. You can then use a single command to start all the containers and link them together. Compose helps you separate your stack’s components into individual containerised services.

Compose is distributed independently of Docker. Install Docker before adding Compose – otherwise, Compose won’t be able to function.

RELATED: How to Use Docker to Containerize PHP and Apache

Install Docker

You can use your operating system’s package manager to install the latest Docker release. You’ll need to add Docker’s repository, update your package lists and then install Docker.


Begin by adding dependencies needed by the installation process:

sudo apt-get update
sudo apt-get install apt-transport-https ca-certificates curl gnupg lsb-release

Next, add Docker’s repository GPG key:

curl -fsSL | sudo gpg --dearmor -o /usr/share/keyrings/docker-archive-keyring.gpg

Add the repository to your sources and update your package lists:

echo "deb [arch=amd64 signed-by=/usr/share/keyrings/docker-archive-keyring.gpg] $(lsb_release -cs) stable" | sudo tee /etc/apt/sources.list.d/docker.list > /dev/null
sudo apt-get update

Now you can install Docker:

sudo apt-get install docker-ce docker-ce-cli


Add Docker’s package repository:

sudo dnf -y install dnf-plugins-core
sudo dnf config-manager --add-repo

Install Docker:

sudo dnf install docker-ce docker-ce-cli


Add Docker’s package repository:

sudo yum -y install yum-utils
sudo yum-config-manager --add-repo

Install Docker:

sudo yum install docker-ce docker-ce-cli

Using Docker Without Sudo

The Docker daemon runs as root. You must usually prefix Docker commands with sudo. This can get tedious if you’re using Docker often. Adding yourself to the docker group will let you use Docker without sudo.

sudo usermod -aG docker $USER

Once you’re in the group, logout and login again. Alternatively, run the newgrp docker command to immediately login to the updated group. You should now be able to drop sudo from Docker commands.

Testing Your Docker Installation

Now Docker’s installed, it’s time to test it’s working! You can use the minimal hello-world image.

docker run hello-world:latest

You should see a few lines of output appear in your terminal. Docker will first look for the hello-world:latest image on your machine. As it won’t exist, the image will then get pulled from the Docker Hub repository.

image of Docker "hello world" image output

Once the image has been pulled, a new container will be created from it. The container is configured to emit a basic “hello world” message and then exit. If you see the text, your Docker installation is working!

Managing the Docker Service

You can check whether Docker’s running by inspecting its service with systemctl. There are two components to consider, docker and containerd. docker is the Docker Engine daemon which the CLI sends commands to. containerd is the underlying runtime which actually runs your containers.

sudo systemctl status docker.service
sudo systemctl status containerd.service

You can manage the daemons like any other services on your system. Use systemctl stop if you want to temporarily stop Docker and free up system resources used by your containers:

sudo systemctl stop docker.service

You can restart the service with systemctl start.

Adding Docker-Compose

docker-compose is a separate binary which is best downloaded directly from the project’s GitHub releases. Most popular Linux distributions do include Compose in their package managers but it can be significantly outdated.

Head to Docker Compose’s releases page and take note of the latest version number. At the time of writing, it was 1.29.0.

Substitute the version you see instead of 1.29.0 in the command below. This will download the right binary for your system and drop it into /usr/local/bin.

sudo curl -L "$(uname -s)-$(uname -m)" -o /usr/local/bin/docker-compose

Next make the file executable:

sudo chmod +x /usr/local/bin/docker-compose

You’ll now be able to use the docker-compose command in your terminal. Try running docker-compose --version to check.

Creating a Simple Docker-Compose File

To use docker-compose you must create a docker-compose.yml file. This describes the containers which make up your application’s stack. You can specify port bindings, environment variables, networks and volumes which are used by your containers.

Containers declared in the same docker-compose.yml file automatically become part of the same stack. They’re linked together into a Docker network, so they can communicate with each other using their docker-compose.yml service names as hostnames.

Here’s a simple docker-compose.yml to run a PHP web server and a MySQL database:

version: "3"

    image: php8.0-apache
      - MYSQL_SERVER=mysql
      - MYSQL_USERNAME=root
      - MYSQL_PASSWORD=example
      - ${PORT:-80}:80
    restart: unless-stopped
    image: mysql:8.0
      - 3306
      - mysql:/var/lib/mysql
    restart: unless-stopped


You can launch both the services by running docker-compose up -d. You’ll see both images get pulled from Docker Hub. The containers will then be started. You can stop them both using docker-compose stop. Use docker-compose down to remove the containers.

The example YAML file showcases a few Docker Compose features. Containers are defined under the services node, with each container declaring its Docker image. You can pass shell environment variables into containers (environments) and setup Docker port binds (ports). Environment variables can be interpolated into strings using the ${VARIABLE:-DEFAULT} syntax. If the variable’s not set in your shell, DEFAULT will be used as the value instead. You can learn more about Docker Compose in our dedicated guide.


You can easily install Docker using the package managers of popular Linux distributions. Add the Docker repository and then install docker-ce, docker-ce-cli and These components give you everything you need to build and run your containers.

Once you’re up-and-running, you can write a Dockerfile and use docker build -t my-app:latest . to build it. Then use docker run my-app:latest to start your container.

Docker-Compose is an additional abstraction layer which makes it easier to run a “stack” of multiple containers. With Compose, you don’t need to manually run multiple commands in series. You can write a declarative YAML file and use docker-compose up to start all your containers in unison.

RELATED: What Is Docker Compose, and How Do You Use It?

Profile Photo for James Walker James Walker
James Walker is a contributor to How-To Geek DevOps. He is the founder of Heron Web, a UK-based digital agency providing bespoke software development services to SMEs. He has experience managing complete end-to-end web development workflows, using technologies including Linux, GitLab, Docker, and Kubernetes.
Read Full Bio »